第 12 章:Linux 侧 RPMsg 用户态驱动与数据接口

📅 发布时间:2026/7/10 6:14:06 👁️ 浏览次数:
第 12 章:Linux 侧 RPMsg 用户态驱动与数据接口
通过前面几章我们已经让 M33 在底层跑得飞快数据也通过 HSEM 或 OpenAMP 顶到了 A35 的门口。现在我们要解决 Linux 开发者最关心的问题如何在应用层User Space优雅、稳定地拿到这些数据在 Linux 侧我们通常不希望业务逻辑开发者去操作复杂的 VirtIO 寄存器而是提供一个标准的字符设备节点如/dev/rpmsg0。12.1 RPMsg 字符设备框架 (RPMSG_CHAR)Linux 内核提供了一个专用的辅助驱动rpmsg_char它能将 M33 侧定义的rpmsg-raw服务映射为文件描述符。M33 侧我们在第 10 章创建了名为rpmsg-raw的端点。Linux 侧内核检测到该名称后会在/sys/class/rpmsg/下生成控制接口。12.2 实战在 Linux 终端手动激活端点默认情况下Linux 可能不会自动为每个端点创建/dev节点。我们需要在 Linux 启动后执行以下操作# 1. 找到 M33 对应的控制器目录cd /sys/class/rpmsg/rpmsg_ctrl0# 2. 创建一个本地端点关联到 M33 的 rpmsg-raw 服务# 格式echo name src_addr dst_addrecho rpmsg-raw create_ept# 3. 检查是否生成了设备文件ls -l /dev/rpmsg012.3 深度实战编写 Linux C 应用读取 IMU 数据现在我们可以像读串口一样编写 C 语言程序。#include stdio.h#include fcntl.h#include unistd.h#include string.hint main() {int fd;char buf[256];/* 1. 打开 RPMsg 设备 */fd open(/dev/rpmsg0, O_RDWR);if (fd 0) {perror(Open /dev/rpmsg0 failed);return -1;}printf(Waiting for IMU data from M33...\n);/* 2. 阻塞读取数据 */while (1) {int len read(fd, buf, sizeof(buf) - 1);if (len 0) {buf[len] \0;/* 假设数据格式是第 10 章定义的 ACC:x,y,z;GYRO:x,y,z */printf(M33 Data: %s\n, buf);}}close(fd);return 0;}12.4 进阶如何处理二进制结构体字符串解析sprintf/sscanf非常耗费 CPU。在工业实战中我们通常直接传递二进制 Raw Data。注意M33 是 32 位A35 是 64 位。虽然两者都是小端模式但结构体对齐可能不同。/* 在 M33 和 A35 之间必须严格共享的头文件定义 */typedef struct __attribute__((packed)) {uint32_t timestamp;int16_t accel[3];int16_t gyro[3];uint16_t checksum;} IMU_Frame_t;/* A35 侧读取 */IMU_Frame_t frame;read(fd, frame, sizeof(IMU_Frame_t));12.5 异步监听使用 poll 提高效率如果你的 Linux 应用不仅要读 M33 数据还要处理网络、GUI 任务那么不能死等read。#include poll.hstruct pollfd fds[1];fds[0].fd fd;fds[0].events POLLIN;if (poll(fds, 1, 1000) 0) { // 1秒超时if (fds[0].revents POLLIN) {read(fd, buf, sizeof(buf));}}12.6 避坑指南权限问题默认情况下/dev/rpmsg0只有 root 权限。解法编写udev规则或者在启动脚本里chmod 666 /dev/rpmsg0。缓冲区限制RPMsg 默认单包上限通常是512 字节。如果你要传高清摄像头的一帧图像必须分包或者改用第 11 章的无锁队列DDR 映射。端点冲突如果 Linux 端点名和 M33 端点名不一致read将永远阻塞。总结 本章我们完成了核间通讯的最后一块拼图。现在IMU 数据已经从传感器经过 M33 的实时采集穿过共享内存隧道最终稳稳地出现在了 Linux 应用层的控制台上。