开发者分享 | 适用于HPM的RustSBI实现


HPMicro的MCU一直以高性能著称,之前也一直有想在HPM的MCU上运行Linux的想法。直到看见Linux 6.10中支持了RISC-V架构在S-mode中运行nommu内核,才下定决心开始在HPM6360上折腾nommu Linux。
RISC-V上的Linux启动流程
在ARM架构中,通常Linux的启动流程为:
而在具有S态的RISC-V架构中,通常的启动流程为:
SBI (Supervisor Binary Interface)
RISC-V架构中,存在着定义于操作系统之下的运行环境(Runtime)。这个运行环境不仅将引导启动RISC-V下的操作系统, 还将常驻后台,为操作系统提供一系列二进制接口,以便其获取和操作硬件信息。RISC-V给出了此类环境和二进制接口的规范,称为“监管者二进制接口”,即“SBI”。
SBI有多种实现,如Berkeley Boot Loader (BBL)、OpenSBI。而本次项目中使用的SBI实现为RustSBI。
RustSBI项目源于2020年清华操作系统夏令营,旨在使用Rust语言编写RISC-V指令集中的SBI实现,支撑上层系统软件比如操作系统的运行。在国际SBI实现列表中获得 编号四。具有以下功能:
多功能且可拓展的操作系统运行时
为物理机、虚拟机、模拟器提供支持和兼容性
支持RISC-V SBI规范v2.0
使用Rust编写,使用稳定版本的Rust工具链构建
由于HPM系列芯片的启动设备较为单一(XPI),且XPI的初始化工作已经在BootROM中完成并映射到地址空间中,同时为了加快启动速度,本项目最终没有移植U-Boot;而是基于RustSBI库,编写操作系统的Bootloader,实现SDRAM初始化、固件加载、设备树传递和内核跳转等功能,以及为操作系统提供监管者二进制接口(SBI)。
最终在HPM6360芯片上的启动流程如下:
启动镜像布局
部分实现细节
Zicntr指令集拓展支持
Linux内核中,使用了TIME和TIMEH这两个CSR寄存器来获取系统时钟用于调度。但HPM6360使用的Andes D45核心并没有实现这两个CSR寄存器,在执行csrrs rd, time, rs1或csrrs rd, timeh, rs1指令时会产生非法指令异常(Illegal Instruction)。这就需要软件在异常处理函数中模拟这两条指令的执行。
static inline cycles_t get_cycles(void)
{
return csr_read(CSR_TIME);
}
#define get_cycles get_cycles
static inline u32 get_cycles_hi(void)
{
return csr_read(CSR_TIMEH);
}
#define get_cycles_hi get_cycles_hi
#endif /* !CONFIG_RISCV_M_MODE */
#ifdef CONFIG_64BIT
static inline u64 get_cycles64(void)
{
return get_cycles();
}
#else /* CONFIG_64BIT */
static inline u64 get_cycles64(void)
{
u32 hi, lo;
do {
hi = get_cycles_hi();
lo = get_cycles();
} while (hi != get_cycles_hi());
return ((u64)hi << 32) | lo;
}
#endif /* CONFIG_64BIT */
arch/riscv/include/asm/timex.h:51
这里我使用了riscv-decode这个库对机器码进行解码。
1、触发非法指令异常后从mtval寄存器中读取到非法指令;
2、将其作为参数调用riscv_decode::decode() 函数进行解码,获取到CSR以及rd的值,判断是否为TIME:0xc01和TIMEH:0xc81这两个CSR寄存器;
3、如果是,则将MCHTMR外设中MTIME寄存器的值保存至rd寄存器中。并恢复现场并从异常指令的下一条指令开始执行;
4、如果不是,则将异常委托给Linux内核处理。模拟异常发生时的硬件行为,填充对应寄存器并更新mstatus:MPP,使异常返回后的特权级别为S-mode,最后将mepc寄存器覆盖为stvec的值,异常返回后将从Linux内核的异常处理函数入口开始执行。
SDRAM区域原子指令的支持
在调试过程中发现,HPM6360无法在SDRAM的地址范围中执行原子指令,会产生存储/原子指令访问错误异常(Store/AMO Access Fault)。而Linux内核中有部分操作调用了原子指令(例如加锁等同步操作),在CPU不支持原子指令的情况下Linux内核无法运行。这里同样可以基于异常对原子指令进行模拟。
1、AMO指令
在执行AMO指令时,会陷入存储/原子指令访问错误异常。同样的,我们需要从mepc指向的指令地址获取出错的原子指令,并进行模拟。
2、lr/sc
对于lr (Load Reserved) 和sc (Store Conditional) 指令的情况则有一些特殊。lr指令执行时会触发加载指令访问错误异常(Load Access Fault),但sc指令在执行时不会触发任何异常,rd寄存器的结果直接返回1,则就导致无法直接模拟该指令的执行。
这里我选择的解决办法是:在执行到lr指令时,先对lr指令进行模拟,然后查找后续内存地址中的sc指令,并将其替换为非法指令(实际使用的是csrrw zero, time, zero)。这样在执行到原先sc指令的位置时就会触发非法指令异常。在异常处理函数中,判断是否是原先替换指令的地址,如果是,则还原被替换的sc指令,并模拟指令执行,随后异常退出至下一条指令继续执行;如果不是,则将异常委托给内核处理。
设备树
/dts-v1/;
/ {
#address-cells = <0x01>;
#size-cells = <0x01>;
compatible = "hpmicro,hpm6360";
model = "HPMicro HPM6360 Evaluate Kit";
aliases {
serial0 = &uart0;
};
chosen {
bootargs = "earlycon=sbi console=hvc0 ignore_loglevel rootwait root=/dev/mtdblock0";
stdout-path = "hvc0";
};
memory@40000000 {
device_type = "memory";
reg = <0x40000000 0x02000000>;
};
cpus {
#address-cells = <0x01>;
#size-cells = <0x00>;
timebase-frequency = <1000000>;
cpu@0 {
phandle = <0x01>;
device_type = "cpu";
reg = <0x00>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv32imafdcp";
riscv,isa-base = "rv32i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicsr",
"zifencei", "zihpm";
mmu-type = "riscv,none";
interrupt-controller {
#interrupt-cells = <0x01>;
interrupt-controller;
compatible = "riscv,cpu-intc";
};
};
};
soc {
#address-cells = <0x01>;
#size-cells = <0x01>;
compatible = "simple-bus";
ranges;
rom@80400000 {
compatible = "mtd-rom";
reg = <0x80400000 0xC00000>;
bank-width = <1>;
};
uart0: uart0@f0040000 {
compatible = "hpmicro,hpm6360-uart";
reg = <0xf0040000 0x40>;
clock-frequency = <24000000>;
status = "okay";
};
};
};
实现效果
目前已经成功实现Linux 6.10内核启动引导,并传递设备树给内核。
coremark跑分结果:
~ # coremark
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 13913
Total time (secs): 13.913000
Iterations/Sec : 1437.504492
Iterations : 20000
Compiler version : GCC13.3.0
Compiler flags : -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O2 -g0 -fPIC -Wl,-elf2flt=-r -static -lrt
Memory location : Please put data memory location here
(e.g. code in flash, data on heap etc)
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0x382f
Correct operation validated. See readme.txt for run and reporting rules.
CoreMark 1.0 : 1437.504492 / GCC13.3.0 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
ramspeed测试结果,可以看出缓内的读取速度是非常快的,超出缓存范围后读取速度受限于SDARM的速度:
~ # ramspeed -b 2 -g 1 -m 1 -r
RAMspeed (GENERIC) v2.6.0 by Rhett M. Hollander and Paul V. Bolotoff, 2002-09
1Gb per pass mode
INTEGER & READING 1 Kb block: 1460.57 Mb/s
INTEGER & READING 2 Kb block: 1487.33 Mb/s
INTEGER & READING 4 Kb block: 1498.92 Mb/s
INTEGER & READING 8 Kb block: 1505.16 Mb/s
INTEGER & READING 16 Kb block: 1507.90 Mb/s
INTEGER & READING 32 Kb block: 1301.73 Mb/s
INTEGER & READING 64 Kb block: 116.71 Mb/s
INTEGER & READING 128 Kb block: 116.79 Mb/s
INTEGER & READING 256 Kb block: 116.81 Mb/s
INTEGER & READING 512 Kb block: 116.82 Mb/s
INTEGER & READING 1024 Kb block: 116.74 Mb/s
- |
- +1 赞 0
- 收藏
- 评论 0
本文由雪飘梦飞转载自先楫半导体HPMicro公众号,原文标题为:开发者分享 | 适用于HPM的RustSBI实现,本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。
相关推荐
【经验】先楫半导体MCU HPM6750使用JLINK调试下如何进行串口打印配置
在使用JLINK调试先楫半导体HPM6750EVK2开发板调试时遇到不知如何使用SEGGER Embedded Studio (以下简称SES)内置的虚拟串口打印工具,本文介绍正确配置串口打印工具的步骤。
OpenHarmony(鸿蒙)支持先楫MCU的开发环境搭建1:Ubuntu搭建
OpenHarmony是面向全场景、全连接、全智能时代、基于开源的方式,是搭建一个智能终端设备操作系统的框架和平台。先楫高性能MCU搭载OpenHarmony系统,强强联手,为行业客户打造系列创新解决方案。
先楫HPM5361EVK开发板测评
上海先楫半导体举办的HPM5361EVK开发板试用活动圆满结束,广大工程师和爱好者们踊跃参与此次试用并提交报告。HPM5361EVK是基于先楫HPM5300系列高性能RISC-V内核MCU的一款开发板。本文介绍先楫HPM5361EVK开发板测评。
国产高性能MCU又一力作,集成授权EtherCAT,助力工业伺服走向海内外
最近,先楫半导体发布中国首款拥有德国倍福公司正式授权EterhCAT从站控制器的高性能MCU产品HPM6E00系列,将国产高性能MCU在工业领域的应用推向新高度。
【应用】基于RISC-V的高主频MCU HPM6750用于LED大屏,双千兆以太网透传实现实时控制
基于RISC-V的高主频MCU能让LED大屏显示系统实现更高的驱动频率及更高的实时性。HPM6750是先楫半导体开发的采用RISC-V 内核、具有高主频及创新总线架构的双核高性能MCU,能通过双千兆以太网透传的方案加双核加持完美解决高速的链路设计。
OpenHarmony(鸿蒙)支持先楫MCU的开发环境搭建3:编译工程和固件烧录
OpenHarmony是面向全场景、全连接、全智能时代、基于开源的方式,是搭建一个智能终端设备操作系统的框架和平台。先楫高性能MCU搭载OpenHarmony系统,强强联手,为行业客户打造系列创新解决方案。
媒体视角 | 先楫半导体HPM6E00系列MCU填补国内空白,EtherCAT中国首授权
2023年12月先楫半导体正式推出中国首款拥有德国倍福公司正式授权EtherCAT从站控制器的高性能MCU产品HPM6E00系列。先楫半导体HPM6E00系列产品采用国际流行的RISC-V架构,主频高达600MHz,有单双核选项,集成了德国倍福公司授权的EtherCAT从站控制器,具备高性能运动控制、高实时工业以太网互联的特性。
OpenHarmony(鸿蒙)支持先楫MCU的开发环境搭建4:工程中代码结构说明
OpenHarmony是面向全场景、全连接、全智能时代、基于开源的方式,是搭建一个智能终端设备操作系统的框架和平台。先楫高性能MCU搭载OpenHarmony系统,强强联手,为行业客户打造系列创新解决方案。
【IC】有动静!先楫出了颗适用机器人的国内首款内嵌ESC高性能MCU——HPM6E00
先楫半导体(HPMicro)推出的新款MCU——HPM6E00,引发了外界的广泛关注。这家成立仅四年的公司,凭借“国内首款内嵌ESC的高性能MCU”,再次证明了其在MCU领域的创新实力。
【经验】先楫HPM6000系列双核MCU的使用和操作方法
本文通过对先楫半导体HPM6000系列双核MCU的使用方法、工程编译与调试、双核通信方式和资源分配等内容的介绍,全方位给大家介绍双核的使用和操作,让大家轻松玩转双核,完成更多的片上系统功能开发。
OpenHarmony(鸿蒙)支持先楫MCU的开发环境搭建2:GCC编译器和源码安装
OpenHarmony是面向全场景、全连接、全智能时代、基于开源的方式,是搭建一个智能终端设备操作系统的框架和平台。先楫高性能MCU搭载OpenHarmony系统,强强联手,为行业客户打造系列创新解决方案。
【经验】MCU HPM6750使用ISP烧录程序步骤及注意事项
先楫半导体推出的HPM6750是一款高性能MCU,采用双RISC-V内核,主频可达816MHz,使用自主的创新总线架构、高效的L1缓存和本地存储器,高达9220CoreMark和高达4651 DMIPS的MCU性能纪录;同时整个MCU还整合了一系列高性能外设。
【IC】先楫半导体最新款高性能MCU HPM5301,搭载单核32位RISC-V处理器,主频高达360MHz
先楫半导体于2023年11月24日宣布推出高性能HPM5300系列MCU最新款——HPM5301芯片。这款MCU搭载单核32位RISC-V处理器,采用QFN48封装,是迄今为止先楫推出的最简单易用的产品。该芯片的开发板HPM5301EVKLite也同步上市。
媒体专访:《用“芯”赋能,先楫半导体助力伺服驱动迈向高效、智能》
先楫半导体率先将RISC-V架构高性能微控制器芯片(MCU)引入伺服驱动领域,协助伺服驱动器行业客户迈向更高效、更智能的发展方向,同时还确保了高度自主可控的供应链管控能力,推动国内智能制造和工业自动化的创新与发展。
电子商城
现货市场
服务

提供电机的输出反电势波形测试、驱动芯片输入/输出波形测试服务,帮助您根据具体应用场景来选择适合的电机驱动芯片型号,确保电机驱动芯片能够与其他系统组件协同工作达到最佳效果。支持到场/视频直播测试,资深专家全程指导。
实验室地址: 成都 提交需求>

提供蓝牙BLE芯片协议、蓝牙模块、蓝牙成品测试认证服务;测试内容分Host主机层,Controller控制器层,Profile应用层测试。支持到场/视频直播测试,资深专家全程指导。
实验室地址: 深圳 提交需求>
登录 | 立即注册
提交评论