基于OpenSBI的linux nommu实现

2024-09-19
浏览量:
23432

Linux内核6.10提供了对没有mmu的riscv处理器工作在S模式下的内核的支持,本文介绍基于OpenSBI的linux no mmu的实现,供大家参考。


1、OpenSBI介绍

SBI:Supervisor Software Binary Interface 软件二进制接口

Linux内核工作在S模式下时,不能直接访问机器定时器。而系统的运行依赖于定时器,为了解决这个问题,需要通过SBI接口由工作在M模式下的SBI固件来提供访问定时器等功能。

SBI的实现方式有很多种,常见的包括BBL、OpenSBI、Xvisor、KVM、RustSBI、Diosix、Coffer。

文章将要介绍的OpenSBI应用实例采用了FW_JUMP方式的OpenSBI方案。

FW_JUMP类型的固件假设下一个引导阶段入口的地址是固定的,例如引导加载程序或操作系统内核,而不直接包含下一个阶段的二进制代码。


2、内核配置

在内核配置上,主要涉及到以下选项,也可以通过仓库中的hpmicro_hpm6800evk_defconfig来获取默认的配置。

仓库中还提供了基础的GPIO和PINMUX驱动,爱好者们可以通过修改设备树来实现LED和按键功能,而不用修改内核驱动代码。对于其他的外设的PINMUX配置,也可以通过修改设备树来完成。


3、Loader配置

由于HPM芯片启动时一般是以XIP的方式执行flash中的代码,所以需要一个loader程序来实现将OpenSBI、kernel、设备树等固件拷贝到其运行地址中。

除了搬移固件外,loader还需要做一些基础的初始化工作,包括sdram/ddr的使能,默认console的时钟和串口的pinmux配置等。

做完这些工作后,loader跳转至OpenSBI的入口函数,将系统交给OpenSBI来管理,接着OpenSBI在做完准备工作后,跳转至内核。


4、BuildRoot配置

单独编译loader、OpenSBI、Linux内核和文件系统并进行烧写是可行的,但是不是那么的方便,使用BuildRoot,我们可以方便的将这些固件整合到一起,一次性编译出整个固件。


4.1 loader的添加

首先将编写好loader固件上传到git服务器上。然后在buildroot的boot目录下创建一个文件夹hpmicro_loader,在其中添加两个新文件:Config.in和hpmicro_loader.mk

Config.in中主要是创建了一个Kconfig选项,用来选择是否要使能hpmicro_loader。使能后hpmicro_loader.mk会被加入到编译系统中。

在本文的实现中,loader是基于hpm_sdk进行编写的,其中将hpm_sdk作为submodule引入,所以在hpmicro_loader.mk中,不仅要将loader的仓库地址填入,还需要指定HPMICRO_LOADER_GIT_SUBMODULES = yes来让编译系统去初始化submodule,否则会缺失hpm_sdk文件。同时由于hpm_sdk是基于cmake构建系统的,还需要指定hpmciro_loader的构建系统为cmake:$(eval $(cmake-package))。由于hpm_sdk不支持源文件目录下直接编译,所以要指定HPMICRO_LOADER_SUPPORTS_IN_SOURCE_BUILD = no。再指定一些SDK编译需要的环境变量后,就可以顺利进行编译了。

编译结束后,通过后处理命令,将编译输出的bin文件,拷贝到genimage的工作目录,用于最终的镜像生成。

define HPMICRO_LOADER_INSTALL_TARGET_CMDS
dd if=/dev/zero of=$(@D)/buildroot-build/output/temp.bin bs=1 count=1024
cat $(@D)/buildroot-build/output/temp.bin $(@D)/buildroot-build/output/demo.bin > $(@D)/buildroot-build/output/opensbiloader.bin
$(INSTALL) -D -m 0644 $(@D)/buildroot-build/output/opensbiloader.bin $(BINARIES_DIR)/opensbiloader.bin
endef

4.2 Kernel版本的指定

Kernel的自定义版本指定功能是BuildRoot自带的,我们可以通过修改以下两个选项来指定Kernel的版本。


· 指定Kernel版本

BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="$(call github,hpmicro,linux,7b088c87b6758e413bd316bf883438f7134f1e7f)/linux-7b088c87b6758e413bd316bf883438f7134f1e7f.tar.gz"

其中github,hpmicro,linux代表了仓库地址为github/hpmicro/linux.git,后边的7b088c87b6758e413bd316bf883438f7134f1e7f为指定的提交编号

也可以通过menuconfig在图形界面中去修改。

· 指定Kernel的配置文件

BR2_LINUX_KERNEL_DEFCONFIG="nommu_hpmicro"

· 指定设备树文件

BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="hpmicro/hpm6800-evk"


4.3 OpenSBI版本的指定

OpenSBI的版本指定和Kernel的版本指定类似

BR2_TARGET_OPENSBI_CUSTOM_REPO_URL="https://github.com/hpmicro/opensbi.git"
BR2_TARGET_OPENSBI_CUSTOM_REPO_VERSION="2900da09af75c80ed8c4a8553a35e94e0f3f5c0d"
BR2_TARGET_OPENSBI_VERSION="2900da09af75c80ed8c4a8553a35e94e0f3f5c0d"

· 指定OpenSBI的平台名称:

 BR2_TARGET_OPENSBI_PLAT="hpmicro"

4.4 镜像排布的指定

采用genimage对各个独立的镜像进行整合:创建genimage脚本文件genimage_opensbi.cfg, 指定每个镜像文件存放的位置:

flash w25q128 {
pebsize = 64K
numpebs = 256
minimum-io-unit-size = 1
}
image flash.img {
flash {
   }
flashtype = "w25q128"
partition opensbiloader {
size = 64k
image = "opensbiloader.bin"
}
partition opensbi {
offset = 64K
image = "fw_jump.bin"
size = 192K
}

partition kernel {
image = "Image"
offset = 256K
size = 2880K
}
partition dtb {
image = "hpm6800-evk.dtb"
offset = 3136K
size = 64K
}
partition rootfs {
image = "rootfs.squashfs"
offset = 4M
size = 1M
}
}

5、编译过程

5.1 OpenSBI单独编译:

· Github仓库地址

https://github.com/hpmicro/opensbi.git

· 编译命令

make all PLATFORM=hpmicro CROSS_COMPILE=riscv32-unknown-elf- HPMSOC=HPM6800 O={build_dir} 

编译完成后可以在{build_dir}中找到platform/hpmicro/firmware/fw_jump.bin,需要loader将其拷贝到地址0然后再跳转到地址0来运行。


5.2 Loader参考:

· Github仓库地址

https://github.com/hpmicro/hpm_opensbi_loader.git

· 编译命令

 HPM_SDK_BASE={SDKBASE} GNURISCV_TOOLCHAIN_PATH={RISCV TOOLCHAIN PATH} HPM_SDK_TOOLCHAIN_VARIANT=gcc cmake -GNinja -DBOARD=hpm6800evk -DHPM_BUILD_TYPE=flash_xip -B build

5.3 buildroot工程编译:

· Github仓库地址

https://github.com/hpmicro/buildroot.git

· 编译命令

make hpmicro_hpm6800evk_defconfig
make all

6、烧录和运行

· 烧录需要用到hpm_manufacturing_tool,仓库地址:

https://github.com/hpmicro/hpm_manufacturing_tool.git

将buildroot生成的镜像output/images/flash.img重命名成flash.bin烧录到0x80000000即可。

OpenSBI v0.6
  ____                    _____ ____ _____
 / __ \                  / ____|  _ \_   _|
| |  | |_ __   ___ _ __ | (___ | |_) || |
| |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
| |__| | |_) |  __/ | | |____) | |_) || |_
 \____/| .__/ \___|_| |_|_____/|____/_____|
       | |
       |_|

Platform Name          : HPMicro D45
Platform HART Features : RV32ACDFIMSUX
Platform Max HARTs     : 1
Current Hart           : 0
Firmware Base          : 0x0
Firmware Size          : 76 KB
Runtime SBI Version    : 0.2

MIDELEG : 0x00000222
MEDELEG : 0x0000b109
PMP0    : 0x00000000-0x0001ffff (A)
PMP1    : 0x01200000-0x0127ffff (A,R,W,X)
PMP2    : 0x40000000-0x41ffffff (A,R,W,X)
PMP3    : 0x80000000-0x9fffffff (A,R,X)
PMP4    : 0xe0000000-0xefffffff (A,R,W)
PMP5    : 0xf0000000-0xffffffff (A,R,W)
[    0.000000] Linux version 6.10.0 (ubuntu@ubuntu-virtual-machine) (riscv32-buildroot-linux-uclibc-gcc.br_real (Buildroot -g71f87772fd) 13.3.0, GNU ld (GNU Binutils) 2.41) #1 Sat Sep 14 10:38:43 CST 2024
[    0.000000] Machine model: HPMicro HPM6800 Evaluate Kit
[    0.000000] SBI specification v0.2 detected
[    0.000000] SBI implementation ID=0x1 Version=0x6
[    0.000000] SBI TIME extension detected
[    0.000000] SBI IPI extension detected
[    0.000000] SBI RFENCE extension detected
[    0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
[    0.000000] printk: legacy bootconsole [sbi0] enabled
[    0.000000] printk: debug: ignoring loglevel setting.
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000040000000-0x0000000041ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x0000000041ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x0000000041ffffff]
[    0.000000] riscv: base ISA extensions acdfim
[    0.000000] riscv: ELF capabilities acdfim
[    0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[    0.000000] pcpu-alloc: [0] 0
[    0.000000] Kernel command line: earlycon=sbi console=hvc0 ignore_loglevel rootwait root=/dev/mtdblock0
[    0.000000] Dentry cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
[    0.000000] Inode-cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 8192
[    0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[    0.000000] Memory: 30248K/32768K available (1370K kernel code, 298K rwdata, 266K rodata, 97K init, 136K bss, 2520K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] riscv-intc: 32 local interrupts mapped
[    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
[    0.000005] sched_clock: 64 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
[    0.008230] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=96000)
[    0.018469] pid_max: default: 4096 minimum: 301
[    0.023214] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.030507] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.041674] devtmpfs: initialized
[    0.048165] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.057969] pinctrl core: initialized pinctrl subsystem
[    0.087311] cpu0: Ratio of byte access time to unaligned word access is 1.65, unaligned accesses are fast
[    0.098916] platform soc: Fixed dependency cycle(s) with /soc/interrupt-controller@e4000000
[    0.109020] platform soc: Fixed dependency cycle(s) with /soc/interrupt-controller@e4000000
[    0.120899] clocksource: Switched to clocksource riscv_clocksource
[    0.130851] workingset: timestamp_bits=30 max_order=13 bucket_order=0
[    0.137423] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.155691] riscv-plic e4000000.interrupt-controller: mapped 76 interrupts with 1 handlers for 2 contexts.
[    0.167985] hpmicro gpio f00d0000.gpio-controller: port0dx, ngpios32
[    0.175826] hpmicro gpio f00d0000.gpio-controller: gpio irq_num 1, dev_namef00d0000.gpio-controller
[    0.185459] hpmicro gpio f00d0000.gpio-controller: port1dx, ngpios32
[    0.192568] hpmicro gpio f00d0000.gpio-controller: gpio irq_num 2, dev_namef00d0000.gpio-controller
[    0.202134] hpmicro gpio f00d0000.gpio-controller: port2dx, ngpios32
[    0.209294] hpmicro gpio f00d0000.gpio-controller: gpio irq_num 3, dev_namef00d0000.gpio-controller
[    0.218797] hpmicro gpio f00d0000.gpio-controller: port3dx, ngpios32
[    0.225921] hpmicro gpio f00d0000.gpio-controller: gpio irq_num 4, dev_namef00d0000.gpio-controller
[    0.235458] hpmicro gpio f00d0000.gpio-controller: port4dx, ngpios32
[    0.242579] hpmicro gpio f00d0000.gpio-controller: gpio irq_num 6, dev_namef00d0000.gpio-controller
[    0.252514] hpmicro gpio f00d0000.gpio-controller: port5dx, ngpios32
[    0.259651] hpmicro gpio f00d0000.gpio-controller: gpio irq_num 7, dev_namef00d0000.gpio-controller
[    0.271904] printk: legacy console [hvc0] enabled
[    0.271904] printk: legacy console [hvc0] enabled
[    0.281387] printk: legacy bootconsole [sbi0] disabled
[    0.281387] printk: legacy bootconsole [sbi0] disabled
[    0.291843] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.304084] f0040000.uart0: ttyS0 at MMIO 0xf0040000 (irq = 8, base_baud = 1500000) is a 16550A
[    0.313704] hpmicro-uart f0040000.uart0: hpm-uart probe success
[    0.322184] hpmicro-uart f004c000.uart3: hpm-uart probe success
[    0.328959] physmap-flash 80400000.rom: physmap platform flash device: [mem 0x80400000-0x80ffffff]
[    0.340420] pinctrl-hpmicro f4040000.pinctrl: pin167 config set:
[    0.346446] pinctrl-hpmicro f4040000.pinctrl:                5:1
[    0.351353] pinctrl-hpmicro f4040000.pinctrl:                14:1
[    0.356376] pinctrl-hpmicro f4040000.pinctrl:                128:3
[    0.361505] pinctrl-hpmicro f4040000.pinctrl:                129:0
[    0.367076] input: gpio-keys0 as /devices/platform/gpio-keys0/input/input0
[    0.374457] evbug: Event. Dev: input0, Type: 1, Code: 304, Value: -1
[    0.380747] evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
[    0.386999] evbug: Connected device: input0 (gpio-keys0 at gpio-keys-polled/input0)
[    0.394686] evbug: Event. Dev: input0, Type: 1, Code: 304, Value: 0
[    0.400939] evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
[    0.410306] ledtrig-cpu: registered to indicate activity on CPUs
[    0.425354] pinctrl-hpmicro f4040000.pinctrl: pin166 config set:
[    0.431358] pinctrl-hpmicro f4040000.pinctrl:                5:1
[    0.436289] pinctrl-hpmicro f4040000.pinctrl:                14:1
[    0.441351] pinctrl-hpmicro f4040000.pinctrl:                128:3
[    0.446424] pinctrl-hpmicro f4040000.pinctrl:                129:0
[    0.452175] input: gpio-keys1 as /devices/platform/gpio-keys1/input/input1
[    0.459436] evbug: Connected device: input1 (gpio-keys1 at gpio-keys/input0)
[    0.466928] clk: Disabling unused clocks
[    0.471437] cramfs: checking physical address 0x80400000 for linear cramfs image
[    0.480081] VFS: Mounted root (squashfs filesystem) readonly on device 31:0.
[    0.487534] devtmpfs: mounted
[    0.490877] Freeing unused kernel image (initmem) memory: 96K
[    0.496618] This architecture does not have kernel memory protection.
[    0.503115] Run /sbin/init as init process
[    0.507258]   with arguments:
[    0.510291]     /sbin/init
[    0.513096]   with environment:
[    0.516231]     HOME=/
[    0.518701]     TERM=linux
[    1.553000] random: crng init done
mount: mounting devpts on /dev/pts failed: No such device
sh: can't execute 'seedrng': No such file or directory

Welcome to Buildroot
buildroot login:

当按下开发板上的按键时,会有信息打印出来:

[    3.208963] evbug: Event. Dev: input0, Type: 1, Code: 304, Value: 1
[    3.215174] evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
[    3.388948] evbug: Event. Dev: input0, Type: 1, Code: 304, Value: 0
[    3.395153] evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
[    3.808915] evbug: Event. Dev: input1, Type: 1, Code: 305, Value: 1
[    3.815120] evbug: Event. Dev: input1, Type: 0, Code: 0, Value: 0
[    3.952914] evbug: Event. Dev: input1, Type: 1, Code: 305, Value: 0
[    3.959119] evbug: Event. Dev: input1, Type: 0, Code: 0, Value: 0
[    4.284913] evbug: Event. Dev: input1, Type: 1, Code: 305, Value: 1
[    4.291118] evbug: Event. Dev: input1, Type: 0, Code: 0, Value: 0
[    4.420915] evbug: Event. Dev: input1, Type: 1, Code: 305, Value: 0
[    4.427115] evbug: Event. Dev: input1, Type: 0, Code: 0, Value: 0


“先楫半导体”(HPMicro)是一家致力于高性能嵌入式解决方案的半导体公司,总部位于上海,产品覆盖微控制器、微处理器和周边芯片,以及配套的开发工具和生态系统。公司成立于2020年6月,总部坐落于上海市浦东软件园区,并在天津、苏州、深圳和杭州均设立分公司。核心团队来自世界知名半导体公司管理团队,具有15年以上,超过20个SoC的丰富的研发及管理经验。先楫半导体以产品质量为本,所有产品均通过严格的可靠性测试。目前已经量产的高性能通用MCU产品包含HPM6700/6400、HPM6300、HPM6200、HPM5300、HPM6800及HPM6E00系列,性能领先国际同类产品并通过AEC-Q100认证。公司已完成ISO9001质量管理认证和ISO 26262/IEC61508功能安全管理体系双认证,全力服务中国乃至全球的工业、汽车和能源市场。更多信息,敬请访问 https://hpmicro.com/