linux_learn/learn/AMP-vs-LinuxRT/README.md

9.9 KiB
Raw Permalink Blame History

Linux+Preempt-RT vs AMP (Linux+RTOS) — 实时系统方案对比

目标平台RK35684×Cortex-A55 + 1×Cortex-M0 应用场景:电力二次保护设备 CAN 通讯


一、两种方案一句话概括

方案 核心思路
Linux + Preempt-RT 给 Linux 内核打实时补丁,让原本"不可抢占"的内核路径变得可抢占,把最坏延迟从 200μs+ 压到 20μs 以内。所有代码(协议栈、业务逻辑、驱动)都在同一个 Linux 里跑。
AMP (Linux + RTOS) 硬件分家1~3 个 A55 核跑 Linux 做复杂业务网络、文件系统、协议栈上层另外的核A55 或 M0跑 RT-Thread/Baremetal 做硬实时任务CAN 收发、保护逻辑、ADC 采集)。中间靠共享内存 + 中断rpmsg通信。

二、实时性能对比

2.1 中断响应延迟

这是最核心的指标——从 CAN 控制器收到一帧到 CPU 开始处理的时间:

指标 Linux+RT AMP (RT-Thread 裸核)
典型中断延迟 5~15 μs < 1 μs
最坏中断延迟 15~30 μs < 3 μs
延迟抖动 (jitter) ±10 μs ±1 μs
确定性 概率性99.9% 在预算内) 确定性100% 在预算内)

来源创龙文档RT 内核 cyclictest 测试 max < 20μs裸核无操作系统调度开销中断延迟仅取决于 CPU 频率和中断控制器。

2.2 你的 CAN 场景对号入座

场景 延迟要求 Linux+RT 够不够 AMP 必要性
CAN 帧收发(标准 1Mbps < 100μs 轻松满足 不必要
CAN FD 高速收发5Mbps < 50μs 基本满足 有富余
保护动作出口(从判断到出口继电器) < 1ms 满足 不必要
多通道同步 ADC + CAN 突发 < 10μs jitter ⚠️ 临界 AMP 更安全
微秒级 SOE 打时戳 < 5μs jitter 不够 必须 AMP
100μs 周期实时控制(如 SVG/APF < 50μs jitter 不够 必须 AMP

三、功能效果对比

3.1 Linux+Preempt-RT

┌──────────────────────────────────────────────┐
│  单块 Linux 内核 (PREEMPT_RT)                 │
│                                              │
│  ┌──────────┐ ┌───────────┐ ┌─────────────┐ │
│  │ CAN协议栈 │ │ 保护逻辑   │ │ 文件系统/NET │ │
│  │ SCHED_FIFO│ │ SCHED_FIFO │ │ 普通线程    │ │
│  │ prio=80   │ │ prio=70    │ │             │ │
│  └──────────┘ └───────────┘ └─────────────┘ │
│  ┌──────────────────────────────────────────┐│
│  │      全部共享同一个内核、同一套驱动        ││
│  └──────────────────────────────────────────┘│
└──────────────────────────────────────────────┘

优点:
  ✅ 所有代码一个工程,开发/调试/GDB 全统一
  ✅ SocketCAN 接口直接用,驱动现成
  ✅ POSIX 线程、文件系统、网络全有
  ✅ 丢帧、超时等异常处理逻辑好写

缺点:
  ✗ 最坏延迟 20μs够99%场景,但不是"硬实时"
  ✗ 内核态某些路径仍不可抢占(如某些 spinlock 临界区)
  ✗ 系统负载高时抖动会增大

3.2 AMP (Linux + RT-Thread)

┌──────────────────┐  rpmsg(共享内存+中断)  ┌──────────────────┐
│  Core0: Linux    │ ◄══════════════════►  │  Core2: RT-Thread │
│  (CA55)          │                       │  (CA55, 裸核)     │
│                  │                       │                   │
│  • CAN 协议栈上层 │ ←── CAN 帧、控制命令  │  • CAN FD 直接收发 │
│  • 定值管理       │                       │  • SOE 打时戳      │
│  • 录波文件存储   │ ──── 录波数据 ──────► │  • 保护逻辑判断    │
│  • MQTT 上送     │                       │  • GPIO 出口继电器 │
│  • GUI/调试      │                       │  • 100μs 周期控制  │
│                  │                       │                   │
│  应用层, 复杂业务  │                       │  实时层, 确定性任务 │
└──────────────────┘                       └──────────────────┘

优点:
  ✅ 真正的硬实时(裸核中断延迟 < 1μs
  ✅ 实时任务不受 Linux 调度器影响
  ✅ 实时核崩溃不影响 Linux 核(故障隔离)
  ✅ Linux 核可以做复杂的事(录波分析、文件压缩、网络通讯)

缺点:
  ✗ 两套代码、两个编译链、两种调试方式
  ✗ rpmsg 通信有开销(~10-50μs 的单次传输延迟)
  ✗ 核间通信协议需自己设计Linux侧和RT-Thread侧的数据结构要对齐
  ✗ 没有 SocketCAN 这样的现成接口,裸核 CAN 驱动需要自己写/移植

四、开发难度对比

4.1 技能要求

技能点 Linux+RT AMP
Linux 应用编程 (POSIX, SocketCAN) 需要 需要
Linux 内核/驱动 基本了解即可 不需要Linux 侧)
RTOS 编程 (RT-Thread) 不需要 必须掌握
裸核编程 (中断、寄存器、Linker Script) 不需要 必须掌握
交叉编译链 1 套 (aarch64-linux-gnu-) 2 套 (Linux + bare-metal)
JTAG 调试 不需要 需要(调试裸核)
共享内存/核间通信协议设计 不需要 需要
ARM 架构知识Cache、MMU、内存屏障 基本了解即可 需要深入理解

4.2 开发工作量估算

假设最终目标都是实现一个完整的 CAN 协议栈(含定时发送、突发上送、遥控、定值、文件传输):

阶段 Linux+RT AMP
环境搭建 1 天 (换 RT 内核镜像即可) 1~2 周 (AMP SDK 环境、双编译链、JTAG)
CAN 驱动 0 天 (SocketCAN 现成) 1~2 周 (移植/写裸核 CAN 驱动)
协议栈开发 2~4 周 (POSIX CGDB 调试) 4~8 周 (双端开发 + rpmsg 协议)
实时优化 1 周 (SCHED_FIFO + 绑核 + 锁内存) 1~2 周 (裸核本来就有确定性)
调试/稳定性 1 周 (GDB/valgrind/perf 工具链成熟) 2~4 周 (核间问题难复现、难定位)
总计 约 5~8 周 约 9~18 周

4.3 调试难度

Linux+RT:
  GDB → 打断点 → 看变量 → 搞定
  所有线程在一个进程空间crash 日志清晰

AMP:
  Linux 核: GDB 可调
  裸核: JTAG (硬件调试器) + printf 通过串口
  跨核问题: 裸核死掉Linux 侧完全不知道发生了什么
           只能靠看共享内存 dump + 猜

五、针对你的场景的建议

首先确认:你需要的"实时"到底是哪个级别?

对照 docs/05-实时性与系统优化.md 第 7-17 行的需求表:

你的需求场景 实时级别 推荐方案
CAN 帧收发1Mbps, 最大 8 字节) 软实时 Linux+RT
CAN FD 收发5Mbps, 64 字节) 软实时 Linux+RT
遥控选择-返校-执行ms 级) 软实时 Linux+RT
定时遥测上送100ms~1s 非实时 Linux+RT
保护动作出口(从采样到跳闸 < 30ms 硬实时 Linux+RT ⚠️ 基本够
微秒级 SOE 打时戳 硬实时 AMP
100μs 周期快速控制环 硬实时 AMP

结论:分阶段路线

阶段 1 (当前): Linux+RT — 跑通 CAN 协议栈
  ├── 标准 Linux 内核上把协议栈功能全部开发完
  ├── 用 SocketCAN 收发GDB 调试
  ├── 功能稳定后 → 切 RT 内核
  ├── 加 SCHED_FIFO + 绑核 + mlockall
  └── cyclictest 验证 → 基本满足 90% 的电力保护需求

阶段 2 (未来,如果有需要): AMP 硬实时
  前提条件:
  ├── 业务确实需要 <5μs 确定性(如 SOE 打时戳、100μs 控制环)
  ├── 准备好了 JTAG 调试器
  ├── 团队有人熟悉 RT-Thread 或裸核编程
  └── 架构拆分: Linux 做协议栈 + 界面,裸核做收发 + 保护逻辑

为什么不一开始就上 AMP

  1. 创龙的文档也这么建议的docs/05 第 147-157 行)——先跑通功能,再优化
  2. AMP 最大的坑不是写代码,是调试——两个核的状态不同步,出了 bug 很难定位
  3. 电力保护设备里,绝大多数通讯场景不到 1ms 级别——CAN 帧 1Mbps 下一帧才 ~100μsRT 内核的 20μs 中断延迟完全够
  4. 你当前的 CAN 协议栈设计(遥控超时 30 秒、遥测周期 500ms也是 ms~s 级别,不是 μs 级别

六、补充:还有一个中间方案 — Linux + M0 协处理

RK3568 内部有一颗 Cortex-M0(不是 A55可以跑极简裸核代码

A55 (Linux+RT):      M0 核:
  CAN 协议栈  ←── mailbox/IPCC ──→  CAN FD 收发
  保护逻辑                           GPIO 快速出口
  文件系统                           SOE 打时戳
  • M0 频率低(~200MHz但中断响应极快
  • Rockchip AMP SDK 主要就是面向 M0 核的
  • 不需要占用 A55 核Linux 侧 4 核全保留
  • 适合把"极少量的硬实时逻辑"剥离出去

这个方案比 AMP(A55+RT-Thread) 更轻量,但需要评估 M0 算力是否够你的保护逻辑。