Chạy Linux trên ESP32-S31: MMU thay đổi điều gì?
ESP32-S31 đã có Linux BSP chính thức ở dạng Developer Preview. Mình cùng xem MMU, Buildroot, U-Boot, Linux 6.18 và những giới hạn thực tế trước khi chọn board để thử.
Chia sẻ

Nếu chỉ đọc tiêu đề “Linux chạy trên ESP32”, mình rất dễ nghĩ đây lại là một bản giả lập chậm hoặc một demo chỉ đủ in ra prompt. Nhưng lần này câu chuyện đáng chú ý hơn: ESP32-S31 có MMU và Espressif đã phát hành Linux BSP chính thức ở dạng Developer Preview.
Tính đến ngày 24/8/2026, đây vẫn là nền tảng để thử nghiệm chứ chưa phải lựa chọn an toàn cho sản phẩm. Dù vậy, nó cho thấy khoảng cách giữa MCU và một SoC Linux nhỏ đang ngắn lại thật sự.
S31 khác gì so với những ESP32 trước đây?
ESP32-S31 dùng hai core RISC-V 32-bit, chạy tối đa 320 MHz và hỗ trợ MMU. Board ESP32-S31-Korvo-1 phổ biến hiện tại dùng module có 16 MB flash và 16 MB PSRAM.
MMU không phải là điều kiện tuyệt đối để kernel Linux tồn tại: ESP32-S3 đã có những port Linux NOMMU chạy native. Tuy nhiên, thiếu MMU đồng nghĩa với việc không có mô hình bộ nhớ ảo và cách cô lập process quen thuộc; nhiều chương trình phụ thuộc vào fork() cũng không chạy bình thường. Với S31, Linux có thể dùng mô hình MMU đúng nghĩa hơn thay vì phải ép toàn bộ userspace vào giới hạn NOMMU.
| Nền tảng | Cách chạy | Điểm cần nhớ |
|---|---|---|
| ESP32-S3 Xtensa | Linux native NOMMU | Có thể boot và vào shell, nhưng userspace bị giới hạn mạnh |
| ESP32 cũ + emulator | Giả lập RISC-V hoặc x86 | Thú vị để học, đổi lại tốc độ rất chậm |
| ESP32-S31 RISC-V | Linux native với MMU | Gần mô hình embedded Linux thông thường hơn, nhưng RAM và driver vẫn rất hạn chế |

Korvo-1 dùng module ESP32-S31-WROOM-3 với 16 MB flash và 16 MB PSRAM.
Mình vẫn không xem S31 như Raspberry Pi thu nhỏ. 16 MB PSRAM đủ cho Buildroot tối giản, BusyBox và một số tiến trình nhỏ; nó không biến board thành máy chạy desktop, package manager hay container đầy đủ.
BSP chính thức gồm những gì?
Nhánh integration/v1.0-esp32s31 của esp-linux-bsp được Espressif ghi rõ là Developer Preview. Stack hiện tại xoay quanh:
- Buildroot 2025.02 để tạo toolchain và root filesystem.
- Fork Linux kernel 6.18 cho ESP32-S31.
- U-Boot SPL, OpenSBI và U-Boot FIT trong chuỗi boot.
- Kernel XIP chạy từ NOR flash để tiết kiệm PSRAM.
- Root filesystem
cramfstối giản. - File tổng
s31_full_flash.binđể ghi từ offset0x0.

BSP đóng gói U-Boot SPL, OpenSBI, U-Boot, kernel XIP và cramfs thành một image.
Luồng boot có thể hình dung ngắn gọn như sau:
ESP ROM → U-Boot SPL → OpenSBI/U-Boot → Linux XIP → cramfs/BusyBox
Repository esp-linux-bsp chủ yếu chứa layout và công cụ đóng gói. Phần tích hợp Buildroot nằm ở esp-buildroot-external, còn kernel nằm trong fork espressif/linux. Cách tách này hơi nhiều repository, nhưng ít nhất từng lớp đã được công khai để mình kiểm tra thay vì chỉ tải một binary không rõ nguồn.
Chuẩn bị trước khi thử
Đường build chính thức hiện nhắm đến ESP32-S31 Function Core Board. Các port cộng đồng thường dùng ESP32-S31-Korvo-1. Hai board không có layout cổng giống nhau, vì vậy hãy đọc đúng tài liệu của board mình đang cầm.
Với Korvo-1, cổng USB-C Power chỉ cấp nguồn; cổng USB-C UART mới dùng để flash và mở console qua CP2102N. Đây là chi tiết nhỏ nhưng dễ khiến mình mất nửa giờ vì cắm đúng loại cáp vào sai cổng.
Trước khi flash:
- Dùng board/module có 16 MB PSRAM và flash phù hợp với image.
- Dùng cáp USB có data.
- Cập nhật
esptoollên 5.3.0 hoặc mới hơn. - Backup firmware và dữ liệu đang có trên board.
- Không thử trên board đã bật Secure Boot/Flash Encryption nếu chưa có quy trình recovery.
Image đầy đủ được ghi từ 0x0, nên firmware, partition table và dữ liệu cũ sẽ bị thay thế.
Build image Linux chính thức
Mình khuyên dùng Linux hoặc một máy ảo Linux sạch, vì toàn bộ flow dựa trên Buildroot. Các lệnh dưới đây bám theo external tree hiện tại:
mkdir -p ~/esp32-s31-lab && cd ~/esp32-s31-lab
git clone --branch 2025.02 --depth 1 \
https://gitlab.com/buildroot.org/buildroot.git esp-buildroot
git clone --branch buildroot/v2025.02-esp32s31 \
https://github.com/espressif/esp-buildroot-external.git
Cấu hình cho Function Core Board boot từ NOR flash:
make -C esp-buildroot \
BR2_EXTERNAL="$PWD/esp-buildroot-external" \
O="$PWD/esp32-s31-linux" \
espressif_esp32s31_function_core_board_nor_defconfig
Sau đó build:
ESP_ESPTOOL="$(command -v esptool)" \
make -C esp-buildroot O="$PWD/esp32-s31-linux" -j"$(nproc)"
Lần đầu có thể mất hơn một giờ vì Buildroot tải và biên dịch toàn bộ toolchain, bootloader, kernel và rootfs. Kết quả quan trọng nằm tại:
esp32-s31-linux/images/s31_full_flash.bin
Flash và mở console
Hãy thay <serial-port> bằng cổng thật, chẳng hạn /dev/ttyUSB0 hoặc /dev/cu.usbserial-*:
esptool --chip esp32s31 \
--port <serial-port> \
--baud 1152000 \
write-flash 0x0 esp32-s31-linux/images/s31_full_flash.bin
Console Linux chạy ở 115200 baud:
picocom -b 115200 <serial-port>
# hoặc
screen <serial-port> 115200

UART console là nền tảng rõ nhất; ngoại vi và networking vẫn phải kiểm tra theo từng commit.
Sau khi thấy BusyBox shell, mình chỉ kiểm tra một nhóm lệnh nhỏ trước:
uname -a
cat /proc/cpuinfo
cat /proc/meminfo
mount
df -h
dmesg | tail -n 30
Mục tiêu ban đầu là xác nhận kernel, RAM, rootfs và console ổn định. Đừng vội lấy việc hiện prompt làm bằng chứng rằng Wi-Fi, USB, SD hoặc toàn bộ ngoại vi đã hoạt động.
Ba hướng Linux trên S31 hiện nay
| Hướng | Kernel | Trạng thái đáng chú ý |
|---|---|---|
| Espressif ESP Linux BSP | 6.18 fork | Developer Preview; chuỗi Buildroot/U-Boot chính thức, chưa khuyến nghị production |
GrieferPig esp32-s31-linux | 6.12 | Rootfs và reboot ổn định theo bảng trạng thái; Wi-Fi/driver còn experimental |
annoyedmilk/esp32-s31-linux | 7.1 + OpenSBI 1.9 | Có LCD, microSD, USB HID và thử nghiệm Wi-Fi; nhiều ngoại vi còn thiếu |
Điểm dễ nhầm lẫn nhất là Wi-Fi. Port GrieferPig ghi ESP-Hosted ở mức experimental. Project Linux 7.1 có firmware giữ một hart để quản lý radio, nhưng README hiện vừa mô tả lệnh wifi, vừa liệt kê việc association chưa hoàn thiện. Còn BSP chính thức chưa công bố ma trận driver đủ rõ. Vì vậy, ở thời điểm viết bài, mình xem UART console là nền tảng đã rõ nhất; networking cần kiểm tra theo đúng commit và đúng board.
“Hai core” không có nghĩa Linux dùng cả hai
Các port cộng đồng thường để một hart chạy ESP-IDF/FreeRTOS và firmware radio, Linux chạy trên hart còn lại. Đây là cách thực tế để giữ Wi-Fi/Bluetooth proprietary stack mà không phải đưa toàn bộ radio vào kernel.
Vì vậy, câu “vừa chạy FreeRTOS, vừa chạy Linux” khá đúng về kiến trúc thử nghiệm, nhưng không nên hiểu là hai hệ điều hành đã có một API ổn định để chia workload sản phẩm. IPC, cache coherency, DMA, security boundary và lifecycle cập nhật vẫn là những phần khó.
Container cũng chưa phải là use case hợp lý. MMU giúp process model tốt hơn, nhưng 16 MB PSRAM vẫn quá chật cho Docker và các image thông thường. Giá trị gần hơn là BusyBox, networking daemon nhỏ, công cụ POSIX gọn và khả năng tận dụng một phần của hệ sinh thái embedded Linux.
Có nên dùng cho sản phẩm?
Hiện tại, chưa nên. Espressif nói thẳng preview này có cập nhật không đều, breaking change không báo trước, không đảm bảo API/ABI và chỉ hỗ trợ theo best effort. Driver, shutdown, bảo mật, hiệu năng PSRAM và khả năng phục hồi sau lỗi đều cần được đánh giá lâu hơn.
Mình sẽ dùng nó cho ba việc: học boot flow RISC-V, thử Buildroot trên một MCU có MMU, và đo xem workload Linux nhỏ đến đâu thì còn hợp lý. Với sản phẩm cần real-time, boot nhanh và driver đầy đủ, ESP-IDF/FreeRTOS vẫn an toàn hơn. Nếu ứng dụng thật sự cần Linux phong phú, nhiều RAM và package có sẵn, một MPU/SBC nhỏ vẫn tiết kiệm thời gian hơn.
Điều đáng chú ý nhất không phải là “ESP32 chạy được Linux” — S3 đã chứng minh điều đó theo cách NOMMU. Điểm mới là S31 đưa MMU, boot stack từ vendor và các port cộng đồng vào cùng một thời điểm. Đây là bước tiến thật, chỉ là vẫn đang ở bàn lab chứ chưa đến dây chuyền sản xuất.
Tài liệu tham khảo
- Espressif
esp-linux-bsp— Developer Preview cho ESP32-S31 - Espressif
esp-buildroot-external— Buildroot external tree - Espressif Linux kernel fork
- ESP32-S31 product overview và thông số MMU
- ESP32-S31-Korvo-1 V1.1 user guide
- Thông báo ESP32-S31 sản xuất đại trà, 27/7/2026
- GrieferPig/esp32-s31-linux — Linux 6.12 MMU port
- annoyedmilk/esp32-s31-linux — Linux 7.1 và OpenSBI 1.9
- CNX Software — build thử Developer Preview
- Bài thảo luận Facebook được bạn đọc chia sẻ
Chia sẻ
Tiếp tục khám phá
Đọc tiếp
Bài viết liên quan
TinyML trên ESP32: Chạy AI ngay tại thiết bị
Cách mình chạy một model nhận diện người ngay trên ESP32 bằng TensorFlow Lite Micro và ESP-NN, từ giới hạn bộ nhớ đến cách thử ví dụ person_detection.
Thiết kế hệ thống trạng thái cảm xúc cho robot Mochi
Xây dựng state machine cảm xúc cho Robot Mochi: idle, listening, talking, happy, sad, thinking, error và animation dễ thay thế.
Tối ưu thời lượng pin cho robot ESP32 có màn hình
Phân tích thời lượng pin cho robot ESP32 có màn hình: backlight, Wi-Fi, audio, ngoại vi, sleep mode, wake-up và runtime.