第 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_addr>

echo "rpmsg-raw" > create_ept

3. 检查是否生成了设备文件

ls -l /dev/rpmsg0

12.3 深度实战:编写 Linux C 应用读取 IMU 数据

现在我们可以像读串口一样编写 C 语言程序。

#include <stdio.h>

#include <fcntl.h>

#include <unistd.h>

#include <string.h>

int main() {

int fd;

char buf256;

/* 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) {

buflen = '\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 accel3;

int16_t gyro3;

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.h>

struct pollfd fds1;

fds0.fd = fd;

fds0.events = POLLIN;

if (poll(fds, 1, 1000) > 0) { // 1秒超时

if (fds0.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 应用层的控制台上。

相关推荐
川石课堂软件测试7 小时前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试
m0_715646767 小时前
20260720
linux·arm
寒晓星7 小时前
[linux]线程及多线程
linux·运维
辰痕~7 小时前
物理机装Linux操作系统(Ubuntu为例)
linux·ubuntu
慧一居士8 小时前
Linux如何设置固定的静态ip
运维
十月的皮皮8 小时前
stm20260720-从新手 C 到量产 STM32 工程:程序设计推导指南
c语言·开发语言·stm32·stm32cubemx·hal库
开发笔记-阿牛9 小时前
解析一款有意思的产品||CK6159A语音芯片设计的儿童专注力训练机-舒尔特玩具
stm32·单片机·嵌入式硬件·音频
X7x59 小时前
跨厂商路由引入(重发布)实战指南:华为、华三、思科的逻辑差异与配置避坑
网络协议·信息与通信·信号处理·实施路由引入
国服第二切图仔9 小时前
13其他工具 - Skill/LSP/Sleep等
linux·运维·里氏替换原则
玩转4G物联网10 小时前
FS800DTU 新品上线|免费使用 DMP 设备管理平台,支持远程批量配置 & OTA 升级
物联网·网络协议·tcp/ip·云平台·核心板·fs800dtu·iot管理平台