Esp32串口自动下载电路,嵌入式开胃菜,你学废了么

芯片程序下载的特定状态

芯片上电都是直接执行用户程序的。 要想进行程序更新,就必须进入特定的串口下载状态。 Esp32 就是要求goio0拉低, 然后启动。 这样就进入了下载状态。

串口更新程序,是最通用的方式。但是启用这个模式大概率都需要在复位前,配置某一个或者某几个引脚。 然后复位或者要求重新上电。 这样就进入了下载状态。

串口自动下载电路

嵌入式工程师都会复用现有的资源去实现新的功能。 这个串口自动下载电路,就是这样的一个例子。cp210x是有扩展的gpio口的。但是用起来就比较特例。当然, 如果通用串口的一些引脚能够复用,那应该是更好的事情。但是, 因为功能已经被定义了。所以,需要一些辅助电路进行兼容。防止引入新的问题。 esp32串口自动下载电路

这个图来自我买的esp32-s3的小板, chip_pu 是reset, gpio0是boot。 他pdf上的真值表是错的。 我就不贴出来了。 两个三极管都是npn,只是为了好画图镜像了一下。 可没有锁存器那么复杂。

boot reset

这里把两个引脚的其他电路也贴出来。 因为如果仅仅是简单逻辑,可能就不会迷糊了那么多人。 因为三极管电路是一个数字电路。 这个纯数字电路实现不了复位下载要求的时序。

真值表分析:

DTR CTS chip_pu gpio0 原因
1 1 x x be之间没有电压差,没有电流。三极管关掉。不影响当前状态
0 0 x x be之间没有电压差,没有电流。三极管关掉。不影响当前状态
1 0 0 x chip_pu被拉低. gpio0 三极管关断
0 1 x 0 chip_pu三极管关断. gpio0 三极管打开,拉低

因为引脚上都有默认上拉电阻。所以x一般被认为1. 除非开关按下,强制为0

class ClassicReset(ResetStrategy):
    """
    Classic reset sequence, sets DTR and RTS lines sequentially.
    """

    def reset(self):
        self._setDTR(False)  # IO0=HIGH
        self._setRTS(True)  # EN=LOW, chip in reset
        time.sleep(0.1)
        self._setDTR(True)  # IO0=LOW
        self._setRTS(False)  # EN=HIGH, chip out of reset
        time.sleep(self.reset_delay)
        self._setDTR(False)  # IO0=HIGH, done

我们要把软件代码和硬件信号对齐。 这里DTR都是低有效。 所以代码里设置为true,就是拉低。 代码里设置为false,就是拉高。 嵌入式不难,但是细节多。这些看起来让人迷糊的细节,又是规范,再牛逼的人也改不了。 互联网行业喜欢造规范,但是这些迷惑人的东西,才是真正的规范。

前两句设置复位状态。然后等待0.1s, 这个等待是把复位电容里的电放光(快)。io0的电容充电到满(慢),芯片复位状态cpu是停止的。 然后设置io0为低电平。复位结束,cpu开始运行, 这时候cpu检测到io0为低电平,就进入下载状态。 注意三极管放电速度,大于电容上拉充电速度。 也就是说控制电路只保证了io0是低电平, 复位引脚是类似开漏控制, 也可以认为控制电路未连接 复位引脚自然执行的是电阻给电容充电,缓慢上升和复位结束。

最后, 把io0恢复到不控制状态。 这样就可以正常运行了。因为io0还可以有其他功能。 一直拉低就浪费了这个引脚。

总结

  1. 如果驱动注册的是modem,这个下载永远是不会成功的。 因为modem使用了这两个控制引脚。我的macos就是这么一直不成功,浪费了我一天。重装ch34x驱动以后, 驱动又注册了一个串口, 可以下载了。
  2. 如果io0输出低, 按键复位的时候, 要保证结束时io0是高电平,否则之间进入boot模式了。
  3. 和不经过三极管直接控制电路相比, 稳定性有提高,防止串口输出信号和cpu引脚,复位按键同时输出导致的打架。
  4. 但是是否真需要这么复杂, 是解决哪些历史设计不兼容,已经无从考证了。就算是一个前辈秀技术,也成了祖传逻辑。当然,很多简化的电路。也能正常运行。