基于RUST的树莓派Raspberry 4的bare metal体验

最近看了几个讲Bare Metal的文章,看老外在Raspberry搞得风生水起,也手痒用RUST倒腾了下。。。
参考链接,拿来主义最快,主要基于下面几个链接:
基于RUST的树莓派3的Bare Metal
基于C的树莓派4的Bare Metal
基于RUST的RISC-V的OS
树莓派4B的CPU BCM2711 Datasheet

整体其实没什么难度,最主要的是环境配置。然后照着老外的代码改一改就能跑了,目前只试了试串口。

环境配置

基本上参考基于C的树莓派4的Bare Metal 一文来配置即可。
因为我用的是MacOS,所以额外的在使用FTDI的串口的时候,还需要重新倒腾一下驱动,参考老外的经验,重新安装即可。

RUST版本需要使用最新的版本,因为最新的tock-registers库,需要使用最新的RUST,否则编译不过。(懒得查版本号了,有兴趣看tock-registers的具体描述)

建议先使用基于C的树莓派4的Bare Metal的代码,编译出来一个kernel8.img放到树莓派上进行基本的串口验证。。。。我就是因为本来系统不对被坑了半天,重新烧录了树莓派的版本后才正常。。。。btw:macos烧录树莓派的方法见: macos烧录树莓派

文件组织

Project的文件结构如下:
基于RUST的树莓派Raspberry 4的bare metal体验_第1张图片
大致的每个文件的功能记录如下:

.cargo/config文件

Rust的cargo new不会创建该文件,我也不知道是哪个命令创建的,我是手动自行创建的该文件,该文件中主要是要指定编译的target的CPU体系结构,以及指定link description的文件位置, BCM2711是arm 64的架构,所以要用aarch64作为target,ld文件在src目录下名为linker.ld。 另外一个frame-pointers不晓得啥意思,没查。。。>_<。

[build]
target = "aarch64-unknown-none"

[target.aarch64-unknown-none]
rustflags = [
    "-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes"
]

raspi4_boot目录

该目录用来引导raspberry 4的启动,里面保存了一段用于启动的汇编,以及跳转到rust的世界的函数。

raspi4_boot/src/boot_cores.S

抄的。

直接拿基于C的树莓派4的Bare Metal的。其中主要是几个汇编指令,用于启动core 0并跳转到rust的reset函数去执行,其他的几个core都挂起。稍微翻一下ARM的手册理解问题不大。。。。自己写还是算了,汇编无能。。。>_<

raspi4_boot/src/lib.rs

抄的。

直接拿的基于RUST的树莓派3的Bare Metal中miniUart的代码,其中定义了一个entry的宏,用于暴露给OS来指定入口函数。reset函数则是通过boot_cores.S来调用的。
最后用global_asm来调用boot_cores.S中的汇编指令。

raspi4_boot/src/Cargo.toml

指定raspi4_boot使用的crate。。。其实目前cortex_a没用到。。。我也还没仔细看过这个库。回头学习一下。

src目录

Bare Metal的主逻辑。

gpio.rs

用基于RUST的树莓派3的Bare Metal中miniUart的部分,参考基于C的树莓派4的Bare Metal的代码逻辑和树莓派4B的CPU BCM2711 Datasheet,对几个寄存器做了修改,主要是描述串口中使用到的几个GPIO的配置,其实也就是GPIO14 和GPIO15.
tock-registers这个库的bit fields做的挺好用的,相对于C,省了不少的功夫。

linker.ld

抄的。

直接拿基于C的树莓派4的Bare Metal的。用来指定编译的内存分配。。。link description的语法看一次头疼一次。。。能抄就抄吧~~~

main.rs

额。逻辑比较简单。
一是定义了panic的处理,这玩意不定义,rust编译器不让你过。
二是kernel_entry的入口函数,里面初始化了uart,然后在屏幕上输出"Hello Steven",然后进入无限循环,串口每收到一个字符,都打印到屏幕上。

uart.rs

串口的寄存器定义,参考树莓派4B的CPU BCM2711 Datasheet的Chapter 2.

代码的主体逻辑抄的基于RUST的树莓派3的Bare Metal和
基于C的树莓派4的Bare Metal,raspberry3的初始化还需要有150个nop操作,raspberry4不需要了,不过初始化的寄存器操作跟3比起来略有变化。

Cargo.toml文件

指定raspi4_boot的位置,raspi4_boot是作为一个lib被使用的。
指定使用的tock-registers的版本。

Makefile文件

马马虎虎写的makefile,不想改了。。。最烦makefile文件的破语法了。
直接把Cargo build生成的文件,通过rust-objcopy输出成aarch64的bin然后改名成kernel8.img文件即可给Raspberry使用了。

效果图

超级简单。。。。
基于RUST的树莓派Raspberry 4的bare metal体验_第2张图片
其实整体没什么难度,只是一个引导和配置寄存器的过程。。。
只不过需要注意Datasheet的坑>_< (我觉得还是直接抄Demo代码的逻辑最靠谱):
在这里插入图片描述

代码

我的github
其他的外设等有空再照着基于C的树莓派4的Bare Metal抄抄改改。。。。

你可能感兴趣的:(Bare,Metal,裸金属,rust,开发语言,后端,bare,metal,裸金属)