ARM3 MSS UART接收中断重复触发首字节覆盖丢失问题咨询
ARM3 MSS UART中断重复触发、首字符丢失问题
初始问题
为什么我的UART ARM3 MSS函数会被调用两次?
已确认的基础触发原因:当前配置为单字节触发接收中断模式,每收到1字节就会触发一次中断。第一次中断触发时硬件FIFO仅存入1个字符,第二次中断触发时剩余数据才全部进入FIFO。
新异常现象
在plink/putty中输入字符串"test"并按下回车时,出现首字符丢失问题:
- 第一次触发ISR时,缓冲区中仅存在字符't'
- 第二次触发中断时,缓冲区中仅存'e','s','t','\n',首个字符't'丢失。同类异常表现为输入"status\n"时仅读取到"tatus\n"
该现象存在偶发性,少数场景下缓冲区可接收到完整字符串。目前计划调整逻辑为持续接收数据直到检测到'\n'为止,待解决两个核心疑问:
- 首个接收到的字符't'丢失到哪里了?
- 为何首字符会被覆盖?
现有实现代码
UART初始化
MSS_UART_init(&g_mss_uart0, MSS_UART_115200_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY);
中断回调注册
MSS_UART_set_rx_handler(&g_mss_uart0, uart3_rx_handler, MSS_UART_FIFO_SINGLE_BYTE);
流程差异
中断处理函数负责打印读取到的内容,并将内容传入command和value_str变量供后续处理:
- 预期流程:中断触发->调用UART处理函数->无后续中断
- 实际流程:中断触发->调用UART处理函数->再次触发中断->调用UART处理函数->无后续中断
中断处理函数实现
void uart3_rx_handler(mss_uart_instance_t *this_uart) { unsigned int rx_size = MSS_UART_get_rx(this_uart, g_rx_buff, sizeof(g_rx_buff)); (void)rx_size; uart_calls_cnt++; uart_handler_flag = 0; if (strchr((char *)g_rx_buff, '\n') != NULL) { memset(command, 0, 255); memset(value_str, 0, 255); strcpy(value_str, (char *)g_rx_buff); strcpy(command, (char *)g_rx_buff); value_str[strcspn(value_str, "\n")] = 0; command[strcspn(command, "\n")] = 0; memset(&g_rx_buff[0], 0, 128); uart_handler_flag = 1; } else { // 无任何处理逻辑 } }
问题根因
两个疑问是同一个逻辑bug导致的:
- 首字符没有丢失,是被第二次读取UART的操作直接覆盖了。
- 覆盖原因:第一次中断触发时,硬件FIFO里只有首字符't',调用
MSS_UART_get_rx把't'读到了g_rx_buff的起始位置,之后判断缓冲区里没有'\n',直接走else分支无任何操作——既没有把已经读到的't'暂存到累积缓冲区,也没有记录当前已接收的长度偏移。等后续字节到达触发第二次中断时,再次调用MSS_UART_get_rx,仍然把新读到的'e','s','t','\n'从g_rx_buff的起始地址开始写入,直接把之前存在0偏移位置的't'覆盖。
偶发可以收到完整字符串的场景,本质是多个字节几乎同时到达UART FIFO,第一次中断触发时FIFO里已经攒了全部字符,一次读取完成,没有触发第二次中断,自然不会出现覆盖。
修复方案
不要每次中断都把新读的数据往接收缓冲区的起始地址写入,需要维护一个接收偏移指针:
- 定义全局变量记录当前缓冲区已写入的位置,例如
uint16_t rx_write_idx = 0;,初始值设为0 - 每次进入中断调用
MSS_UART_get_rx时,读缓冲区地址传入g_rx_buff + rx_write_idx,不要直接传g_rx_buff首地址 - 读取完成后把本次读到的字节数
rx_size加到rx_write_idx上,更新下一次写入的位置 - 判断缓冲区中是否存在'\n':如果存在,执行命令解析逻辑、置位处理标记,之后把
rx_write_idx重置为0准备接收下一包数据;如果不存在'\n',直接退出中断等待后续数据即可,不要清空接收缓冲区 - 增加缓冲区长度判断,避免
rx_write_idx超过g_rx_buff的大小导致内存越界
内容的提问来源于stack exchange,提问作者pgapga
相关产品推荐
相关产品推荐

