5.3 KiB
5.3 KiB
05-实时性与系统优化
一、为什么嵌入式开发需要关注实时性?
你的 CAN 协议栈对实时性的需求:
| 场景 | 延迟要求 | 不达标后果 |
|---|---|---|
| CAN 帧收发中断响应 | < 100μs | 丢帧、总线错误 |
| 急停/安全帧 | < 1ms | 安全隐患 |
| 100Hz 周期发布 | < 10ms jitter | 数据抖动 |
| 文件传输 ACK 超时 | < 500ms | 重传风暴 |
标准 Linux 的 sleep(10) 实际可能睡 12-15ms——调度器不保证实时性。
二、Linux 实时化方案
2.1 Preempt-RT 补丁
标准 Linux: CONFIG_PREEMPT=n → 内核态不可抢占
低延迟 Linux: CONFIG_PREEMPT=voluntary → 检查点可抢占
实时 Linux: CONFIG_PREEMPT_RT=y → 几乎全部内核态可抢占
创龙已提供:RT 版本的内核镜像在 Linux/Kernel/image/ 下。
2.2 验证工具:Cyclictest
路径: [`Demo/linux-rt-demos/Cyclictest/`](../TL3568-EVM(Buildroot-2018.02)_V1.8/Demo/linux-rt-demos/Cyclictest/)
# 测试调度延迟
cyclictest -t 4 -p 99 -i 1000 -l 100000 -h 200 -q
# 4线程 RT99 1ms周期 10万次 直方图
# 预期结果:
# 标准内核: max latency 200+ μs (偶发)
# RT内核: max latency < 20 μs (稳定)
关键指标:
- Average latency → 平均延迟,< 5μs 正常
- Max latency → 最大抖动,RT 内核 < 20μs
- 直方图 → 看分布,有没有长尾
2.3 RT Demo 代码
| Demo | 路径 | 内容 |
|---|---|---|
| Cyclictest | linux-rt-demos/Cyclictest/ |
延迟基准测试 |
| rt_gpio_ctrl | linux-rt-demos/rt_gpio_ctrl/ |
SCHED_FIFO 线程控制 GPIO |
| rt_input | linux-rt-demos/rt_input/ |
实时采集输入信号 |
| rt_spi_rw | linux-rt-demos/rt_spi_rw/ |
实时 SPI 通信 |
三、CAN 协议栈的实时化策略
3.1 线程优先级
// 接收线程 → 最高实时优先级
struct sched_param param = { .sched_priority = 80 };
pthread_setschedparam(rx_thread, SCHED_FIFO, ¶m);
// 发送线程 → 次高
param.sched_priority = 70;
pthread_setschedparam(tx_thread, SCHED_FIFO, ¶m);
// 协议处理线程 → 普通实时
param.sched_priority = 60;
pthread_setschedparam(proc_thread, SCHED_FIFO, ¶m);
优先级原则:
收 (80) > 发 (70) > 协议处理 (60) > 日志/MQTT (普通)
↑ 丢了就再收不到 ↑ 可以定时补发 ↑ 可推迟
3.2 CPU 绑核
把 CAN 协议栈绑到独立 Core,避免和其他系统任务(网络中断、调度器)竞争:
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(3, &cpuset); // 绑定到 Core 3
pthread_setaffinity_np(rx_thread, sizeof(cpuset), &cpuset);
配合内核参数隔离 Core 3:
# 内核启动参数中加: isolcpus=3
cat /proc/cmdline # 确认生效
3.3 内存锁定(防 Swap)
mlockall(MCL_CURRENT | MCL_FUTURE); // 锁所有内存页,禁止 swap
CAN 收发循环中的内存如果被换出到存储,延迟可能飙到 10ms+。
四、PTP 时钟同步
手册: [`3-用户手册/2-17-基于PTP的时钟同步测试手册.pdf`](../TL3568-EVM(Buildroot-2018.02)_V1.8/3-%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8C/2-17-%E5%9F%BA%E4%BA%8EPTP%E7%9A%84%E6%97%B6%E9%92%9F%E5%90%8C%E6%AD%A5%E6%B5%8B%E8%AF%95%E6%89%8B%E5%86%8C.pdf)
如果多个 RK3568 节点需要微秒级时间戳对齐 CAN 报文(比如事故分析),需要 PTP (IEEE 1588):
# RK3568 GMAC 支持硬件时间戳
ethtool -T eth0 # 确认支持
# 启动 ptp4l
ptp4l -i eth0 -m # 自动选主从,同步时钟
五、性能调优工具
| 工具 | 用途 | 命令示例 |
|---|---|---|
perf |
CPU 热点分析 | perf top -p <pid> |
strace |
系统调用跟踪 | strace -c -p <pid> |
ftrace |
内核函数跟踪 | echo function > /sys/kernel/debug/tracing/current_tracer |
/proc/interrupts |
中断统计 | watch -n1 cat /proc/interrupts | grep can |
六、学习建议
CAP CAN 协议栈时按这个顺序做实时优化:
1. 先跑通功能(标准内核 + 普通线程) ← 保证逻辑正确
2. 用 cyclictest 测基线延迟 ← 了解系统"抖动底限"
3. 给收发线程加 SCHED_FIFO ← 最直接的提升
4. 绑核 (CPU affinity) ← 避免和网络中断竞争
5. mlockall 锁内存 ← 消灭不可控延迟源
6. 压测中 perf top 分析热点 ← 只优化真正慢的地方
7. 如有余力,切 Preempt-RT 内核 ← 把最坏延迟压到 20μs
⚠️ 不要在第一步就切 RT 内核。RT 内核的优先级反转、锁依赖会让普通的 bug 表现为"整个系统死掉",难以调试。