来了来了,用单片机 ESP32-S3 跑 RISC-V 模拟器运行 Linux,这次启动只要 8 秒

在之前一篇文章 《用 7 毛钱的 CH32V003 单片机跑 Linux,启动需要 5 分钟》 中介绍了开源项目 linux-ch32v003mini-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 需要对接的几个函数,主要包含以下几个方面:

  1. 读取并加载 Linux 系统镜像
  2. 检测和读取键盘输入
  3. 输出 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 系统镜像加载,直接从固件中复制过去就可以了。

linux-on-esp32s3-1

这里的 ram_image 指针指向了使用 ps_malloc 分配的 PSRAM 中的内存区域。

检测和读取键盘输入

这里为了方便使用模拟器上的 Linux,直接通过 UART 来对接了 Linux 中的 console 设备,很简单地通过 Serial 是否有数据和读取一个字节来实现用户输入。

linux-on-esp32s3-2

输出 Linux console 到 UART

对于 Linux console 输出来说,就不需要额外处理了,本身 mini-rv32ima 内部就使用了 printf 来输出,在 ESP32 Arduino 框架里,printf 也是默认输出到 Serial 的。

linux-on-esp32s3-3

经过上面三个步骤的对接,基本上就可以把 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-on-esp32s3-4

这个项目的编译脚本除了编译一个 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-on-esp32s3-5

Linux 启动~

连接上后,按一下开发板的 RST 按钮,就可以看到 Linux console 的输出了,这次启动只需要 8 秒 😃。

linux-on-esp32s3-6

看看有哪些命令可以用:

linux-on-esp32s3-7

有点少 😂。

用 coremark 跑个分

linux-ch32v003 作者的编译脚本还同时打包了一个 coremark 来测试模拟器的性能,这也在 ESP32-S3 上跑一下看看:

linux-on-esp32s3-8

哈,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

参考资料

发表评论?

1 条评论。

  1. 在淘宝上买的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

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>