linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案

问题现象

机器在户外测试时, 出现 轮速记 丢失的现象

  • 小概率出现 50Hz丢失1~2帧
  • 极低概率出现 0.1~0.3秒内没有底盘数据
    linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案_第1张图片
    linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案_第2张图片
    此问题导致slam定位漂, 需要优化处理.

验证与测试

问题1: 底盘串口 一个数据帧(head–data–crc) 被分片2~3报文
碎片报文
解决方法:
检测到head之后, 解析data_len, 读取剩余的字节

问题2: 极小概率, 帧head 不在头部, 即buf[0], buf[1]不是head
linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案_第3张图片
解决方法: 内存搜索head, 若匹配到
1.使用memmove移到buf[0]
2.使用p_head 指向buf中的head

验证1: 压力测试

开发板运行stress --cpu 6 , 模拟cpu高负载场景
–>结果: 数据未丢失
htop 查看cpu负载
linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案_第4张图片

验证2: 回环测试

1. PC模拟串口数据, 给开发板发串口数据.
2. 开发板运行stress  --cpu 6, 给cpu增加负载.
-->结果: 数据未丢失

验证3: 怀疑串口线过长

1.怀疑串口线过长, 硬件改线改短.  --无优化效果
2.更改串口通信的波特率bps. --无优化效果

验证4: 怀疑MCU没有发送数据

发送定位,感知信息给MCU做导航处理, 怀疑处理不及时导致丢包.

  1. 验证方法: MCU上报数据协议添加: 时间戳, 序列号.
    <1 通过序列号调试发现, 确实丢失报文, 丢失的序列号, 时间戳与数量对的上.
  2. 硬件信号上的确认
    <1 逻辑分析仪器, 捕捉信号分析. --未进行
    <2 PC接入串口, 看是否有数据丢失. --未进行

小结

  1. 给开发板CPU加负载, 测试没有复现问题
    1. 排除硬件接线问题. -->验证2(回环测试) + 验证3(串口线改短)排除.
    2. 怀疑MCU处理速度慢, 来不及上报数据.
      需要进行
      1.逻辑逻辑分析仪 捕捉串口数据信号, 解析判断
      2.PC串口接RX, 尝试解析串口数据, 从第3方外设确认是否丢包

中断绑定CPU优化方法

柳暗花明的提示点1: 压力测试方法
1. 同事进行拷机测试, 尝试把SOC的温度, 提高到95度, 进行 7 x 24 小时老化, 稳定性测试.
2. 得知只进行CPU压力测试, 无法把SOC温度提到最高, 给了我一个cpu+npu+gpu的压力测试工具, 极限压榨SOC.

使用压力测试工具
–> 测试结果: 串口帧率从50Hz降到30Hz.

默认 压力测试
50Hz 30Hz

柳暗花明的提示点2: 绑定CPU核
1. 同事负责深度相机数据上报, 说绑定CPU核, 可以稳定帧率
绑定CPU亲和性API

#define _GNU_SOURCE
#include 

    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(3, &mask);
    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1){
        return 0;
    }

测试: 尝试绑定CPU核
压力测试工具 + 绑定CPU核
测试结果如图

默认 压力测试 压力测试+绑定CPU核心
50Hz 30Hz 45Hz

不经意的发现: cpu处理中断不均衡

调试时, top查看负载时, 发现 0.3 si

  • hi 表示硬件中断
  • si 表示软件中断
    查看中断使用情况
    cat /proc/interrupts
    linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案_第5张图片
    可以看到, irq中断默认在cpu0上触发.
    尝试 将 irq中断绑定到其它的cpu核心上.

串口设备为ttyS0, 查看ttyS0的中断号
cat /proc/interrupts| grep tty
在这里插入图片描述

ttyS0的中断号为28, 绑定中断号28到cpu2
sudo echo 0x4 > /proc/irq/28/smp_affinity
确认修改是否成功
cat /proc/irq/28/smp_affinity

04

运行程序, 查看中断触发情况
cat /proc/interrupts| grep -E "tty|CPU"
在这里插入图片描述
可以看到, 中断号irq28在cpu2上触发
测试结果

默认 压力测试 压力测试+绑定CPU核心 压力测试+irq中断绑定CPU
50Hz 30Hz 45Hz 46.5

方案对比测试

通过上面分析验证测试, 找到如下的优化方案

  1. 增加程序的优先级
  2. 进程绑定CPU核
  3. irq 中断绑定CPU核
    增加一个对比测试
  4. 进程绑定CPU + 中断绑定CPU核

开发有多个外设, 选取两个外设做压力测试.
ttyS0 底盘串口, ttyS3 IMU串口, 测试结果如下
linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案_第6张图片

测试结论:
中断irq绑定CPU >= 进程绑定CPU >= 中断绑定CPU+进程绑定CPU

总结

  1. 怀疑串口数据丢失, 应该使用 逻辑分析仪, 第三方串口工具接入RX 验证数据是否丢失.
  2. 高CPU负载不能复现问题, 可以从io负载, irq中断 使用等情况分析.

其它
3. 设置内核启动参数isolcpus(隔离CPU, 系统调度不会切换到CPU)
linux下串口数据_延迟.丢失--系统高负载下_实时性优化方案_第7张图片
如图cpu8 不会被系统调度, 使用率为0.
尝试将外设进程绑定到CPU8, 实测效果无变化.
估计是进程占用资源比较少, 最高占用2.5%cpu, 只要cpu有空闲, 都可以被调度.
主要还是 中断绑定CPU 提升最大.

参考链接

中断分配
https://developer.aliyun.com/article/64868
https://blog.csdn.net/ysdaniel/article/details/8779084

修改程序优先级: nice, setpriority
https://www.cnblogs.com/zhangxuan/p/6427533.html

隔离CPU-isolcpus
https://blog.csdn.net/haitaoliang/article/details/22427045

进程绑定到CPU核, 亲和性绑定
https://blog.csdn.net/Z_Stand/article/details/107883684
绑定CPU实例代码

RK3588 实时性能分析与优化方案文档: Rockchip_Trouble_Shooting_Linux_Real-Time_Performance_CN.pdf

经过分析,最终RK3588读取串口节点数据慢的解决⽅案如下:

  1. CONFIG_PREEMPT 打开(抢占打开,⼀个任务不会⻓时间占⽤CPU,减小延迟)
  2. CONFIG_HZ=1000(减小内核⼼跳间隔,提⾼任务切换响应)
  3. UART0中断绑定到⼤核CPU4上(提⾼UART0的中断响应速度)
  4. 单独把内核UART0(与MCU通信)数据上报改成RT线程(保证UART0线程唤醒的时候,可以⻢上 得到CPU,不⽤等待其他普通任务)
  5. 应⽤读取串口UART0节点线程改为RT线程(保证读取UART0节点的应⽤线程唤醒时,可以⻢上得 到CPU,不⽤等待其他普通任务)
  6. 在RT线程中去掉耗时和阻塞的操作(避免影响实时线程的调度)
  7. 内核UART0数据上报实时线程和应⽤读取串口UART0节点实时线程,都绑定CPU5,与串口中断绑 定的CPU4隔离开(否则TX数据发送时,会打断RX实时线程)
    /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor cat
    /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq cat
    /sys/class/devfreq/dmc/governor cat /sys/class/devfreq/dmc/cur_freq
  8. 需要合理调整应⽤实时线程的优先级,已排查到很多应⽤线程设为RT线程,需要结合产品应⽤进⾏ 修改
  9. MCU有概率地会超过13ms发送数据,此作为已知问题,MCU部分去排查

一个网络-系统-linux内核-机器人 工程师
微信名片

你可能感兴趣的:(外设,linux,各子系统,linux,机器人,kernel,中断,串口,CPU绑定)