接前一篇文章PY32F系列MCU在串口接收时跑飞的根因分析1二、问题分析4. 实验确认上一回在分析排查板子接收串口错误数据跑飞的问题时定位到了是串口中断处理程序中else分支代码所导致的问题。再来回顾一下。完整的串口接收中断处理代码示例代码如下void USART1_IRQHandler(void) { __IO uint8_t data; static uint16_t length 0; if (__HAL_UART_GET_IT_SOURCE(Uart1Handle, UART_IT_RXNE) ! RESET) { data Uart1Handle.Instance-DR; if (uart1_rx_cnt (UART_RX_BUFFER_SIZE - 1)) { switch (uart1_rx_cnt) { case 0: if (data 0x55) //frame header 1 uart1_rx_buf[uart1_rx_cnt] data; else uart1_rx_cnt 0; break; case 1: if (data 0xAA) //frame header 2 uart1_rx_buf[uart1_rx_cnt] data; else uart1_rx_cnt 0; break; case 2: uart1_rx_buf[uart1_rx_cnt] data; break; case 3: …… break; case 4: …… break; default: uart1_rx_buf[uart1_rx_cnt] data; if (uart1_rx_cnt 3 length 2 2 - 1) { if (uart1_rx_buf[uart1_rx_cnt] 0xCC) { uart1_rx_cnt; recv_cmd1 1; } else { uart1_rx_cnt 0; memset((uint8_t *)uart1_rx_buf, 0x00, sizeof(uart1_rx_buf)); } break; } uart1_rx_cnt; break; } } else { uart1_rx_cnt 0; } __HAL_UART_CLEAR_FLAG(Uart1Handle, UART_IT_RXNE); } HAL_UART_IRQHandler(Uart1Handle); }问题出在default中的else分支中重点怀疑是memset一行代码导致的问题。为了验证就是是否是这一行代码引发的问题将这一行注释掉。编译、烧录再次运行仍然发送错误数据以及正确数据这次不会出现跑飞的情况了最多就是先发送错误帧的情况下接下来发送的一帧正确数据也会被“带坏”但再接下来就正常了。这就是说确实如之前猜测问题出在了memset这一行。但正如上一回所讲的memset函数是系统标准库代码笔者也没有用错也不存在数组溢出的问题。为什么会导致程序跑飞呢三、根因分析这个问题确实比较令人费解。没办法只能求助于AI工具了。笔者之前在“PY32F系列MCU在OTA时App区概率性跑不起来的根因分析”系列文章中曾经提到过Cursor当时用它来正向定位解决了OTA遇到的跑飞问题。当时在那个系列文章中曾经提到后续使用Cursor工具又解决了另一个棘手问题PY32F系列MCU在OTA时App区概率性跑不起来的根因分析6-CSDN博客就是本系列的这个问题了。Cursor给出的根因分析如下串口中断里这条memset会把中断拖过一个字节的时间USART溢出之后中断就再也不退出。memset本身没有把内存写坏。由于工程开了MicroLIB因此memset这一句编出来是 __aeabi_memclr给uart1_rx_buf清 256字节。链接信息里这个函数栈占用是0只是一段字节循环。串口波特率是15000001.5M一个字节大约6.7us。PY32F040的USART没有FIFO清256字节远长于这个间隔后面的字节进不了数据寄存器硬件置上溢出标志ORE。中断函数末尾又调用了HAL_UART_IRQHandler()。ORE已经置位、并且RXNE中断是开着的时候这个函数读完状态就return没有按“先读SR、再读DR”把ORE清掉。ORE在RXNE中断开启时会一直产生中断请求所以一返回又马上再进USART1_IRQHandler。主循环再也得不到执行表现表象就是跑飞。没有memset这行时收一个字节的处理时间短于字节间隔ORE起不来所以只有加上它才出现。四、最终解决解决方案很简单就是注释掉memset这一行就可以了。因为中断里也不需要清这256字节。uart1_rx_cnt 0之后下一帧会从下标0重新覆盖。主循环处理完命令后本来就会memset这块缓冲。五、总结与感悟说实在的如果说之前那个OTA问题笔者还能够自己想明白虽然比AI时间长得多但最终能够根据结果反推进而想清楚那么这个问题就让笔者看到了自己这二十几年在MCU层面的不足了。以我的功力能够定位到memset这一行也能够通过将其封掉来解决问题但把这个问题想得如此透彻以目前的功力来说无论如何做不到。还是要将基础再打牢一些甚至得“二次学艺”才能弥补这种理论基础上的“先天不足”了。笔者因为这两次败于AI确实一度感到沮丧甚至心灰意冷。但后来使用Cursor分析了基于SoC的Linux源码对于这一块Cursor表现得比较弱远不如MCU领域所展现出来的专业和精深。看来短时间几年之内程序员们还不至于没饭吃只要他们努力提高自身修为还是能够与AI一较高下的。
阅读完成 · 觉得有帮助?