
记一次CH343在特定情况下致ESP32启动异常情况的排查
本文由于某些原因,对其中的“故事性”情节进行了一定的改编或虚构。本文当中所提到“某款芯片出现某类问题”仅为对本人测试的样品情况进行描述。文末有两种解决方案和总结。
近日,我设计了一款以ESP32为主控芯片的物联网设备,为节省空间采用了南京沁恒的CH343芯片作USB转UART桥芯片,同时利用其RTS、DTR信号实现自动下载时序。CH343P为小巧的QFN16封装,波特率可高达6M,且具有完备的串口流控信号功能,可谓是我非常喜欢使用的一款USB转UART桥芯片(除了价格略高于CH340系列)。
根据互联网资料搜索整合,我绘制了以下的原理图连接,仔细检查后认为无问题。
考虑到设备的主3.3V电源上有大电解电容,为避免电压上升下降斜率过小引起ESP32的非预期行为,我还设计了使用独立的电源监控复位IC——SGM803S,阈值电压2.93V。
但就在焊好板子准备测试的时候……意外袭来。
非常坏时序,使我的ESP32旋转
首次上电,我在USB输入习惯性的串入一个600mA的负载开关,一旦我焊接失误引起过流,可以及时发现。(虽然这和本文无关)
连接计算机,CH343的串口设备顺利被识别到,打开Arduino IDE修改好以太网PHY的例程,点击上传按钮。随后就开始摸鱼
过了一会,程序上传完毕,但并没有见到以太网网口的灯亮起。
这里补充一下,我使用了LAN8720A作为以太网的PHY,自制模块和ESP32主控板连接:
我首先怀疑我的PHY小板焊接不良,或是FPC座子焊接不良,于是打开串口监视器查看情况,并按下复位使程序从头运行。不料,打印出来的启动日志给我迎头痛击:
1 | ets Jul 29 2019 12:21:46 |
显然ESP32进入了ISP下载模式。我早在设计的时候就想到,IO0用作时钟输入可能导致有一定概率ESP32上电时正好遇上时钟信号低电平,导致启动不成功。我直接取下连接PHY小板的排线,然后再次上电测试。
出乎意料的是,ESP32仍然进入了ISP下载模式:
1 | ets Jul 29 2019 12:21:46 |
这可令我感到大为不解:ESP32的IO0上明明什么也没接,为什么还是低电平?我为了防止IO0悬空引起问题,甚至在IO0上接了10k的上拉电阻。
谁在撅IO0啊(恼
等等……确实是什么也没接吗?
并不是。IO0引脚的连接,除了一个10k的上拉电阻连接到3.3V主电源,还有一个三极管连接到IO0,用于支持Arduino自动进入ISP下载模式的功能。
而如果DTR为低、RTS为高,此时Q2导通,IO0就会被拉低。
可是DTR在空闲状态应当是高电平啊?
这套设计几乎是100%复制了曾经多次使用的一套原理图,理论上不应当存在能够这么稳定复现的问题。但至于说为什么是“几乎”,因为这次将原先使用的CH340C更换为了更好的CH343P。
CH343P会不如CH340C稳定吗?未必,市面上使用CH343芯片的板子不计其数,为什么会出现这么稳定复现的问题?
我忽然意识到市面上许多使用CH343芯片的ESP32核心板上,并没有SGM803这一电压监控复位IC。难道说,CH343和SGM803存在兼容性问题?
想到这里,我打开示波器,准备观察上电瞬间各路信号的波形,尝试从中发现端倪。
Big Oscilloscope is Watching You(无端
为了避免CH343与计算机通信引起流控信号变化,我使用了一个移动电源为ESP32主控板供电,并将示波器探头挂到RST、IO0、RTS、DTR四个信号上,抓取上电时的波形。(测量时标注的标签有误,手写更正了一下)
我将上电时短暂的干扰尖峰对齐屏幕水平轴中心,抓取到了如下的波形。
容易注意到,RST在上电后50ms内一直处于拉低状态(受到SGM803控制,其在上电后有一个固定的延迟复位),IO0也处于低电平;而RTS在约15ms时跳变为高,DTR一直为低电平。
考虑到怀疑问题与SGM803S有关,故拆除了SGM803S,并重新抓取上电时信号波形。
可以看出,RST信号有正常的RC复位电路充电的波形,同时IO0在刚上电时呈现小斜率上升的特征,在上电约6ms后出现一个强上拉达到高电平稳定;RTS和DTR信号均在10ms后达到高电平稳定状态。此时的信号状态,足以使ESP32正常复位从Flash启动程序,实际测试也证明了拆除SGM803S后不再出现启动异常。但总不能怕噎着就饿着,我还是想找到问题的原因。
等等,虽然RTS和DTR的波形都呈现出小斜率上升,但为什么DTR信号是分两段上升的?
图中可以看到DTR信号(蓝)在上电瞬间较快地上升到1V,2ms后又出现一次较快的上升达到2V+,然后才以较小的斜率上升到高电平稳定。
那么异常情况下,DTR信号的波形如何呢?
容易看出,DTR信号(蓝)在上电瞬间同样较快地上升到1V,但持续了约15ms后迅速恢复低电平。
仔细查阅CH343的手册CH343DS1后,在其第四节引脚信息当中注意到:
也就是说,上述波形当中的DTR上电瞬间的波形变化,可能是CH343在检测外部是否有下拉电阻,若检测到,则该引脚默认的DTR功能转换为TNOW功能。该功能常用于485收发器的方向控制,空闲状态默认为低电平,这也就导致了出现问题时DTR被持续拉低的情况。
但是,DTR引脚上的下拉电阻在哪里?再次回到这张图,并不能看出其中哪里存在DTR引脚的下拉:
Q2反向导通使得电流由发射极流向集电极未免太荒谬了一点。难道是Q1的基极电流过大?的确,正常启动的时候,RTS电压是和DTR的电压几乎同步上升的,Q1由于Vbe很小基本处于截止区。
而注意到问题只发生在RST在上电时被强下拉拉低(由SGM803S提供)一定时间的条件下,这使得我把问题锁定在DTR和RST之间的互相影响。
可我看了半天,也没想明白Q1的电流如何从基极流向集电极。
理想和现实还是有差距的
此时,一位群友一语点破问题的关键:
是的,三极管存在Ibc这项电流!只不过平时由于其远小于Ice、Ibe而在大信号分析的时候将其忽略了,可它并不是不存在。由于集电极有复位IC的强下拉,故CH343上电时DTR的弱上拉电流(VIO=3.3V时约15-90uA)经由Q1的基极到集电极然后流入GND,使得CH343认为“检测到外部DTR下拉电阻”。
同时,这位群友也热心地给出了解决方案1:在DTR引脚上额外添加1K级别的较强上拉电阻到VIO,此时由于Ibc电流有限,不足以将DTR电压拉的足够低,故不会被CH343判断为“外部下拉”。
另一位群友也给出了解决方案2:把NPN三极管更换为NMOS(连接方法见图)。NMOS的Igss均在百nA级别,完全不足以影响CH343的DTR下拉检测。然而,在市售产品当中,这种使用NMOS产生自动下载时序的设计并不多见。也许是由于MOS贵一点?又或者只是照搬官方的DevkitC的自动下载三极管电路?甚至也许只是我孤陋寡闻罢了。
经过测试,两位群友的解决方案均可以解决本人遇到的问题,在此向其表示感谢。
总结一下,此次遇到的问题是在以下三个平时毫无问题的因素的巧合当中产生的:
- 相比于CH340系列,CH343的DTR引脚支持外接下拉电阻切换到第二功能,而该第二功能默态电平是低电平;
- 三极管自动下载电路会从DTR和RTS抽取一定的电流;
- SGM803S等复位IC上电时会有100ms左右的固定延时,此期间RST引脚被强下拉到地(即使不使用此类复位IC,只要RST引脚上电时有超过15ms的强下拉,即可导致该问题,包括按住复位键上电);
而在分析问题的过程中,我在分析三极管电路时习惯性地套用了三极管分析的“简化结论”而忽略了实际情况,致使未能察觉Ibe导致基极电流过大拉低DTR电压。这也是我本人今后要注意小心的问题。