第 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 应用层的控制台上。

相关推荐
不做菜鸟的网工2 天前
BGP特性
网络协议
AlfredZhao2 天前
生产环境里,为什么不建议把普通端口直接暴露到公网?
linux·https·443·80
戴为沐3 天前
Linux内存扩容指南
linux
zylyehuo4 天前
Linux 彻底且安全地删除文件
linux
明月_清风4 天前
开发者网络概念全扫盲:一篇搞定
后端·网络协议
刘马想放假4 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
用户805533698034 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297914 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
乘云数字DATABUFF4 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
王二端茶倒水5 天前
一套可落地的无线运营方案,不能只管 AP,还要管用户、计费和运维
网络协议