第 10 章:OpenAMP 实战——构建 M33 与 Linux 的 RPMsg 消息隧道

在多核系统中,M33 采集到的 IMU 数据如果只能从自己的串口打印,那 A35 侧的 GUI 和云端应用就成了摆设。我们要建立一套标准化的通讯协议------OpenAMP (Open Asymmetric Multi-Processing) 。它基于 virtio 队列和 RPMsg 总线,是异构多核交互的工业标准。


10.1 RPMsg 工作原理

RPMsg (Remote Processor Messaging) 就像是核间局域网。

  • 端点 (Endpoint):每个通讯频道都有一个地址(类似于端口号)。

  • 共享内存 :数据存放在第 7 章划定的 Shared Memory 中。

  • 中断通知 :M33 写完数据后,触发一个 IPCC (Inter-Processor Communication Controller) 中断通知 A35。


10.2 M33 侧:移植 OpenAMP 库

在 M33 工程中,我们需要引入 libmetalopen-amp 框架。STM32CubeMP2 SDK 已经提供了移植好的代码。

1. 初始化 OpenAMP 资源

/* 定义一个 RPMsg 终端 */

static struct rpmsg_endpoint my_endpoint;

void OpenAMP_Init(void) {

// 1. 初始化硬件邮箱 (IPCC)

MX_IPCC_Init();

// 2. 初始化 libmetal 环境

metal_init(&params);

// 3. 初始化 RPMsg 实例

MX_OPENAMP_Init(RPMSG_REMOTE, NULL);

// 4. 创建本地端点,等待 Linux 连接

rpmsg_create_ept(&my_endpoint, &rpmsg_vdev, "rpmsg-raw",

RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,

my_endpoint_cb, // 收到消息的回调函数

rpmsg_service_unbind);

}

10.3 深度实战:将 IMU 数据打包发送

我们要把第 5 章采集到的 IMU_Data_t 结构体,通过 OpenAMP 发往 A35。

void Send_IMU_To_Linux(IMU_Data_t *data) {

char msg_buf[128];

// 格式化为 JSON 或二进制,这里用简单的字符串便于调试

int len = snprintf(msg_buf, sizeof(msg_buf),

"IMU:%d,%d,%d", data->ax, data->ay, data->az);

// 发送数据到 Linux 侧

if (rpmsg_send(&my_endpoint, msg_buf, len) != RL_SUCCESS) {

// 如果发送失败(缓冲区满),可以记录丢包数

}

}

10.4 Linux 侧:开启 RPMsg 驱动支持

在 Linux 内核配置(make menuconfig)中,需确保以下模块开启:

  • CONFIG_RPMSG_CHAR(允许在用户态通过 /dev/rpmsgX 访问)

  • CONFIG_REMOTEPROC(远程处理器管理)

  • CONFIG_STM32_IPCC(硬件信箱驱动)


10.5 验证:Linux 端的"收件箱"

当 M33 运行并开启 OpenAMP 后,Linux 启动时会在控制台看到: virtio_rpmsg_bus virtio0: creating channel rpmsg-raw addr 0x400

你可以直接在终端测试:

查看生成的设备节点

ls /dev/rpmsg_ctrl*

绑定端点并读取数据

stty -F /dev/rpmsg0 raw

cat /dev/rpmsg0

如果你在屏幕上看到了 M33 发出的 IMU:xxx,xxx,xxx,恭喜你,跨核通讯的高速公路已经通车!


10.6 性能瓶颈:为什么不用读写锁?

这是回答你在开篇提到的痛点:

  • 传统读写锁:会导致 M33 等待 A35 释放总线,如果 A35 正在处理高负载 GUI 任务,M33 的采集就会被阻塞。

  • OpenAMP 方案 :它是异步非阻塞的。M33 只负责把数据丢进共享内存的环形队列(Ring Buffer),然后发个"敲门"信号(中断)就走。即便 A35 还没来得及看,M33 也可以继续采集下一帧。


10.7 避坑指南 (Debug Tips)

  • 陷阱:资源释放顺序。如果重启 A35 Linux,M33 侧必须检测到 RPMsg 链路断开并重置虚拟队列,否则 A35 无法再次连接。

  • 陷阱:内存属性不匹配。确保 Linux 和 M33 看到这块共享内存的 Cache 策略完全一致(建议全部设为 Non-cacheable)。

  • 陷阱:地址对齐。OpenAMP 的缓冲区对齐要求非常严格(通常 512 字节对齐),如果链接脚本没写好,会导致初始化失败。


章节小结

本章我们实现了多核协同的最核心能力:数据流转。M33 采集,Linux 消费。

相关推荐
S-码农1 小时前
Linux——互斥锁
linux·开发语言
Starry_hello world1 小时前
Linux 网络(6)
linux·运维·网络
Starry_hello world2 小时前
Linux 网络(5)
linux·网络·智能路由器
FakeOccupational2 小时前
【电路笔记 STM32】STM32CubeMX配置&自动移植FreeRTOS + STM32&FreeRTOS点灯的最简单示例
笔记·stm32·单片机
S-码农2 小时前
Linux——线程
linux
i建模2 小时前
通过Hyprland事件查看器(如`wev`)修改物理按键的扫描码
linux·运维
2501_918126912 小时前
stm32什么程序效率最高,体积小,运行快,适应广?
c语言·stm32·单片机·嵌入式硬件·学习
2501_918126912 小时前
stm32能做次声波发射器吗?
linux·stm32·嵌入式硬件·学习·个人开发
_OP_CHEN2 小时前
【Linux系统编程】(三十八)进程信号拓展:可重入函数 /volatile/SIGCHLD 全解析
linux·运维·进程·c/c++·信号·可重入函数·volatile