文章目录
在之前一篇文章 《用 7 毛钱的 CH32V003 单片机跑 Linux,启动需要 5 分钟》 中介绍了开源项目 linux-ch32v003
和 mini-rv32ima
,可以在 7 毛钱的单片机 CH32V003 上配合外置 PSRAM 来运行一个 RSIC-V 模拟器,并且可以运行一个裁剪过的 Linux 系统镜像。
但是 CH32V003 的性能不太强劲,按作者介绍启动 Linux 系统需要 5 分钟,为了更好地学习一下 RSIC-V 模拟器,我决定把它移植到 ESP32-S3 来试一下看看。
PS. 搞这个也是仅供娱乐了,毕竟 ESP32-S3-N16R8 20 多元的价格,可以买像 V3S 这样正经 ARM SoC 来跑 Linux 了。
移植 mini-rv32ima
在上一篇文章中,已经大概介绍了移植 mini-rv32ima
需要对接的几个函数,主要包含以下几个方面:
- 读取并加载 Linux 系统镜像
- 检测和读取键盘输入
- 输出 Linux console 内容到 UART
为了让这个模拟器能交互,最后定下来将系统的输入输出对接到 ESP32-S3 的 UART,这样在电脑上可以直接使用 minicom
这样的工具来跟 Linux console 进行交互。
读取并加载 Linux 镜像
在 linux-ch32v003
项目中,是使用了一个 TF 读卡器,并且实现了一个 FATFS 库读取并加载到 PSRAM 中。
但是对于 ESP32-S3 来,我选择了 ESP32-S3-N16R8 这个型号,本身就带了 16MB Flash,足够把编译完的 Linux 镜像直接打包进固件了 😃
这个可以使用 xxd
命令来完成转换,可以直接将一个二进制文件转换成 C Array 的头文件:
xxd -i Image > Image.h
这样原来需要使用 fread
函数来实现的 Linux 系统镜像加载,直接从固件中复制过去就可以了。
这里的 ram_image
指针指向了使用 ps_malloc
分配的 PSRAM 中的内存区域。
检测和读取键盘输入
这里为了方便使用模拟器上的 Linux,直接通过 UART 来对接了 Linux 中的 console 设备,很简单地通过 Serial 是否有数据和读取一个字节来实现用户输入。
输出 Linux console 到 UART
对于 Linux console 输出来说,就不需要额外处理了,本身 mini-rv32ima
内部就使用了 printf
来输出,在 ESP32 Arduino 框架里,printf
也是默认输出到 Serial 的。
经过上面三个步骤的对接,基本上就可以把 mini-rv32ima
在 ESP32-S3 上跑起来了,当然,我们还得有一个可以跑起来的 Linux 镜像。
一个小坑
ESP32-S3-N16R8 虽然说是 8MB PSRAM,但是实际检测到可使用空间并不是完整的 8 * 1024 * 1024 bytes
,因此在模拟器的内存大小定义时,我取了小一点的值,用了 7MB PSRAM。
uint32_t ram_amt = 7*1024*1024;
编译 Linux 系统镜像
感谢 tvlad1234 和他的 linux-ch32v003
项目,已经编写好一个去除 MMU 依赖,以及裁剪过内核的 Linux 编译脚本,可以一键编译出一个可以在 mini-rv32ima
上运行的 Linux 镜像。
将 linux-ch32v003
项目 clone 到本地,进入到 linux
目录,执行 make all
,再经历漫长的等待,即可完成一个 1MB 左右的 Linux 内核镜像的编译。
这个项目的编译脚本除了编译一个 Linux 内核出来,还编译了其他几个东西来方便使用:
- buildroot 根文件系统
- coremark 一个 MCU 跑分软件
- hello_linux 一个编写 Linux app 的示例
另外在 macOS 上,建议使用 OrbStack 开一个 Ubuntu 虚拟机来编译内核,要不然处理工具链问题都要好久。
编译完就可以在 linux/buildroot/output/images
中找到编译完成的 Image
文件,把这个文件使用 xxd
输出成 C 代码文件,就可以在 ESP32-S3 中使用了。
定制 Linux 和 buildroot
本身受制于 PSRAM 容量的限制,默认的 Linux 编译配置和 buildroot 编译配置省掉了很多东西,包括 busybox 支持的命令数量也裁剪了很多,如果想要更多可玩性,可以自行使用 menuconfig 定制一下内核和 buildroot 以及 busybox。
Linux on ESP32,启动!
万事俱备,只欠东风!
现在只要用 PlatformIO 打开 linux-esp32s3
项目,将 ESP32-S3-N16R8 开发板连接到电脑,编译项目并上传到开发板,就可以开始体验运行在 RSIC-V 模拟器的 Linux 啦~
烧录完固件后,就可以使用 minicom 连接 ESP32-S3 来把玩这个 LInux 了,不过开始前记得设置一下 minicom 的端口。
Linux 启动~
连接上后,按一下开发板的 RST 按钮,就可以看到 Linux console 的输出了,这次启动只需要 8 秒 😃。
看看有哪些命令可以用:
有点少 😂。
用 coremark 跑个分
linux-ch32v003
作者的编译脚本还同时打包了一个 coremark
来测试模拟器的性能,这也在 ESP32-S3 上跑一下看看:
哈,6.65 分,稍高于 ATmega2560 4.25 分的成绩 😂。
开源项目
移植到 ESP32-S3 + Arduino 的 mini-rv32ima
的项目已经在 GitHub 开源,可以在下面地址找到。
GitHub 项目: https://github.com/ohdarling/linux-esp32s3
Linux 镜像编译脚本可以在原作者的 linux-ch32v003
项目中找到。
linux-ch32v003: https://github.com/tvlad1234/linux-ch32v003
在淘宝上买的ESP32-S3-N16R8版本,成功运行起来了。uart用的CH341芯片,在ubuntu上无须驱动。
1. 如果遇到uart不能识别,打开dmesg看看是不是刚连上就断开,如果是,删除brltty,再重连一次。sudo apt-get autoremove brltty。就会被识别到/dev/ttyUSB0
2. 如果刷固件的时候失败,需要加权限。
$ sudo adduser dialout
$ sudo chmod a+rw /dev/ttyUSB0
3. 如果minicom乱码,设置一下波特率。
sudo minicom -b 115200 -D /dev/ttyUSB0