ESP32 上的 Linux
Linux on ESP32

原始链接: https://github.com/GrieferPig/esp32-s31-linux

本项目记录了将支持 MMU 的 Linux 成功移植到 ESP32-S31 (RV32IMAFBCNSUX) 架构的过程。由于开发期间无法获取 S31 的技术文档,该移植工作依赖于对自定义中断处理的逆向工程推测,特别是用自定义的 CLIC/SCLIC 驱动替代了标准的 PLIC。 为了适应硬件平台的局限性,内核采用了 Linux 6.12 版本,利用其 XIP(原地执行)支持,在优化设备 16MB PSRAM 使用的同时实现系统启动。 目前,基础系统运行正常,能够执行 shell 进程并运行 CoreMark 基准测试(得分约为 1058 次迭代/秒)。尽管内核可以启动且基础控制台访问已实现,但绝大多数特定于硬件的外设——包括 GPIO、以太网、I2C、SPI 和安全加速器——仍处于未测试、开发中或未实现状态。本项目代表了一项重大的“底层启动”工作,证明了 Linux 可以在 S31 上运行,但对于依赖大量外设的应用而言,尚未达到生产就绪水平。

近期的一场 Hacker News 讨论聚焦于一个将 Linux 移植到 ESP32-S31 的实验性项目。尽管一些用户认为该项目只是一个“进行中”的工作或存在争议,但技术辩论的核心在于在如此受限的硬件上运行 Linux 的可行性。 主要挑战在于 ESP32-S31 的内存架构。与传统 CPU 不同,它的“MMU”是用于内存映射外部闪存和 PSRAM 的外设,而非提供完整进程隔离的标准 Sv32 兼容单元。因此,该移植版本依赖 Linux 内核 6.12 以利用 XIP(原地执行)支持,因为 Linux 主线内核已经移除了对该功能的支持。 虽然参与者质疑 NetBSD 等替代方案是否更合适,或者缺乏真正的 MMU 是否使该项目不切实际,但也有人指出在如此小型且支持无线功能的设备上运行 Linux 具有技术新颖性。作者承认该构建版本具有实验性质,目前仍高度专业化,且未经过通用用途的测试。
相关文章

原文

An attempt to port MMU Linux to S31's architecture (RV32IMAFBCNSUX).

Module tested: ESP32-S31-WROOM-3 E1H16R16V (ESP32-S31 Core Board).

Example boot log

Refer to the Build Instructions.

Feature Status
Buildroot rootfs 🟡 Untested
Wireless (ESP-Hosted) 🟡 Untested
Reboot and poweroff 🟡 Untested
Dual hart SMP ⚫ Not Planned (Used by FreeRTOS)
Feature Status
AXI GDMA 🟡 Untested
AHB GDMA 🟡 Untested
Cache driver 🟡 Untested
TRNG 🟡 Untested
eFuse 🟡 Untested
Watchdog 🟡 Untested
PWM, counter, analog peripherals 🟡 Untested
CLIC/CLINT interrupt driver 🟡 Untested
Flash MTD driver 🟡 Untested
Timers 🟠 WIP
Clock tree 🟠 WIP
Security accelerators 🟠 WIP
LP subsystem & IPC 🔴 Not Implemented
PMP/APM 🔴 Not Implemented (properly)
Feature Status
UART0 console 🟡 Untested
UART1/2 🟡 Untested
GMAC Ethernet 🟡 Untested
SDMMC 🟡 Untested
GPIO 🟡 Untested
pinctrl/GPIO Matrix 🟡 Untested
USB 🟠 WIP
I2C 🔴 Not Implemented
I2S 🔴 Not Implemented
SPI 🔴 Not Implemented
RMT 🔴 Not Implemented
USB Serial/JTAG ⚫ Not Planned (Used by FreeRTOS)

🟢 Stable — Fully tested and working | 🟡 Untested — Seems working; not throughly tested | 🟠 WIP - Functions not fully implemented

Also check out these command outputs.

(For more hardware references, see docs/ folder)

This port was done before S31 TRM is available, therefore these guessworks were made:

S31 uses CLIC and CLINT similar to P4. Linux expects PLIC. Therefore a custom CLIC driver is needed. I referenced this CLIC patch from disdi to get the CLIC working.

Also, standard RISC-V interrupt CSRs are not usable, presumably because, from P4's TRM, CLINT interrupts are routed to CLIC and mtvec.MODE is hardwired to 0x3 (CLIC mode). Patches needed to make OpenSBI interrupts work.

S31's supervisor mode is not standard and has absolutely no usage in ESP-IDF so a lot of these CSR uses were mostly guessed from either P4's TRM or CSR probing (see docs/). For example, the use of sclicbase(?) and the lack of sie.

S31 implemented SCLIC (Supervisor CLIC?) which is confusing since there is no known standardization; According to all laws of esp-idf, mcliccfg.NMBITS is not writable. IT IS WRITABLE! And setting it to 0b01 enables writes to the clicintattr[i].MODE field and thus enabling the use of S-mode interrupts.

To save the precious 16MB PSRAM memory, OpenSBI was modified to use XIP in flash and internal SRAM (hence the 3915901 KB firmware size in OpenSBI banner, since flash and SRAM mappings are not continuous).

In mainline linux, XIP support on RISC-V was removed, so 6.12 was used instead which has proper XIP support.

(as of 7/21/26)

~ # coremark
2K performance run parameters for coremark.
CoreMark Size    : 666
Total ticks      : 18887
Total time (secs): 18.887000
Iterations/Sec   : 1058.929422
Iterations       : 20000
Compiler version : GCC15.2.0
Compiler flags   : -O2 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64  -O2 -g0
Memory location  : Please put data memory location here
                        (e.g. code in flash, data on heap etc)
seedcrc          : 0xe9f5
[0]crclist       : 0xe714
[0]crcmatrix     : 0x1fd7
[0]crcstate      : 0x8e3a
[0]crcfinal      : 0x382f
Correct operation validated. See README.md for run and reporting rules.
CoreMark 1.0 : 1058.929422 / GCC15.2.0 -O2 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64  -O2 -g0    / Heap
# cat /proc/cpuinfo
processor       : 0
hart            : 0
isa             : rv32imafc_zicntr_zicsr_zifencei_zca_zcf_zbb
mmu             : sv32
uarch           : espressif,esp32s31
mvendorid       : 0x612
marchid         : 0x80000003
mimpid          : 0x1
hart isa        : rv32imafc_zicntr_zicsr_zifencei_zca_zcf_zbb
# uname -a
Linux (none) 6.12.0-00036-gdccf9c1b2c4f-dirty #30 Thu Jul  2 23:48:23 CST 2026 riscv32
# free -h
              total        used        free      shared  buff/cache   available
Mem:          15004        1892       12784           0         328       12108
Swap:             0           0           0
# ps -aux
    1 0          380 S    /bin/sh -i
    2 0            0 SW   [kthreadd]
    3 0            0 SW   [pool_workqueue_]
    4 0            0 IW   [kworker/0:0-eve]
    5 0            0 IW<  [kworker/0:0H]
    6 0            0 IW   [kworker/u4:0-ev]
    7 0            0 IW<  [kworker/R-mm_pe]
    8 0            0 SW   [ksoftirqd/0]
    9 0            0 SW   [kdevtmpfs]
   10 0            0 IW<  [kworker/R-inet_]
   11 0            0 SW   [oom_reaper]
   12 0            0 IW<  [kworker/R-write]
   13 0            0 SW   [kcompactd0]
   14 0            0 IW<  [kworker/R-kbloc]
   15 0            0 SW   [kswapd0]
   16 0            0 IW   [kworker/0:1-pm]
   17 0            0 IW   [kworker/u4:1-ev]
   18 0            0 SW   [khvcd]
   19 0            0 IW<  [kworker/R-mld]
   20 0            0 IW<  [kworker/R-ipv6_]
   34 0          380 R    ps -aux
# cat /proc/meminfo
MemTotal:          15004 kB
MemFree:           12788 kB
MemAvailable:      12112 kB
Buffers:               0 kB
Cached:              328 kB
SwapCached:            0 kB
Active:                4 kB
Inactive:             32 kB
Active(anon):          4 kB
Inactive(anon):       32 kB
Active(file):          0 kB
Inactive(file):        0 kB
Unevictable:         328 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:            52 kB
Mapped:              208 kB
Shmem:                 0 kB
KReclaimable:          0 kB
Slab:                756 kB
SReclaimable:          0 kB
SUnreclaim:          756 kB
KernelStack:         352 kB
PageTables:           24 kB
SecPageTables:         0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        7500 kB
Committed_AS:        304 kB
VmallocTotal:     524288 kB
VmallocUsed:          12 kB
VmallocChunk:          0 kB
Percpu:               32 kB
联系我们 contact @ memedata.com