14 · 自动驾驶 SoC 落地(ARM64):干扰源、分区样板与参数集
结论:自动驾驶 SoC(Orin/Thor、TDA4、S32G、R-Car V4H、Snapdragon Ride、征程 6 等)都是「多簇 Cortex-A 应用核 + Cortex-R 安全岛 + GPU/NPU/ISP 加速器 + 高带宽传感器接入」的异构结构,Linux 只跑在 A 核上。RT 内核解决的是 A 核上的内核抢占问题;要让 100 Hz–1 kHz 的控制/规划回路拿到 < 100 µs 抖动,还必须:把传感器接入 + 感知与控制/规划放到不同核簇;把 GPU/NPU/ISP 驱动的中断、DMA 缓存维护、CMA/SMMU 开销关进接入簇;用完整的参数集(Kconfig + cmdline + sysctl + 亲和 + 优先级)固化下来;并对厂商驱动做一次 RT 兼容性验证。本章给出三种核数样板与可直接套用的参数集,全部参数在 6.12.107 源码中有据可查。
第一层:数据流与抖动
先看结论:默认形态下所有传感器中断、GPU 完成中断、softirq、分配器路径都汇到同一批核的不可抢占区里,控制线程的最坏唤醒延迟由「最长的那一段」决定;分区后控制簇上只剩 arch timer、IPI 和自己触发的内核路径。
第二层:干扰源全景与 12 核样板
先看结论:自动驾驶 SoC 比通用 arm64 多出四类噪声——GPU/NPU/ISP 厂商驱动、非一致性 DMA 与 CMA、hypervisor、功能安全监控;RT 内核直接消除的是中断/softirq/锁那一层,其余靠分区与启动期预分配。
14.1 自动驾驶 SoC 的共性与 BSP 现状
| 特征 | 典型配置 | 对 RT 的意义 |
|---|---|---|
| 应用核 | 4–12× Cortex-A78AE/A76/A72/A53,1–3 个 DSU 簇,部分支持 Split-Lock/DCLS 锁步 | 分区以簇为单位;锁步模式下核数减半、频率可能降 |
| 安全岛 | Cortex-R52/R5F 跑 AUTOSAR/RTOS,通过 mailbox/rpmsg 与 Linux 通信 | 硬实时(< 10 µs)留在 R 核;Linux 侧目标是「软硬之间」的 50–100 µs 级 |
| 加速器 | GPU(NVIDIA/Mali/Adreno)、NPU/DLA、ISP、视频编解码 | 厂商驱动是 RT 兼容性最大的未知数 |
| 传感器接入 | 8–12 路 CSI-2 相机、10 GbE/2.5 GbE 雷达与激光雷达、CAN-FD ×N、TSN 以太网 | 高中断率与高 DMA 带宽集中在接入簇 |
| 互连/内存 | 非一致性或部分一致性 DMA、SMMU、LPDDR5 共享带宽、ECC | 缓存维护与带宽争用是 RT 无法消除的噪声 |
| 虚拟化 | QNX Hypervisor / Xen / KVM 分隔 ASIL 域与 QM 域 | Linux 作为 guest 时 vGIC 注入延迟叠加 |
| 内核版本 | 厂商 BSP:Orin JetPack 6 = 5.15(提供 RT 内核)、TI SDK = 6.1/6.6(PROCESSOR-SDK-LINUX-RT)、NXP = 6.6(RT BSP)、Renesas = 6.1 | 6.12 之前需要 -rt 补丁;本文机制在 5.15+ 的 -rt 内核上基本一致,行号不同 |
14.2 自动驾驶特有的干扰源(按严重程度)
| 干扰源 | 机制 | 典型量级 | 对策 | 位置 |
|---|---|---|---|---|
| 非一致性 DMA 缓存维护 | 相机/雷达缓冲 dma_sync 时 dcache_clean/inval_poc() 逐行遍历 |
每 MB 约 0.1–0.4 ms(A53 更慢),在 irq 线程或 ioctl 调用线程里执行 | DT dma-coherent(若互连支持);用持久映射(DMA_ATTR_SKIP_CPU_SYNC + 显式局部同步);缓冲区在接入簇处理 |
arch/arm64/mm/dma-mapping.c:15-31;drivers/of/address.c:1000-1010 |
| CMA / 大块分配 | GPU/ISP 缓冲、V4L2 REQBUFS 从 CMA 迁移页面 |
ms 级尖峰,随内存碎片增长 | 启动期一次性分配并长期持有;cma= 预留足够;避免运行期 REQBUFS/cudaMalloc |
mm/cma.c:406;kernel/dma/contiguous.c:91 |
| SMMU TLB 失效 | 每次 unmap 严格同步失效,cmdq sync 等待 | 几 µs–几十 µs/次,高频 map/unmap 叠加 | iommu.strict=0 惰性失效;映射长期持有;必要时 iommu.passthrough=1(失去隔离) |
drivers/iommu/iommu.c:44, 207-208;drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c:36-37 |
| GPU/NPU/ISP 驱动 | 厂商驱动常依赖 spin_lock_irqsave 关中断、hardirq 内分配、忙等 fence |
RT 下 lockdep 告警、死锁或延迟放大 | 用 PROVE_RAW_LOCK_NESTING + RT 内核过一遍驱动;把驱动中断线程锁定在接入簇;不让控制线程调用它们 |
第 02/06 章规则 |
| 相机/ISP 中断 | 每帧 1–3 个中断 × 8–12 路 = 500–1000 IRQ/s,每个后面跟 DMA 与 V4L2 队列操作 | 线程化后每中断 +3–6 µs(A78) | irq 线程 FIFO 70、亲和接入簇;帧级批处理 | 第 03 章 |
| 激光雷达 / 雷达 UDP | 50k–200k pps 小包 | NET_RX 线程化 + backlog 线程:pps 上限下降 10%–30% | 网卡中断硬件合并;busy_poll;接收线程 FIFO 60 绑接入簇;大包/GRO |
第 04 章;net/core/dev.c:11202-11210 |
| TSN 门控 | taprio 软件模式 hrtimer 在 RT 下进 softirq |
门控抖动几十 µs | 硬件 offload(flags 0x2)、etf 硬件 SO_TXTIME |
net/sched/sch_taprio.c:1953, 2077 |
| 安全岛 IPC | mailbox 中断线程化 | 通知延迟 = irq 线程调度延迟 | mailbox irq 线程 FIFO ≥ 控制线程 | drivers/mailbox/tegra-hsp.c:711, 858;drivers/mailbox/omap-mailbox.c:233 |
| 热降频 / DVFS | thermal governor 降频、SCMI 调频 | 频率跳变引起周期性能变化 | 固定频率于热稳定点之下;cpufreq.default_governor=performance + scaling_max_freq 上限 |
drivers/cpufreq/cpufreq.c:3084 |
| PSCI 深度 idle | cluster 级 idle 退出 100–300 µs | 控制簇尤其致命 | cpuidle.off=1 或逐态 disable;RT 下分层布局本就拿不到 cluster 态 |
drivers/cpuidle/Kconfig.arm:27-33;drivers/firmware/psci/psci.c:469-480 |
| Hypervisor | vGIC 注入、WFI/WFE trap、vCPU 被抢占 | 每次中断 +5–30 µs | KVM:kvm-arm.vgic_v4_enable=1 直通 LPI、vCPU 钉物理核、kvm-arm.wfi_trap_policy=notrap;Xen:sched=null、vwfi=native |
arch/arm64/kvm/vgic/vgic-v3.c:614;arch/arm64/kvm/arm.c:2888-2918;kernel-parameters.txt:2751-2797 |
| 功能安全监控 | softlockup/hardlockup、EDAC 轮询、RAS/SDEI | 周期性小噪声;nowatchdog 与 FuSa 监控冲突 |
内核看门狗交给外部 WDT/安全岛;保留 softlockup_panic 语义由安全岛复位 |
arch/arm64/kernel/watchdog_hld.c:15-35;drivers/firmware/Kconfig:31-38 |
| 安全缓解 | KPTI(A75)、Spectre-BHB(A72–A78) | 每次 syscall/中断 +几十–几百 ns | 评审后 mitigations=off 或保留 |
第 01 章 |
| 内存带宽争用 | GPU/NPU 满载时 CPU 访存延迟翻倍 | 无 MPAM,内核无法分区 | SoC QoS 寄存器 / 固件配置;控制线程数据放 SRAM/L2 常驻 | 6.12.107 无 MPAM |
14.3 CPU 分区样板
样板 A:12 核 A78AE,三簇(Orin 类)
| 簇 / CPU | 角色 | 内核线程与中断 | 用户态 |
|---|---|---|---|
| 簇 0:CPU 0-3 housekeeping | 所有非关键中断、内核线程、中间件 | irq/*(默认 50)、ksoftirqd、rcuc/rcuo、kworker、pr/legacy;网络/存储/USB/显示中断亲和于此 |
DDS 发现、日志、诊断、OTA、shell |
| 簇 1:CPU 4-7 接入 + 感知 | 传感器接入与 GPU/NPU 提交 | CSI/ISP、雷达网卡、GPU/NPU 中断亲和于此;rcu_nocbs 覆盖 |
感知推理线程(FIFO 55)、雷达接收(FIFO 60) |
| 簇 2:CPU 8-11 控制 / 规划(隔离) | 硬约束回路 | isolcpus=domain,managed_irq + nohz_full + rcu_nocbs;只剩 arch timer / IPI;控制用 CAN/EtherCAT 中断可专门亲和到 CPU 8 |
控制 100 Hz(FIFO 90,CPU 8)、规划 10 Hz(FIFO 80,CPU 9)、定位/融合(FIFO 75,CPU 10-11) |
启动参数:
isolcpus=domain,managed_irq,8-11 nohz_full=8-11 rcu_nocbs=4-11 irqaffinity=0-3 skew_tick=1
cpuidle.off=1 cpufreq.default_governor=performance rcutree.kthread_prio=3
iommu.strict=0 cma=512M nosoftlockup
(nowatchdog 视功能安全方案而定;KPTI/mitigations 见 14.5。)
样板 B:8 核 A72 同构(TDA4 类)
| CPU | 角色 |
|---|---|
| 0-1 housekeeping | 全部非关键中断与内核线程、中间件、日志 |
| 2-5 接入 + 感知 | 相机/雷达/以太网中断、DSP/NPU(C7x/MMA)完成中断、感知线程 |
| 6-7 控制隔离 | isolcpus=domain,managed_irq,6-7 nohz_full=6-7 rcu_nocbs=2-7 irqaffinity=0-1;控制 FIFO 90 绑 CPU 6,规划 FIFO 80 绑 CPU 7 |
A72 无 LSE,rt_mutex 快路径走 LL/SC;KPTI 关闭(kpti_safe_list)但 Spectre-BHB 缓解生效。
样板 C:4 核 A53(S32G / 网关类)
| CPU | 角色 |
|---|---|
| 0 housekeeping | 所有中断与内核线程、诊断 |
| 1 接入 | CAN/以太网中断线程(FIFO 60-70)、路由/网关线程 |
| 2-3 控制隔离 | isolcpus=domain,managed_irq,2-3 nohz_full=2-3 rcu_nocbs=1-3 irqaffinity=0;控制线程 FIFO 90 |
A53 频率低、无 LSE、线程切换 3–5 µs,目标放宽到 < 100 µs;硬实时留给 M7 锁步核。
14.4 优先级栅格(三种样板通用)
| 优先级 | 对象 | 依据 |
|---|---|---|
| 99 | migration/N、watchdog/N |
内核固定(kernel/sched/core.c:3566) |
| 92 | 控制回路依赖设备的 irq/*(CAN、EtherCAT、安全岛 mailbox) |
必须先于控制线程被处理 |
| 90 | 控制线程(100 Hz–1 kHz) | 最高业务优先级 |
| 80 | 规划(10 Hz) | |
| 75 | 定位 / 融合 | |
| 70 | CSI/ISP、雷达网卡 irq/* |
接入簇最高 |
| 65 | GPU/NPU 驱动 irq/* |
|
| 60 | napi/*、雷达 UDP 接收线程 |
|
| 55 | 感知推理线程 | 被 GPU 提交/等待主导 |
| 50 | 其余 irq/*(默认) |
kernel/sched/syscalls.c:856-861 |
| 3 | rcuc/N、rcub/N |
rcutree.kthread_prio=3 |
| OTHER nice 0 | DDS/ROS 2 非关键线程、ksoftirqd、kworker |
|
| OTHER nice 10 | 日志、上传、诊断 |
规则:同一条数据流上游的中断线程优先级 ≥ 下游消费线程;控制簇里除控制设备中断外不允许任何 irq 线程;感知簇的 irq 线程优先级低于控制簇所有线程(它们不在同一簇,但 IPI/迁移场景下仍需保证)。
14.5 参数集(可直接套用后按平台裁剪)
Kconfig(arm64,在厂商 defconfig 上叠加)
CONFIG_EXPERT=y CONFIG_PREEMPT_RT=y CONFIG_HZ_1000=y
CONFIG_NO_HZ_FULL=y CONFIG_RCU_NOCB_CPU=y CONFIG_HIGH_RES_TIMERS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
CONFIG_CMA=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=512(按需)
CONFIG_ARM64_64K_PAGES=y(仅当全部驱动/用户态验证通过;否则 4K)
CONFIG_ARM64_PSEUDO_NMI=y(需要 NMI 看门狗或 perf 精确采样时)
# 关闭
CONFIG_DEBUG_PREEMPT / LOCKDEP / PROVE_LOCKING / KASAN / KCSAN / DEBUG_RT_MUTEXES / ARM64_DEBUG_PRIORITY_MASKING
CONFIG_SLUB_CPU_PARTIAL=n CONFIG_ARM64_SVE=n(无 SVE 用户时) CONFIG_ARM64_MTE=n
CONFIG_TRANSPARENT_HUGEPAGE / NUMA_BALANCING(RT 下自动不可选)
启动参数(样板 A)
isolcpus=domain,managed_irq,8-11 nohz_full=8-11 rcu_nocbs=4-11 irqaffinity=0-3 skew_tick=1
cpuidle.off=1 cpufreq.default_governor=performance rcutree.kthread_prio=3
iommu.strict=0 cma=512M nosoftlockup
# 按安全评审决定:
mitigations=auto | mitigations=off | nospectre_bhb
# 仅 A75 等 CSV3=0 的核:kpti=off
# 需要 NMI 看门狗 / perf 时:irqchip.gicv3_pseudo_nmi=1
# 无 SVE 用户:arm64.nosve
# KVM host(Linux 作为 hypervisor):kvm-arm.vgic_v4_enable=1 kvm-arm.wfi_trap_policy=notrap
sysctl(/etc/sysctl.d/90-rt.conf)
kernel.sched_rt_runtime_us = -1
kernel.sched_energy_aware = 0
kernel.timer_migration = 0
kernel.hung_task_timeout_secs = 0
kernel.printk = 3 4 1 3
vm.stat_interval = 120
vm.swappiness = 0
vm.compact_unevictable_allowed = 0
net.core.busy_poll = 50
net.core.busy_read = 50
net.core.rmem_max = 67108864
net.core.netdev_max_backlog = 250000
中断亲和与线程优先级(启动脚本)
systemctl disable --now irqbalance
echo 0-3 > /proc/irq/default_smp_affinity
for i in /proc/irq/*/smp_affinity_list; do echo 0-3 > $i 2>/dev/null; done
# 接入设备 → 簇 1
for irq in $(grep -E 'csi|isp|vi|nvcsi|eqos|dwmac|gpu|nvgpu|dla|pva' /proc/interrupts | cut -d: -f1); do echo 4-7 > /proc/irq/$irq/smp_affinity_list; done
# 控制设备 → CPU 8
for irq in $(grep -E 'can|mttcan|flexcan|ecat' /proc/interrupts | cut -d: -f1); do echo 8 > /proc/irq/$irq/smp_affinity_list; done
# 优先级
chrt -f -p 92 $(pgrep -f 'irq/.*-(can|mttcan|flexcan)')
chrt -f -p 70 $(pgrep -f 'irq/.*-(csi|isp|vi)')
chrt -f -p 65 $(pgrep -f 'irq/.*-(gpu|nvgpu|dla|pva)')
chrt -f -p 60 $(pgrep -f 'napi/')
for s in /sys/devices/system/cpu/cpu[4-9]*/cpuidle/state[1-9]*/disable /sys/devices/system/cpu/cpu1[01]/cpuidle/state[1-9]*/disable; do echo 1 > $s 2>/dev/null; done
应用侧
- 控制/规划进程:
mlockall(MCL_CURRENT|MCL_FUTURE);预触碰栈与堆;clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME)周期循环;PTHREAD_PRIO_INHERIT;pthread_setaffinity_np绑定隔离核;热路径无malloc/ioctl/printf。 - 感知进程:GPU/NPU 缓冲区(
cudaMalloc/dma-buf)与 CMA 在初始化阶段全部申请并常驻;推理线程 FIFO 55 绑接入簇;与控制簇之间用共享内存零拷贝(iceoryx / DDS SHM),不走 socket。 - 中间件:DDS executor 线程按数据流分级
chrt;发现/心跳线程留在 housekeeping;UDP 多播缓冲区SO_RCVBUF提前放大。 - 记录/上传:
SCHED_OTHERnice 10,ionice -c3,绑 housekeeping。
14.6 hypervisor 场景
| 场景 | 参数 / 做法 | 位置 |
|---|---|---|
| Linux 作 KVM host,RT guest | kvm-arm.mode=nvhe|protected 按安全需求;kvm-arm.vgic_v4_enable=1 让 LPI 直接注入 vCPU;kvm-arm.wfi_trap_policy=notrap、wfe_trap_policy=notrap 避免 idle 陷入;vCPU 线程 FIFO 并钉在专用物理核;直通传感器设备(VFIO) |
arch/arm64/kvm/arm.c:2888-2918;arch/arm64/kvm/vgic/vgic-v3.c:596-614;kernel-parameters.txt:2751-2797 |
| Linux 作 guest(QNX Hypervisor / Xen) | guest 内参数同 13.5;宿主侧:vCPU 1:1 钉物理核、sched=null(Xen)、vwfi=native、中断直通、避免 host 侧 vCPU 抢占 |
宿主文档 |
| 安全域与 QM 域分离 | 控制簇物理核只给 ASIL 域 guest;接入/感知簇给 QM 域 | — |
guest 内看到的「hardirq 停留时间」包含 host 的注入延迟,cyclictest 要在 guest 内和 host 内各测一次分辨来源。
14.7 功能安全与看门狗
nowatchdog/nosoftlockup消除内核自身周期噪声,但功能安全需要「Linux 卡死可被检测」——把检测责任交给外部 WDT / 安全岛(Linux 用户态喂狗线程 FIFO 95 周期性喂狗,卡死即由 R 核复位),内核内 watchdog 关闭。- 若必须保留内核 hardlockup 检测,arm64 需要伪 NMI(
arch/arm64/Kconfig:232;watchdog_hld.c:28-35),接受第 01/03 章所述的伪 NMI 副作用。 panic_on_oops=1、oops=panic、softlockup_panic=1(如保留)让故障行为确定,由外部 WDT 完成复位;kernel.panic=<秒>自动重启。- RAS/SDEI 事件在
dmesg中留痕即可,不要在控制簇上处理 RAS 轮询。
14.8 验收清单(自动驾驶版)
cyclictest -m -Sp90 -i1000 -h200 -D24h -a8:控制核 24 小时最大值 < 50 µs(A78)/ < 100 µs(A53),且在满负载感知 + 满带宽传感器回放下重复。- 控制回路端到端:从 CAN 帧到达时间戳到指令发出,P99.99 抖动 < 100 µs(用硬件时间戳或 gPTP 对齐)。
- 传感器时间戳抖动:相机 frame done → 用户态可见 < 200 µs;雷达 UDP 包到用户态 < 100 µs,丢包 0。
osnoise/timerlat在控制簇:无 IRQ/softirq/线程噪声;hwlatdetect24 小时无 > 20 µs 固件停顿。- GPU/NPU 提交延迟分布不因 RT 恶化超过 20%;驱动在
PROVE_RAW_LOCK_NESTING下无告警。 - 热稳定:满负载 30 分钟后频率不降、延迟不漂。
源码定位
| 主题 | 位置 |
|---|---|
| DMA 缓存维护 / dma-coherent | arch/arm64/mm/dma-mapping.c:15-31;drivers/of/address.c:1000-1010 |
| CMA / swiotlb | mm/cma.c:406;kernel/dma/contiguous.c:91;kernel/dma/swiotlb.c:206 |
| SMMU | drivers/iommu/iommu.c:44, 207-208;drivers/iommu/Kconfig:110-135;drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c:36-37 |
| KVM / vGIC | arch/arm64/kvm/arm.c:2888-2918;arch/arm64/kvm/vgic/vgic-v3.c:596-614 |
| TSN | net/sched/sch_taprio.c:1289, 1953, 2077 |
| mailbox | drivers/mailbox/tegra-hsp.c:711, 858;drivers/mailbox/omap-mailbox.c:233 |
| PSCI / cpuidle / cpufreq | drivers/firmware/psci/psci.c:469-480, 736-740;drivers/cpuidle/Kconfig.arm:17-44;drivers/cpuidle/cpuidle.c:811-818;drivers/cpufreq/cpufreq.c:3084 |
| 安全缓解 | arch/arm64/kernel/cpufeature.c:1737, 1982;arch/arm64/kernel/proton-pack.c:90, 413, 829-1034;kernel/cpu.c:3230 |
| 看门狗 | arch/arm64/kernel/watchdog_hld.c:15-35;arch/arm64/Kconfig:224-232 |
| MPAM | 6.12.107 无 |
小结
- 自动驾驶 SoC 上 RT 内核只解决「内核抢占」这一层;控制回路能否稳定 < 100 µs 取决于分区、驱动 RT 兼容性与启动期预分配。
- 三簇分区是核心:housekeeping / 接入+感知 / 控制隔离(housekeeping 的原理与友商做法见第 13 章);中断亲和与优先级栅格按数据流上下游排定。
- 四类平台特有噪声——非一致性 DMA 缓存维护、CMA/SMMU、厂商驱动锁假设、hypervisor——都有对应参数或工程做法。
- 参数集已给出可直接套用的版本;安全缓解与看门狗取舍需过功能安全评审。
- 承上启下:第 15 章是全部源码位置索引,第 16 章把全文收拢。