ESP32 while(!Serial) / isConnected() 失效修复(Arduino)

2k 词

现象

今天在给ESP32S3烧录固件之后发现一个问题

原本的检测串口是否打开的代码失效了

1
while(!Serial);

原本代码会阻塞直到电脑打开串口监视器, 而现在则是一旦连接到电脑就跳出

排查过程

排查后发现在HWCDC.h中对于HWCDC将运算符重载为HWCDC::isCDC_Connected(), 同时HWCDC::isConnected() 也内联到HWCDC::isCDC_Connected()

而HWCDC::isCDC_Connected() 内部的逻辑是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
bool HWCDC::isCDC_Connected() {
static bool running = false;

// USB 可能被拔出
if (!isPlugged()) {
connected = false;
running = false;
// ISR中的SOF导致固件上传问题
//SOF_TIMEOUT = 5; // 拔掉时 SOF 超时
return false;
}
//else {
// SOF_TIMEOUT = 50; // 插入时 SOF 超时
//}

if (connected) {// <--若 connected 为 true 则返回 true
running = false;
return true;
}

if (running == false && !connected) { // 只启用一次!
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
}

// 这将向 CDC TX FIFO 提供数据以触发 IN_EMPTY
usb_serial_jtag_ll_txfifo_flush();
running = true;
return false;
}

这里的connected变量因为误判在上电时为True (具体原因我也不清楚)

我尝试了 pioarduino-espressif32 的很多版本的平台(55.03.311, 55.03.31-2, 54.03.21), 但是无一例外全部不行, 但是在Arduino IDE中编译的固件则没有此问题, 且以前我使用PIO编译出来的固件也没有任何问题, 所以说可能是个玄学bug(?)

解决方案

在Serial.begin()之前加一个Serial.end()

Serial.end()的实现是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void HWCDC::end() {
//Disable/clear/free tx/rx interrupt.
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
esp_intr_free(intr_handle);
intr_handle = NULL;
if (tx_lock != NULL) {
vSemaphoreDelete(tx_lock);
tx_lock = NULL;
}
setRxBufferSize(0);
setTxBufferSize(0);
if (arduino_hw_cdc_event_loop_handle) {
esp_event_loop_delete(arduino_hw_cdc_event_loop_handle);
arduino_hw_cdc_event_loop_handle = NULL;
}
HWCDC::deinit(this);
setDebugOutput(false);
connected = false; // <--此处将 connected 置为 false
}

会把connected置为 false

最终初始化代码为

1
2
3
4
5
6
7
8
Serial.end();// 重置connected
Serial.begin(115200);// 初始化串口通信

// 等待用户打开串口
while(!Serial);
// while (Serial.isConnected()); // 与上一行等价

// TO DO

这样就不会再上电就返回 true 啦

如果还不行的话可以试试 给图灵和冯诺依曼老祖点根香 检查ARDUINO_USB_MODE 宏是否定义且等于1 (Arduino IDE 是 “工具” -> “USB CDC On Boot: “ -> “Enable”)

相似案例

fix(usb_hw_serial): fixes connected state after sketch is uploaded by SuGlider · Pull Request #12184 · espressif/arduino-esp32

留言