FASTBOOT 异构 RAMDISK
在快启流程中,除了启动 BOOT、KERNEL 阶段的性能优化,还有启动到内核中 ROOTFS 加载速度提升。
SDK 支持异构 RAMDISK 模式,相较于传统快启 RAMDISK 模式,异构 RAMDISK 通过异构系统,加速 RAMDISK 的读取和解压启动。并且保证系统的独立与并行。
传统快启 RAMDISK 的加载流程如下
- BOOT 初始化 FLASH,加载内核和 RAMDISK
- 加载后将 FLASH 驱动,DMA 参数保存到预留内存,跳转进入内核
- Linux 在初始化阶段,启动一个内核线程使用 BOOT 阶段预留的 RAMDISK 压缩的地址,开始解压,使用硬件或软件解压
- 解压后启动 RAMDISK 中的应用程序,执行应用

传统快启 RAMDISK 的缺点也很明显,需要内核参与,需要预留内存给 RAMDISK 使用,RAMDISK 需要打包在一起,OTA 更新 KERNEL 的时候也需要 OTA RAMDISK。
异构 RAMDISK 通过最大化系统资源,在 BOOT 阶段就启动双核系统,单独使用一个核心操作 FLASH 进行 RAMDISK 的读取解压操作,此时内核无需调度解压读取,当 RAMDISK 解压完成的同时通知内核可以挂载 RAMDISK,此时直接启动 RAMDISK 中的应用程序。
其优点如下:
- 无需魔改内核,增加解压线程
- 复用内核 RAMDISK 流程,对于内核来说与主线标准 RAMDISK 无差异
- RAMDISK 可以放到分区上,支持直接
dd命令 OTA 更新 RAMDISK - SDK 配置简单,SDK 支持自动打包 RAMDISK,支持 Quick Config 一键切换

异构 RAMDISK 功能配置
Linux 端相关配置
设备树预留内存配置
首先设备树需要配置 RAMDISK 的预留内存,与标准配置无异
linux,initrd-start = <0x47800000>;
linux,initrd-end = <0x48000000>;
预留内存的大小需要参考 RAMDISK 的大小,一般布局如下:
举个例子,RAMDISK 的大小是 6M,经过 LZ4 压缩后的大小是 2M,所以这里需要配置总共 8M 内存
- RAMDISK 解压后的数据:
0x47800000~0x47e00000 - RAMDISK 压缩后的数据:
0x47e00000~0x48000000 - 设备树预留内存的配置:
0x47800000~0x48000000
这部分内存在内核加载完成 RAMDISK 后会释放,所以不需要担心这部分内存有浪费或者无法被使用到
如果系统使用多媒体内存池,建议将 RAMDISK 的地址安排到多媒体内存池之前,多媒体内存池是从内存末尾申请的,如果内存末尾配置了 RAMDISK,则会导致多媒体内存池占用在内存中部,造成内存碎片化。一般建议可释放的内存连续排布,释放后可以改善内存碎片化的情况。
如下图,多媒体内存池占用了 32M 的内存,则按照之前的排布修改如下
- RAMDISK 解压后的数据:
0x45800000~0x45e00000 - RAMDISK 压缩后的数据:
0x45e00000~0x46000000 - 设备树预留内存的配置:
0x45800000~0x46000000

设备树驱动配置
对于使用 RAMDISK 的情况,一般来说存储控制器驱动加载就可以延后了,因为存储控制器驱动比较占用启动时间,需要通讯识别等操作。所以推荐对于系统存储的控制器节点配置为 deferred-device,例如这里将 SPIF 控制器配置为 deferred-device

内核选项配置
内核还需要配置启用 RAMDISK 功能
CONFIG_BLK_DEV_INITRD
配置位于
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

由于不需要内核解压 RAMDISK,所以下面的 RAMDISK 压缩配置可以全部取消。
# CONFIG_RD_GZIP is not set
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
# CONFIG_RD_ZSTD is not set
配置异构 RAMDISK 内核服务模块
CONFIG_AW_PARALLEL_RAMDISK=y
CONFIG_AW_RAMDISK_DELAYINIT_RPROC_NAME="6010000.e907_rproc"
内核配置选项是
General setup --->
[*] Parallel decompress ramdisk
(6010000.e907_rproc) Ramdisk Delay Init Rproc Name

这里的 Ramdisk Delay Init Rproc Name 配置的名字是异构核心的名字,可以在系统启动后运行
ls /dev/rpmsg_ctrl*

这里的 e907_rproc@06010000 就是异构核心的名字,填入的时候需要改一下格式,改为 6010000.e907_rproc 即可
如果不方便启动系统看配置,可以检查内核设备树 bsp/configs/linux-6.6-xuantie/sun252iw1p1.dtsi

RTOS 端功能配置
异构 RAMDISK 的主要操作基本上在 RTOS 端,所以 RTOS 端的配置需要更加注意。
配置 RTOS 存储驱动
SPI NOR 存储驱动配置
Drivers Options --->
soc related device drivers --->
AW Flash Drivers --->
[*] Tina Flash Read
Select Storage Type (SPINOR) --->
[*] Flash Wait for Flag
(0) Flash Wait RTC Data Index
(2) Flash Wait RTC Data Bit
(4064) Flash GPT Offset
(128) Flash Boot Package Offset
存储配置驱动项如下:
CONFIG_DRIVERS_AW_FLASH_READ=y
CONFIG_DRIVERS_AW_FLASH_READ_SPINOR=y
# CONFIG_DRIVERS_AW_FLASH_READ_EMMC is not set
# CONFIG_DRIVERS_AW_FLASH_READ_SPINAND is not set
CONFIG_DRIVERS_AW_FLASH_WAIT_FLASH=y
CONFIG_DRIVERS_AW_FLASH_WAIT_FLASH_WAIT_INDEX=0
CONFIG_DRIVERS_AW_FLASH_WAIT_FLASH_WAIT_BIT=2
# CONFIG_DRIVERS_AW_FLASH_WRITE is not set
CONFIG_DRIVERS_AW_FLASH_GPT_OFFSET=4064
CONFIG_DRIVERS_AW_FLASH_BOOTPKG_OFFSET=128
# CONFIG_DRIVERS_AW_FLASH_DEBUG is not set
# CONFIG_DRIVERS_AW_FLASH_USE_HWLOCK is not set

- 选择
CONFIG_DRIVERS_AW_FLASH_READ驱动 - 配置使用的 FLASH 类型,这里选择 SPI NOR
- 配置
[*] Flash Wait for Flag,设置 FLASH 的等待标志,这里按默认即可 - 配置 FLASH 的 GPT OFFSET,配置需要与 FLASH MAP 一致,需要找到
uboot-board.dts中的flash_map参考下图配置即可

配置 RTOS 解压组件
一般 RAMDISK 支持多组压缩格式,这里就以常用的 LZ4 为例,示意驱动配置。进入如下配置界面:
System components --->
thirdparty components --->
[*] Compress Support --->
[*] LZ4 Compress
配置项目如下:
CONFIG_COMPONENTS_COMPRESS=y
CONFIG_COMPONENTS_COMPRESS_LZ4=y

如果需要使用其他压缩格式,这里也可以配置其他压缩,勾选上即可,组件会自动识别加载的 RAMDISK 是哪一种压缩格式。
配置 RTOS 异构 RAMDISK 组件
配置完成后,另外还需要配置 RTOS 的异构 RAMDISK 组件,配置路径如下所示:
System components --->
aw components --->
AW Fastboot Preloads Compenents --->
[*] Fastboot Preloads Compenents
(spif) Preloads compenents rpmsg notify name
Select Preload Components Type (Ramdisk) --->
[*] Load kernel ramdisk
(0x47e00000) kernel ramdisk load address
(0x200000) kernel ramdisk compress size
(0x47800000) kernel ramdisk decompress address
(0x600000) kernel ramdisk decompress size
相关的地址需要参考设备树配置的预留地址。配置项如下
CONFIG_PRELOAD_COMPENENTS=y
CONFIG_PRELOAD_COMPENENTS_RPMSG_NOTIFY_NAME="spif"
CONFIG_PRELOAD_COMPENENTS_RPMSG_NOTIFY_PARA=""
CONFIG_USE_PRELOAD_RAMDISK=y
# CONFIG_USE_PRELOAD_ROOTFS is not set
CONFIG_PRELOAD_RAMDISK=y
CONFIG_RAMDISK_LOADADDR=0x47e00000
CONFIG_RAMDISK_PARTITION_SIZE=0x200000
CONFIG_RAMDISK_DECOMPRESS_ADDR=0x47800000
CONFIG_RAMDISK_DECOMPRESS_SIZE=0x600000

增加异构 RAMDISK 启动流程
修改 RTOS 的 main 函数,新增 RAMDISK 启动流程代码,例如在 rtos/lichee/rtos/projects/v861_e907/bga_perf1/src/main.c 中,找到 cpu0_app_entry 函数,这样添加代码
#ifdef CONFIG_PRELOAD_COMPENENTS
extern void flash_load_data_async(void);
flash_load_data_async();
#endif

配置打包 RAMDISK 功能
SDK 提供一套简单的脚本去打包 RAMDISK,在执行 PACK 命令的时候,自行去打包 RAMDISK,生成 RAMDISK 镜像,配置方法如下:
首先复制 device/config/chips/v861/configs/default/ramdisk 文件夹到板级目录下,作为 RAMDISK 的基础环境。
然后在板级目录下新建一个 ramdisk_json 配置文件作为打包配置文件。使用脚本自动打包 RAMDISK 环境。

{
"compress": "lz4",
"src": "${configs}/ramdisk",
"auto_copy": {
"lib/ld-musl-riscv32.so.1": "${rootfs}/lib/ld-musl-riscv32.so.1",
"lib/libgcc_s.so.1": "${rootfs}/lib/libgcc_s.so.1",
"usr/lib/libc.so": "${rootfs}/usr/lib/libc.so"
},
"cmd": [
"mkdir -p ${src}/bin",
"find ${rootfs}/bin/ -type l -exec cp -d {} ${src}/bin \\;",
"[ -e ${rootfs}/bin/busybox ] && cp ${rootfs}/bin/busybox ${src}/bin"
]
}
这个配置的含义解释:
- compress: 指定了 RAMDISK 的压缩格式,这里使用的是
lz4。LZ4 是一种快速压缩算法,通常用于高效地压缩数据,尤其是在 RAMDISK 中能显著减少内存占用。 - src: 这是 RAMDISK 固件的源文件位置。
${configs}/ramdisk是一个变量,表示实际路径应该在配置文件中定义。 - auto_copy: 这个字段定义了一系列文件的自动复制操作,将源文件复制到目标文件系统的指定位置。具体文件及其对应的目标路径。这些操作确保了 RAMDISK 中所需的共享库和可执行文件被正确地放置在文件系统的相应位置。
- cmd: 这是一个命令数组,包含一些 shell 命令,要在执行时运行。命令的功能如下:
mkdir -p ${src}/bin: 创建一个名为bin的目录,位于指定的 RAMDISK 源位置。如果路径中某些目录不存在,-p参数将确保创建它们。find ${rootfs}/bin/ -type l -exec cp -d {} ${src}/bin \\;: 查找${rootfs}/bin/目录下的所有符号链接,并将其复制到刚刚创建的${src}/bin目录中。-d参数确保复制符号链接而不是链接指向的文件。[ -e ${rootfs}/bin/busybox ] && cp ${rootfs}/bin/busybox ${src}/bin: 如果${rootfs}/bin/busybox存在,则将其复制到${src}/bin目录中。
这里 auto_copy 主要是拷贝用户程序和相关的依赖库到 RAMDISK 中,如果有新增的 app 需要在这里添加,注意不要让 RAMDISK 变太大,否则加载速度可能会更慢。
cmd 主要是拷贝 busybox 运行环境到 RAMDISK 中,一般不需要改。
如果需要新增一个 app 打包到 RAMDISK 中,在 auto_copy 里新增相关的拷贝即可。如果文件不需要拷贝,可以直接放到 ramdisk 文件夹中,也会打包进去。
配置打包 RAMDISK 分区
修改分区表,新增一个 RAMDISK 分区,名称必须是 ramdisk,大小依照打包出的文件大小可以裁剪

新增分区之后别玩同步分区布局到设备树,执行 quick_config sync_partition_{xxx}_to_bootargs 同步修改到 bootargs 中.
否则会出现分区表不同步导致加载不上 rootfs 的问题

配置 RAMDISK 启动脚本
设备树,配置 RAMDISK 和正常 INIT 的脚本为 RAMDISK 的路径,这样配置使 Kernel 初始化可以找到运行的 init 环境。

修改 RAMDISK 中的 init 脚本,路径 device/config/chips/v861/configs/bga_perf1/ramdisk/init

可以在红框处添加应用的启动命令,当 RAMDISK 初始化的时候便去执行相关命令。

测试 RAMDISK 功能
此时编译系统,打包烧录,查看启动时的大核和小核日志。
在小核的日志中,可以看到 RAMDISK 的相关打印

可以看到 Linux 端也是通过 RAMDISK 启动的

至此快启异构 RAMDISK 功能就算配置完毕了
常见问题
RTOS 打印 get_boot_param failed

请确认配置 FLASH 的 GPT OFFSET,配置需要与 FLASH MAP 一致,需要找到 uboot-board.dts 中的 flash_map 参考下图配置即可
