这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【分享开发笔记,赚取电动螺丝刀】记S32K146使用串口中断接收丢数据的调查过程

共4条 1/1 1 跳转至

【分享开发笔记,赚取电动螺丝刀】记S32K146使用串口中断接收丢数据的调查过程

工程师
2025-03-08 12:23:38     打赏

背景:

在之前我们使用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,第一个字节数据是对的后面是不正确的。

image.png

调查过程:

先使用逻辑分析仪抓取串口接收的物理层数是正确的,从而确定是接收端数据丢失的原因。

image.png

查看代码发现S32K1XX的串口中断接收处理中,在中断接收完成后会关闭LPUART的接收功能,看到此处理方式基本可以确定数据丢失原因为短暂的关闭了UART接收功能,上述逻辑分析仪抓取的数据可以看出数据此时为持续的,这时关闭UART功能会造成数据的丢失。

image.png

我们注释掉上述的处理后,功能恢复正常,从而确定是此处代码的原因。

我们已经可以确认是这块代码的问题了,我们继续通过逻辑分析仪,在关闭uart 接收功能处,添加IO状态查看当前uart 接收功能。

image.png

在此复现之前的问题查看uart 接收数据期间的状态,接收功能被关闭了100us

image.png故障修改:

问题原因明确后,修改方案我们最简单的方式删除该处理,,因为该处理会被SDK的多个接口调用,删除会对sdk的代码造成未知的影响,为了兼容现有sdk 代码的处理方式,sdk 使用lpuart_state_t 来管理驱动的访问方式,在lpuart 初始化后我们可以获取到该结构,在该成员中添加enableRecive 成员控制是否需要关闭uart 接收功能。

image.png

串口初始化后设置该成员为true

image.png

修改接收中断完成处理逻辑,根据用户配置来是否屏蔽该段代码。

image.png


修改后运行代码功能串口丢数据问题得到解决。



       


工程师
2025-03-11 16:04:31     打赏
2楼

楼主是每一次都丢数据还是就是这个按键丢呢?


工程师
2025-03-11 16:07:23     打赏
3楼

是否可以修改为空休闲中断来处理更加合理,或者中断修改一次性接收一个字符,官方不会只规定接收两个字符就休眠吧。


工程师
2025-03-11 19:04:21     打赏
4楼

官方的sdk 设计理念是接收多少字节通过参数传递,接收完就会关闭uart 接收功能,本地的使用场景是每次接收一个字节,接收完成后在次触发接收一个字节,这中间有一次关闭再开开启的过程,如果字符之间有间隔错开这个关闭开启的时间窗口就不会触发问题,本地正好是连续来了三个字符就出问题了。


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]