串口通信失败

1. DMA故障导致串口通信失败

1.1 背景

        Android应用层通过write方法写串口与MCU通信,如果未收到MCU的ack则重新将之前写入的信息重新写一遍,直至收到MCU的ack;

        bug现象是:Android应用层一直未收到ack并不断重写,2分钟之后write方法卡住。

1.2 分析

        经过源码分析,认为serial层的write函数有可能导致休眠,其中有一个缓冲区空间为4096字节,上层通过log将已发送的数据进行统计发现,当数据发送累计4102字节时会卡住。

        加log进行复现和分析,结果如下:

         根据log可知,在write方法卡住时最后一批log显示uart_write方法返回值为0,如果上层应用为阻塞式访问,则会调用schedule方法将当前进程休眠即上层直观感受上的卡死。

        参考log分析源码可知,serial层的环形缓冲区空间已满导致bug的出现,serial层数据到硬件TX_FIFO是由DMA来搬运的,所以初步估计DMA有问题,向SoC厂商咨询后对方表明,该SoC的DMA确实有一些缺陷。

        继续添加log发现,确实DMA出现了不搬运数据的故障,结果如下:

2. 关闭DMA后导致串口通信失败

2.1 背景

        继上次关闭DMA以后,在某特定场景下回出现频率较高的串口通信失败,基本过程就是MCU给SoC发消息,然后有一帧消息会丢失,从而导致Android应用上层校验失败,判断通信失败。

        由于各种原因MCU端屏蔽了针对这种情况的重发机制,所以需要SoC端寻找原因和解决方案。

        有一个值得关注的现象是:应用层通过不停的读缓冲区发现,当一次性读取到的数据为32字节时,下一帧数据就会出现丢失情况。

2.2 分析

        SoC串口的硬件RX_FIFO空间也是32字节,驱动代码中设置的阈值为16字节,即RX_FIFO中超过16字节就会触发中断,提醒CPU搬运数据至tty层,结合应用层发现的现象,初步结论为RX_FIFO溢出。

        SoC的串口控制器是有溢出标志位的,在驱动代码中添加log打印,最终确认出现通信失败时RX_FIFO确实溢出了。

        基本判断是UART硬件中断优先级太低导致出现中断响应不及时,从而导致RX_FIFO溢出。

2.3 解决办法

2.3.1 调整阈值

        调整触发串口中断的阈值,调整之后有些许改善,但是溢出情况的频率依旧较高,故此方法pass掉。

2.3.2 修改中断优先级

        修改中断优先级的影响范围太广,且SoC厂商不建议修改中断优先级,建议修改中断亲缘性,故此方法pass掉。

2.3.3 修改中断亲缘性。

方式一:

//1. 查看中断对应的编号
cat /proc/interrupts 
  ······
  59:        205          0       GIC  21e8000.serial
  
//2. 将串口的中断亲缘性从CPU0改到CPU1  
echo 2 > /proc/irq/59/smp_affi nity
//十进制2对应二进制0010,如果要改到CPU2,则需要写入0100即十进制4,但是IMX6D只有2个CPU核心,所以设置4是无效的(不生效)

方式二:

        在驱动代码中调用irq_set_affinity()将串口中断绑定在某个CPU核心上执行。

retval = request_irq(sport->port.irq, imx_int, 0,
                                     dev_name(port->dev), sport);
irq_set_affinity(sport->port.irq, cpumask_of(2));

        通过调整中断亲缘性后也只能是有一定的改善作用,不能100%解决此问题。

2.3.4 添加流控

        流控分为软件流控和硬件流控,我个人更加倾向于硬件流控。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值