2026/4/6 7:13:59
网站建设
项目流程
RK3506 AMP 异构多核通信 RPMsg-Lite 握手卡死 (wait_for_link_up)1. 问题背景与现象硬件平台Rockchip RK3506 (Cortex-A7 集群 Cortex-M0 协处理器)软件环境Linux 6.1 (主核) 裸机/RTOS (从核 MCU)使用 RPMsg-Lite 框架进行核间通信。问题现象Linux 侧设备树配置正确成功加载rockchip-rpmsg驱动内核打印virtio_rpmsg_bus virtio0: rpmsg host is online且成功生成/dev/rpmsg_ctrl0节点。MCU 侧调用rpmsg_lite_remote_init()后程序死死卡在rpmsg_lite_wait_for_link_up()函数中的死循环里voidenv_wait_for_link_up(volatileuint32_t*link_state,uint32_tlink_id){while(*link_state!1U){}// --- 永远卡在这里}无论如何在 MCU 侧通过轮询或延时link_state始终为0。2. 排查历程在裸机与 Linux 异构通信中底层硬件的耦合度极高只要有一个环节没对齐就会导致“鸡同鸭讲”。排查过程中我们接连踩中了以下四大天坑坑 1误以为link_state存在于共享内存中起初以为link_state是 Linux 写入共享内存如0x03c00000的值。通过调试器仿真器抓取内存地址发现link_state的地址落在 MCU 的本地内部 RAM (0x03A0XXXX) 中。结论link_state根本不在共享内存里它是 MCU 本地变量。它唯一的翻转途径是Linux 向 MCU 发送 Mailbox 硬件中断KickMCU 在中断服务函数ISR中将其置1。卡死说明 MCU 根本没有进中断坑 2SDK 底层中间件的“硬编码”通道为了让 Linux 触发 MCU 的中断试图在 MCU 测试代码中设置REMOTE_ID 2并监听Mailbox 2。但查阅原厂rpmsg_platform.c源码发现#else/* MCU use MBOX CH3 */cpu_id3;// --- 原厂 SDK 把 MCU 的通信通道硬编码成了 3#endif结论底层 SDK 强制监听 Mailbox 3 (通道 3)坑 3Linux 侧 GIC 的“半路截胡” (amp-irqs)在 Linux 的 DTS 中发现了一段针对 AMP 中断的路由配置amp-irqs /bits/ 64 /* MAILBOX */ GIC_AMP_IRQ_CFG_ROUTE(176, 0xd0, CPU_GET_AFFINITY(0, 2)); // 176号中断正是Mailbox2/3相关的中断结论这段代码的作用是强行把 Mailbox 的中断路由给 Cortex-A7 (CPU 2) 处理。Linux 发送了中断结果被 Linux 自己的 GIC 截获了Cortex-M0 听不到信息必须在 DTS 中删掉或注释掉这段配置。3. 解决方法只需要保证两端 ID 对齐并打开所有中断通路。第一步Linux 侧设备树 (DTS) 调整1. 修改 rpmsg 节点指定mailbox3与link-id3rpmsg: rpmsg3c00000 { compatible rockchip,rpmsg; mbox-names rpmsg-rx, rpmsg-tx; /* 接收用 mailbox0发送用 mailbox3 (适配MCU底层硬编码的cpu_id3) */ mboxes mailbox0 0 mailbox3 0; rockchip,vdev-nums 1; /* 匹配 MCU 的 ID */ rockchip,link-id 0x03; reg 0x03c00000 0x200000; memory-region rpmsg_reserved, rpmsg_dma_reserved; status okay; }; /* 确保 mailbox3 使能 */ mailbox3 { rockchip,txpoll-period-ms 1; status okay; };2. 移除抢占中断配置找到rockchip_amp节点删掉或注释掉amp-irqs属性防止 Linux GIC 截胡。。