1. 核间通信组件简介
目前针对不同级别的操作系统,存在几种核间通信组件,分别是以Linux内嵌组件RPMsg、支持跨平台移植的OpenAMP,短小精简的RPMsg-Lite,这三个组件在代码细节、收发策略、移植性上各有优劣,用户可根据需要选择。它们起初都来源于Linux的RPMsg,遵循统一的协议标准(交互过程,内存格式),主要依赖硬件的共享内存和核间中断。和TCP/IP层次结构类似,按照ISO/OSI的层次化结构模型,三个核间通信组件均可分为三层,如下图所示。
1.1 RPMsg(Linux)
在AMP系统中,不同的内核协作的最常见的方式是使用共享内存通信,这样方式效率最高,其中有许多系统自定义的实现,单这也导致不同系统之间不能互联。为了解决这个问题,TI(德州仪器)在Linux内核中提供了remoteproc 和 RPMsg 基础设施使在主处理器上运行的 Linux 应用程序能够管理远程处理器/固件的生命周期,并使用它们执行 IPC。
1.1 OpenAMP(RTOS)
OpenAMP框架包含提供了三个重要组件:Virtio、RPMsg和Remoteproc。Remoteproc实现了主处理器对远程处理器程序的加载、启停远程处理器,实现对远程处理器的生命周期管理;RPMsg依托Virtio实现了主处理器和远程处理器之间的核间通信。
1.1 RPMsg-Lite(BareMetal)
RPMsg-Lite组件是远程处理器消息传递 (RPMsg) 协议的轻量级实现。RPMsg 协议定义了一个标准化的二进制接口,用于在异构多核系统中的多个核之间进行通信。与开放非对称多处理 (OpenAMP) 框架的 RPMsg 实现相比,RPMsg-Lite 减少了代码大小、简化了 API 并改进了模块化。在较小的基于 的系统上,比如裸机系统,建议使用 RPMsg-Lite。RPMsg-Lite 是由 NXP Semiconductors 开发的开源组件,并在 BSD 兼容许可下发布。
2. 核间通信组件的作用
2.1 共享内存缓冲队列管理
对于核间通信来说,两个CPU核同时访问同一个共享内存,如何实现同步实现资源互斥访问是一个需要重点考虑的问题,这里就使用的是数据链路层的virtIO来实现的,详见RPMSG详解-VirtIO。
2.2 多通道、多端点管理
对于异构多核的SOC来说,存在多个CPU核,一个CPU主核可能需要同时和多个CPU从核进行核间通信,因此需要对多个CPU核进行管理通道管理。
对于一个CPU核来说,可能需要运行不同的应用,每个应用需要通信的数据长度,实时性等均存在不同需求,因此需要在通道的管理上再增加端点的管理,类似同一个网卡可以使用不同的端点号建立多个UDP链接,方便应用使用。这部分主要由传输层的RPMsg实现,详见RPMSG详解-RPMsg。
因涉密原因,在此不叙述具体的核间通信设计方案,以下只说明性能优化上需要注意的要点,因为这部分在网上还没有一个博主进行过详细说明。
3. 性能优化
3.1 接收性能
接收性能的主要耗时是共享内存到内核缓冲的数据拷贝,Linux中的VirtIO模块仅支持对vring_buf进行cache flush操作,对于buf的描述结构体vring_rx和vring_tx是需要配置为uncache属性的,这也是imx和zynq的RPMsg参考代码都是使用的uncache的方式初始化共享内存(但是这种方式的性能差很多),因此最优的做法应该是将共享内存的空间分为描述符和buf两段,前者设置为uncache属性,后者设置为cache属性,并开启IOMMU。经过实际性能对比测试,性能可提升6倍。
3.1 发送性能
Linux和OpenAMP的发送阻塞策略不一样,Linux的策略是等到event唤醒线程或者15秒超时唤醒;而OpenAMP的策略是固定睡眠1ms后唤醒线程检查是否有数据需要发送。
因此Linux发送的时候,如果RTOS没有及时读取,很容易在发送一段时间后出现Linux发送进程睡眠而导致发生性能骤降甚至停止,解决的方法是要在RTOS中增加接收完成后发送中断通知机制,Linux接收到接收完成命令后调用event_wakeup唤醒发送线程。
参考资料:
[1] https://github.com/OpenAMP/open-amp
[2] https://github.com/nxp-mcuxpresso/rpmsg-lite
标签:RPMsg,间通信,处理器,Linux,组件,OpenAMP From: https://www.cnblogs.com/mic-chen/p/18217210