MilkV Duo 核间通信分析
一直对 milkv duo 的大小核 Linux 和 FreeRTOS 之间的交互很好奇,但苦于目前相关的资料还很少,就根据目前官方的文档和源码先简单分析一下吧,本人为 Linux 新手,很多理解错误或不到位的地方还希望大家指正补充。
官方文档示例
首先分析官方文档中的一个点灯示例:简介 | Milk-V
文档中给出一个在大核 Linux 中运行的 .c 文件,调用小核的 FreeRTOS 进行点灯。
#define RTOS_CMDQU_DEV_NAME "/dev/cvi-rtos-cmdqu"
int fd = open(RTOS_CMDQU_DEV_NAME, O_RDWR);
这里可以看出运行 FreeRTOS 的小核被描述为一个设备,对应为 /dev/cvi-rtos-cmdqu
Linux 通过其进行访问。
struct cmdqu_t cmd = {0};
cmd.ip_id = 0;
cmd.cmd_id = CMD_DUO_LED;
cmd.resv.mstime = 100;
cmd.param_ptr = DUO_LED_ON;
ret = ioctl(fd , RTOS_CMDQU_SEND_WAIT, &cmd);
并通过 ioctl 对小核 RTOS 设备进行控制 (ioctl
的具体用法和支持的操作取决于设备和设备驱动程序。)
分析 ioctl 是大小核通信的关键部分,Linux 内核中是使用 mailbox 驱动,猜测其与 ioctl 的具体实现相关。
官方源码
大核Linux
https://github.com/milkv-duo/duo-buildroot-sdk/tree/develop/linux_5.10/drivers/soc/cvitek/rtos_cmdqu 通过该文件夹中的源码,分析 Linux 核间通信实现。
cvi_mailbox.h 为 mailbox 相关声明;
cvi_spinlock.c/.h 为自旋锁实现,用于线程通讯时同步保护;
rtos_cmdqu.c/.h 为与小核 RTOS 交互消息队列的主要部分。
在 rtos_cmdqu.h 文件中又能看到对小核 RTOS 设备的描述:
#define RTOS_CMDQU_DEV_NAME "cvi-rtos-cmdqu"
向外提供以下几个向消息队列发送消息的api:
int rtos_cmdqu_send(cmdqu_t *cmdq);
int rtos_cmdqu_send_wait(cmdqu_t *cmdq, int wait_cmd_id);
在 rtos_cmdqu.c 文件中可以找到 ioctl
的具体实现:
static long cvi_rtos_cmdqu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
实现了 IOCTL 处理程序(cvi_rtos_cmdqu_ioctl
)以处理特定的 ioctl 命令,包括 RTOS_CMDQU_SEND
、RTOS_CMDQU_SEND_WAIT
和 RTOS_CMDQU_SEND_WAKEUP
。其中调用 rtos_cmdqu_send
等向小核发起通信,rtos_cmdqu_send
中使用自旋锁进行同步保护,通过 mailbox 机制访问共享内存。
大核 Linux 通过 request_irq
注册中断处理函数:
err = request_irq(mailbox_irq, rtos_irq_handler, 0, "mailbox",
(void *)ndev);
在 rtos_irq_handler
中通过 mailbox 机制访问读取共享内存,中断号 mailbox_irq
通过 platform_get_irq_byname
获取:
mailbox_irq = platform_get_irq_byname(pdev, "mailbox");
小核RTOS
rtos_cmdqu.h 中多出了以下操作:
#define RTOS_CMDQU_REQUEST _IOW('r', CMDQU_REQUEST, unsigned long)
#define RTOS_CMDQU_REQUEST_FREE _IOW('r', CMDQU_REQUEST_FREE, unsigned long)
riscv64 该文件夹中可以找到提供的 led io 操作,以及 FreeRTOS 中负责核间通信的主要部分 comm_main.c ,其中使用命令队列 queHandle 存储来自 Linux 的命令,并创建了一个名为 CMDQU 的任务,用于处理核间通信,根据Linux 的指令进行控制处理。接受来自 Linux 的命令是在中断服务中进行,通过 xQueueSendFromISR 将接受到的命令存储到命令队列中。
总结
以上就是目前 milkv duo 大小核之间通信的简单分析,通过自旋锁进行同步保护,使用中断进行通知触发,通过 mailbox 的机制访问共享内存进行通讯。