芒果派 · 2021年12月13日

[转] MoeOS搬家到Nezha MQ上啦(D1s裸机程序执行)by LI Rui

注:本文属于转载。
原文链接: https://zhuanlan.zhihu.com/p/...
原文作者: https://www.lirui.tech/about/

本文最早发布于我的博客:MoeOS搬家到Nezha MQ上啦(D1s裸机程序执行) | LI Rui
MoeOS是跟着rCore-Tutorial-Book 第三版开发的玩具OS(WIP),非常感谢rcore团队,仓库地址:KernelErr/Moeos。
在学习rcore的过程中,一直想把写的OS在实机上跑起来。但是原教程用的K210系列开源硬件已经停产,现在在网上购买一是价格较高,二是担心版本较旧。

最近发现一款代号为麻雀的开发板,其官网为 https://MangoPi.org 。采用的主控为D1s芯片(使用平头哥C906处理器,64位RISC-V,内置64MByte运行内存),还支持WiFi。9.9USD价格到手后发现这款板子小巧精致,大小仅有约4x4厘米,但正所谓麻雀虽小,五脏俱全。

实拍如下:
image

image

简直是学习RISC-V的好选择 ,就决定用这块板子当作MoeOS的新家了。

Opensbi

搬家的第一步我们需要编译一个适合D1s芯片的SBI (Supervisor Binary Interface),SBI将作为我们操作系统的运行时,负责引导系统启动,为系统提供二进制接口等功能。SBI的实现很多,比如rustsbi、opensbi等。这里我们选择opensbi,但D1/D1s芯片在未来的1.0版本中才能或得支持。所以我们需要手动编译群友的fork:LZU-OSLab/opensbi。

为了保证能够正常交叉编译,我们需要从平头哥芯片开放社区下载gcc(如果从软件源中下载可能会不支持V扩展):工具链-900系列。假设我们将下载的文件解压到TOOLCHAIN_PATH目录下面。

在克隆下来的仓库目录中执行下面的命令:

$ export CROSS_COMPILE=TOOLCHAIN_PATH/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.3/bin/riscv64-unknown-linux-gnu-  PLATFORM=allwinner/d1

$ make

这里我们指定了工具链的地址和前缀,实际编译的时候会在调用“TOOLCHAIN_PATH/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.3/bin/riscv64-unknown-linux-gnu-gcc”。同时指定了platform为d1芯片。

如果一切顺利,我们会得到build/platform/allwinner/d1/firmware/fw_jump.bin文件。

对于不同firmware的区别可以参见:OpenSBI Platform Firmwares。这里我们设置jump到的地址为0x80200000,对于这块芯片的内存映射可以查看文档D1_User_Manual_V0.1(Draft Version)的3.1 Memory Mapping一节,需要注册帐号登录。

xfel

全志D1/D1s在BROM中集成了FEL模式,我们可以在这个模式中进行烧录、测试等操作。社区大佬开发了XFEL工具,允许我们直接初始化内存、将二进制写到内存中等。在MoeOS被制作成img写到SD Card之前,我们直接将其载入内存执行方便调试开发。

Rust no_std 程序
在Rust中,我们平常使用的程序都集成了std标准库,为我们包含了大部分常用功能,包括了panic宏等。但在裸机执行下,我们无法使用std标准库,只有有限的core库功能可用。(推荐阅读Rust月刊文章华为 | no std的可执行文件编写和运行)

同时,我们需要跨平台编译,在x86平台下编写RISC-V下的程序。非常方便的一点是,我们可以使用rustup轻松对添加目标平台支持:

$ rustup target add riscv64gc-unknown-none-elf

为了设置默认编译的target为riscv64gc-unknown-none-elf,我们可以在项目的.cargo/config.toml设置:

[build]
target = "riscv64gc-unknown-none-elf"

[target.riscv64gc-unknown-none-elf]
rustflags = [
    "-C", "link-arg=-Tsrc/lds/virt.lds",
]

这里我们指定了build命令的默认target,还设置了我们的链接脚本的路径(链接脚本可以保证我们生成的二进制文件代码段等段可以放在正确的内存位置上)。

之后我们便可以编写自己的Rust程序,具体实现可以参考MoeOS的代码。

跑起来
Nezha MQ的UART0在下图中的位置:

image

上面的是RX,下面的是TX。在安连接USB转TTL后,我们可以使用minicom打开一个终端。并在MoeOS的目录执行:

$ make d1s

为了保证能够正常执行,需要确保:

已有Rust Toolchain
已经安装xfel
之后我们就可以看到MoeOS跑起来啦 (^ᴗ^) :

image

之后MoeOS也会持续开发,但会更专注于知识的学习,因为坑太多,超过了一开始的初心。感谢大家的阅读和支持~

推荐阅读
关注数
2
内容数
4
持续提供小巧精致的开源硬件
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息