E907 核心固件加载
在调试阶段,需要经常修改 E907 的代码。而为了调试代码多次刷写系统非常麻烦。其实 E907 核心的固件可以在 Linux 系统内加载,本文将描述如何在 Linux 系统内启动 E907 核心、加载 E907 固件、关闭 E907 核心。
如何加载
从上一篇文章可以知道,这里使用 remoteproc
管理小核的生命周期。 上一篇文章:详解全志V853上的ARM A7和RISC-V E907之间的通信方式remoteproc
框架抽象出硬件差异,允许不同的平台/架构来控制(开机、加载固件、关机)这些远程处理器,此外,还为支持这种通信的远程处理器添加了 rpmsg
virtio
设备。这样,特定平台的 remoteproc
驱动程序只需要提供一些低级处理程序,然后所有 rpmsg
驱动程序就可以正常工作。
作用:
从文件系统加载固件
准备远程处理器所需资源
注册一个rpmsg virtio
设备
提供对要提供对远程处理器的生命周期进行管理
所以固件的加载流程大致如下:
1. 加载固件 1. 调用 firmware 接口获取文件系统中的固件 2. 解析固件的 resource_table 段,该段有如下内容 1. 声明需要的内存(Linux 为其分配) 2. 声明使用的 vdev(固定为一个) 3. 声明使用的 vring(固定为两个) 3. 将固件加载到指定地址 2. 注册 rpmsg virtio 设备 1. 提供 vdev->ops(基于 virtio 接口实现的) 2. 与 rpmsg_bus 驱动匹配,完成 rpmsg 初始化 3. 启动小核 1. 调用 rproc->ops->start
Kernel 的配置
首先需要配置设备树,预留 E907 核心内存,buffer
内存,vring
内存等。并正确配置 rproc
与 rpbuf
,也不要忘记配置 firmware-name
,下面的配置示例为测试固件所使用的地址。不同的固件地址可能不同。
reserved - memory { e907_dram : riscv_memserve { reg = < 0x0 0x48000000 0x0 0x00400000 > ; no - map ; }; vdev0buffer : vdev0buffer @47000000 { /* 256k reserved for shared mem pool */ compatible = "shared-dma-pool" ; reg = < 0x0 0x47000000 0x0 0x40000 > ; no - map ; }; vdev0vring0 : vdev0vring0 @47040000 { reg = < 0x0 0x47040000 0x0 0x20000 > ; no - map ; }; vdev0vring1 : vdev0vring1 @47060000 { reg = < 0x0 0x47060000 0x0 0x20000 > ; no - map ; }; };e907_rproc : e907_rproc @0 { compatible = "allwinner,sun8iw21p1-e907-rproc" ; clock - frequency = < 600000000 > ; memory - region = <& e907_dram > , <& vdev0buffer > , <& vdev0vring0 > , <& vdev0vring1 > ; mboxes = <& msgbox 0 > ; mbox - names = "mbox-chan" ; iommus = <& mmu_aw 5 1 > ; memory - mappings = /* DA len PA */ /* DDR for e907 */ < 0x48000000 0x00400000 0x48000000 > ; core - name = "sun8iw21p1-e907" ; firmware - name = "melis-elf" ; status = "okay" ; };rpbuf_controller0 : rpbuf_controller @0 { compatible = "allwinner,rpbuf-controller" ; remoteproc = <& e907_rproc > ; ctrl_id = < 0 > ; /* index of /dev/rpbuf_ctrl */ iommus = <& mmu_aw 5 1 > ; status = "okay" ; };rpbuf_sample : rpbuf_sample @0 { compatible = "allwinner,rpbuf-sample" ; rpbuf = <& rpbuf_controller0 > ; status = "okay" ; };
接下来需要配置 kernel
选项,配置驱动。
并勾选以下驱动:
Device Drivers ---> Remoteproc drivers ---> <*> SUNXI remote processor support Rpmsg drivers ---> <*> allwinnertech rpmsg driver for v853 - e907 <*> allwinnertech rpmsg hearbeat driver <*> Virtio RPMSG bus driver <*> sunxi rpmsg ctrl driver [* ] Mailbox Hardware Support ---> <*> sunxi Mailbox <*> sunxi rv32 standby driver
加载小核固件
烧录启动系统后,可以在 /sys/kernel/debug/remoteproc/
节点找到 remoteproc0
我们可以使用 cat
命令检查小核目前的状况
cat / sys / kernel / debug / remoteproc / remoteproc0 / state
可以看到目前是 offline
的。可以尝试使用 echo
启动小核
echo start > / sys / kernel / debug / remoteproc / remoteproc0 / state
可以看到,由于我们没有加载固件,小核启动失败。此时我们需要把准备好的固件放置到开发板的 lib/firmware
文件夹内。这里我们使用 adb
上传小核固件。
!
然后我们将固件名称置于 firmware
节点内,并启动固件。
echo e907_test .elf > / sys / kernel / debug / remoteproc / remoteproc0 / firmware echo start > / sys / kernel / debug / remoteproc / remoteproc0 / state
此时可以看到 remote processor e907_rproc is now up
,同时查看状态也显示了 running
此时也可以用 stop
命令停止小核运行
echo stop > / sys / kernel / debug / remoteproc / remoteproc0 / state
测试小核
在测试之前我们先把 kernel
侧的设备树中 uart3
禁用,使小核可以使用 uart3
外设打印日志。
& uart3 { pinctrl - names = "default" , "sleep" ; pinctrl - 0 = <& uart3_pins_active > ; pinctrl - 1 = <& uart3_pins_sleep > ; uart - supply = <& reg_dcdc1 > ; status = "disabled" ; };
如果不禁用 uart3
会出现错误提示:
uart : create mailbox fail uart : irq for uart3 already enabled uart : create mailbox fail
然后将调试串口连接到 UART3
排针,加载固件。
echo e907_test .elf > / sys / kernel / debug / remoteproc / remoteproc0 / firmware echo start > / sys / kernel / debug / remoteproc / remoteproc0 / state
便可以启动小核的固件