AMP 异构 功能简介
V821芯片包含两个CPU。一个是主核心RISC-V CPU,运行Tina Linux系统,为芯片主系统;一个是RISC-V MCU,运行FreeRTOS系统,主要功能是提供通用算力补充、辅助 Linux 实现休眠唤醒、低功耗管理以及 WIFI 相关功能。
这些不同架构的核心以及他们上面所运行的软件组合在一起,就成了 AMP 系统 (Asymmetric Multiprocessing System, 异构多处理系统)。
为了多核心协同工作,对于需要异构多核通信框架需要满足以下功能:
- 隔离核间差异,把一部分服务部署在一个核上,另一部分服务部署在另外的核上,应用层代码只需通过标准接口来申请服务,其对底层服务具体在哪个核上实现无感知。
- 同一个核,既可作为远程服务端,也可以作为客户端。
V821 异构启动引导
V821与之前的芯片有所不同,其启动核心是RISC-V MCU,通过RISC-V MCU来引导RISC-V CPU主核心启动。所以当系统上电时,芯片先启动 MCU 核,然后 MCU 核加载一段很小的代码启动 CPU 大核,大核继续执行下面的启动任务,此时小核会进入休眠模式,等待大核将 RTOS 固件加载给小核运行。详细启动流程如下:
- 首先,由芯片内部的BROM在RISC-V MCU上运行,并寻找启动介质(SDCARD/EMMC/SPI-NOR/SPI-NAND),并加载“BOOT0”(包含E907_BOOT和BOOT0)到 SRAM,然后跳转到 E907_BOOT 执行。
- E907_BOOT 启动 RISC-V CPU 并使其跳转到 BOOT0 执行。
- BOOT0 初始化 DRAM,从 FLASH 加载 OpenSBI、UBOOT、RTOS 到 DRAM。其中 RTOS 引导在 RISC-V MCU 上运行,此外引导 OpenSBI 在 RISC-V CPU 上运行。
- UBOOT最终加载引导Linux内核。
安全启动方案
对于安全启动方案,由于 SBOOT 不具备校验小核证书的能力,所以小核是由 U-Boot 引导加载的。SBOOT 只加载并校验 U-Boot 然后跳转执行 U-Boot。不加载小核和启动小核。
RTOS 固件
固件文件的后缀名为 .bin
,一般放置于 device/config/chips/v821/bin/amp_rv0.bin
内,虽然后缀名是 .bin
但是实际上是一个经过 strip
后的 ELF
文件,并非经过 objcopy
后的 .bin
文件。
SDK里小核固件保存的路径可以位于这些地方:
bin/*.bin
configs/*/bin/*.bin
configs/*/*/bin/*.bin
configs/*/*/*/bin/*.bin
如果后面的路径文件存在,它会覆盖前面路径中的文件。
示例说明
-
路径 1
device/config/chips/v821/bin/amp_rv0.bin
这个文件位于
bin
文件夹内,符合第一个路径模式bin/*.bin
,表示主目录下的bin
文件夹。 -
路径 2
device/config/chips/v821/configs/perf2/bin/amp_rv0.bin
这个文件位于
configs/perf2/bin/
路径下,符合第二个路径模式configs/*/bin/*.bin
。 假设该路径下的文件与第一个路径模式中的文件amp_rv0.bin
重名,则此文件会覆盖第一个文件。
文件覆盖规则
- 如果多个路径模式匹配到相同文件(例如
amp_rv0.bin
),后面的路径会覆盖前面的文件。- 例如,
device/config/chips/v821/configs/perf2/bin/amp_rv0.bin
将覆盖device/config/chips/v821/bin/amp_rv0.bin
。
- 例如,
通过这样的路径匹配与覆盖规则,可以精确控制文件的加载顺序与优先级。
AMP 软件框架介绍
从系统架构的角度来看,AMP框架主要由Linux端和RTOS端两部分组成。Linux端通过三大组件协同工作来实现异构通信,RTOS端则采用OPENAMP框架来实现通信和功能。具体内容如下:
Linux端组件
Linux端的AMP框架由以下三个关键组件组成:
- RPMSG:提供异构通信驱动框架,用于管理消息的发送和接收。
- VIRTIO:提供异构通信的实际数据交互区域,负责数据的传输和接收。
- REMOTEPROC:负责异构小核的加载、启动和停止操作,同时兼顾VIRTIO和共享内存的初始化。
这三大组件协同工作,确保了Linux端与RTOS端之间的有效通信与数据交换。
Virtio(虚拟化模块)
Virtio 是一个用于共享内存管理的虚拟设备框架。在 Virtio 中,vring
是指向数据缓冲区指针的 FIFO 队列,具有两个单向的 vring
:
- 一个
vring
专用于发送消息到远程处理器; - 另一个
vring
用于接收从远程处理器发来的消息。
这两个 vring
构成了一个环形结构,Linux 和 MCU 通过 vring
的缓冲区来共享数据。vring
的缓冲区即为两个处理器之间的共享内存(也称为 Vring buffer)。
RPMsg(远程处理器消息传递)
RPMsg 框架位于 Virtio 之上,是基于 Virtio 的消息总线。RPMsg 服务通过该框架实现,具有两个 vring
,分别用于发送和接收消息,vring
缓冲区即为共享内存。
RPMsg 基于 Virtio 的 vring
,利用这些 vring
向远程处理器发送消息或从其接收消息。当共享内存中有新消息时,mailbox 框架会通知处理器可以接收消息。
实际上,RPMsg 是基于 Virtio 的消息总线,主要用于实现消息传递。可以将 RPMsg 看作是与远程处理器通信的通道,每个通道都有一个本地源地址和远程目标地址,消息便通过这些地址进行传输。
RemoteProc(远程处理器控制)
RemoteProc 框架由 Texas Instruments 开发,之后 Mentor Graphics 基于此开发了 OpenAMP 软件框架。在此框架下,主处理器上的 Linux 操作系统可以管理远程处理器及其相关软件环境的生命周期,即启动和关闭远程处理器。
RemoteProc 框架的主要功能:
- 加载固件: 主处理器将 MCU 固件映像的代码段和数据段加载到 MCU 内存中,以便后续执行程序。
- 解析资源表: 解析 MCU 固件资源表,并设置相关资源(如固件各个段的起始地址、大小等信息,以及 Virtio 设备特性、
vring
地址、大小和对齐信息)。 - 启动/停止远程处理器: 控制 MCU 核心固件的启动和停止。
- 建立通信通道: 为与 MCU 的通信创建 RPMsg 通道。
- 监控与调试: 提供远程监控和调试服务,借助 sysfs 和 debugfs 文件系统进行直接交互。
RemoteProc 控制流程:
- 主处理器启动: 主处理器首先启动并引导协处理器启动。
- 加载固件: 主处理器通过 RemoteProc 框架加载远程处理器固件,并解析固件资源表,配置协处理器的系统资源,同时创建 Virtio 设备。
- 启动远程处理器: 主处理器启动远程处理器,远程处理器开始运行。
- 创建通信通道: 在远程处理器启动后,主处理器需要先创建 RPMsg 通道,并发送第一条消息后,双核才能进行核间通信并相互传输数据。
- 停止固件: 若需要停止远程处理器的运行,主处理器可以关闭固件,远端处理器停止执行。
RTOS端实现
RTOS端使用OPENAMP框架,功能实现与Linux端的RPMSG、VIRTIO、REMOTEPROC类似。然而,由于RTOS端不存在用户态与内核态、物理地址与虚拟地址的限制,RTOS端的实现相对更加简洁。
AMP 通信方式
通信采用中断和共享内存的方式进行。在这种机制下,Linux端和RTOS端可以高效地进行数据传输和任务同步。
AMP 系统在每个通信方向上都有两个缓冲区,分别是 USED
和 AVAIL
,这个缓冲区可以按照 RPMsg 中消息的格式分成一块一块链接形成一个环。
当主核需要和小核进行通信的时候可以分为四步:
- 主核先从USED中取得一块内存(Allocate)
- 将消息按照消息协议填充
- 将该内存链接到 AVAIL 缓冲区中(Send)
- 触发中断,通知辅助核有消息处理
反之,小核需要和主核通信的时候也类似:
- 小核先从AVAIL中取得一块内存(Allocate)
- 将消息按照消息协议填充
- 将该内存链接到 USED 缓冲区中(Send)
- 触发中断,通知主核有消息处理。
基于此,SDK 提供了 RPMsg 通讯接口和 RPbuf 通讯接口,具体使用方法请参阅对应文档。