背景:
在之前我们使用S32DS配置好的UART中断接收的程序中(【S32K146车规级MCU】使用S32DS适配Uart),发现串口在连续接收数据的过程中会存在丢数据的情况,就开始调查原因,就有了该篇帖子。
故障现象:
本地适配的shell在输入方向键的↑时候无法解析识别对应的动作,调查发现键盘输入↑在windows 下回连续上报“up key : 0x1b 0x5b 0x41” 三个字符,本地程序只收到两个字符造成无法解析,以下是本地uart 的初始化和中断处理流程。
/******************************************************************************************************** * Private Function Declarations * *******************************************************************************************************/ void uart_rx_callback(void *driverState, uart_event_t event, void *userData) { UartRecvType * Puart = (UartRecvType *)userData; if(event == UART_EVENT_RX_FULL) { /* Get date and write to ringbuffer */ RingBuffer_Write(&Puart->ringbuff,&Puart->data,1); } /* Start to recive uart data */ if(event == UART_EVENT_END_TRANSFER) LPUART_DRV_ReceiveData(INST_LPUART_1,&Puart->data,1); } /******************************************************************************************************** * Global Function Declarations * *******************************************************************************************************/ void uart_init(void) { /* Init lpuart */ LPUART_DRV_Init(INST_LPUART_1,&lpUartState0,&lpuart_0_InitConfig0); /* Init Ringbuffer */ static uint8_t uart_rx_buff[128] = {0}; RingBuffer_Init(&uart_rx.ringbuff,uart_rx_buff,128); /* Enable uart rx irq and set rx callback */ INT_SYS_SetPriority(LPUART1_RxTx_IRQn,2); LPUART_DRV_InstallRxCallback(INST_LPUART_1,uart_rx_callback,(void *)&uart_rx); /* Start to recive uart data */ LPUART_DRV_ReceiveData(INST_LPUART_1,&uart_rx.data,1); }
以上程序初始化接收流程也比较清晰,初始化串口开启UART接收中断,在串口接收中断回调函数中将数据写入环形buffer,接收一字节后继续开启启动一次接收,每次接收长度为1字节。
本地debug 查看串口中更新的ringbuff 数据结构,发现按下↑键,中断触发了两次,对应接收到两个数据分别为 0x1b 0xd0,第一个字节数据是对的后面是不正确的。
调查过程:
先使用逻辑分析仪抓取串口接收的物理层数是正确的,从而确定是接收端数据丢失的原因。
查看代码发现S32K1XX的串口中断接收处理中,在中断接收完成后会关闭LPUART的接收功能,看到此处理方式基本可以确定数据丢失原因为短暂的关闭了UART接收功能,上述逻辑分析仪抓取的数据可以看出数据此时为持续的,这时关闭UART功能会造成数据的丢失。
我们注释掉上述的处理后,功能恢复正常,从而确定是此处代码的原因。
我们已经可以确认是这块代码的问题了,我们继续通过逻辑分析仪,在关闭uart 接收功能处,添加IO状态查看当前uart 接收功能。
在此复现之前的问题查看uart 接收数据期间的状态,接收功能被关闭了100us
故障修改:
问题原因明确后,修改方案我们最简单的方式删除该处理,,因为该处理会被SDK的多个接口调用,删除会对sdk的代码造成未知的影响,为了兼容现有sdk 代码的处理方式,sdk 使用lpuart_state_t 来管理驱动的访问方式,在lpuart 初始化后我们可以获取到该结构,在该成员中添加enableRecive 成员控制是否需要关闭uart 接收功能。
串口初始化后设置该成员为true
修改接收中断完成处理逻辑,根据用户配置来是否屏蔽该段代码。
修改后运行代码功能串口丢数据问题得到解决。