Skip to main content
Nastrotek
NotesFirmwareNew

Running Linux on ESP32-S31: What the MMU Changes

ESP32-S31 now has an official Linux BSP Developer Preview. Here is a practical look at its MMU, Buildroot, U-Boot, Linux 6.18, build flow, and the limits that still matter.

Share

LinkedInFacebookX
ESP32-S31 development board connected to a laptop displaying a minimal Linux serial console

“Linux on ESP32” used to sound like either a very slow emulator or a demo that stopped at a shell prompt. This time the story is more substantial: ESP32-S31 has an MMU, and Espressif has published an official Linux BSP as a Developer Preview.

As of August 24, 2026, this is still lab material rather than a safe production platform. Even so, it is a meaningful sign that the line between an MCU and a small Linux SoC is getting thinner.

What makes S31 different?

ESP32-S31 has two 32-bit RISC-V cores running at up to 320 MHz and includes MMU support. The current ESP32-S31-Korvo-1 board uses a module with 16 MB of flash and 16 MB of PSRAM.

An MMU is not an absolute requirement for a Linux kernel to exist: ESP32-S3 already has native NOMMU Linux ports. Without an MMU, however, there is no familiar virtual-memory and process-isolation model, and software depending on normal fork() behavior becomes difficult or impossible to use. S31 lets Linux follow a more conventional memory model instead of forcing the whole userspace into NOMMU constraints.

PlatformHow Linux runsPractical meaning
Xtensa ESP32-S3Native NOMMU LinuxBoots and provides a shell, but userspace is heavily constrained
Older ESP32 with an emulatorEmulated RISC-V or x86Educational, but extremely slow
RISC-V ESP32-S31Native Linux with an MMUCloser to normal embedded Linux, while RAM and drivers remain limited

ESP32-S31-Korvo-1 development board with power UART and USB host connectors

Korvo-1 uses an ESP32-S31-WROOM-3 module with 16 MB flash and 16 MB PSRAM.

I still would not describe S31 as a tiny Raspberry Pi. Sixteen megabytes of PSRAM can hold a minimal Buildroot system, BusyBox, and a few small processes. It does not suddenly provide a desktop, a large package repository, or practical general-purpose containers.

What is in the official BSP?

Espressif explicitly labels the integration/v1.0-esp32s31 branch of esp-linux-bsp as a Developer Preview. The current stack includes:

  • Buildroot 2025.02 for the toolchain and root filesystem.
  • An Espressif Linux 6.18 fork for ESP32-S31.
  • U-Boot SPL, OpenSBI, and a U-Boot FIT image in the boot chain.
  • An XIP kernel executing from NOR flash to preserve PSRAM.
  • A minimal cramfs root filesystem.
  • A merged s31_full_flash.bin image written at offset 0x0.

Workbench note showing the ESP32-S31 Linux boot chain

The BSP packages U-Boot SPL, OpenSBI, U-Boot, an XIP kernel, and cramfs into one image.

The short version of the boot flow is:

ESP ROM → U-Boot SPL → OpenSBI/U-Boot → XIP Linux → cramfs/BusyBox

The esp-linux-bsp repository mainly contains the image layout and packaging tools. Buildroot integration lives in esp-buildroot-external, while the kernel is in Espressif's Linux fork. That means several repositories are involved, but each layer can be inspected instead of relying on an opaque binary image.

Before you try it

The official defconfig currently targets the ESP32-S31 Function Core Board. Community ports commonly target ESP32-S31-Korvo-1. Their connectors and board layouts are different, so follow the hardware guide for the exact board on your desk.

On Korvo-1, the USB-C Power connector only supplies power. The USB-C UART connector is the one connected to the CP2102N bridge for flashing and console access. It is an easy detail to miss when both sockets look similar.

Before flashing:

  • Use a module with 16 MB PSRAM and enough flash for the image.
  • Use a USB data cable.
  • Upgrade esptool to version 5.3.0 or newer.
  • Back up the board's existing firmware and data.
  • Avoid experimenting on a Secure Boot or Flash Encryption device without a recovery plan.

The full image is written from 0x0, replacing the existing firmware, partition table, and stored data.

Build the official Linux image

I recommend a clean Linux environment because the flow is based on Buildroot. These commands follow the current external tree:

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

Configure the Function Core Board for NOR boot:

make -C esp-buildroot \
  BR2_EXTERNAL="$PWD/esp-buildroot-external" \
  O="$PWD/esp32-s31-linux" \
  espressif_esp32s31_function_core_board_nor_defconfig

Then build the image:

ESP_ESPTOOL="$(command -v esptool)" \
make -C esp-buildroot O="$PWD/esp32-s31-linux" -j"$(nproc)"

The first build can take over an hour because Buildroot downloads and compiles the toolchain, bootloader, kernel, and root filesystem. The main output is:

esp32-s31-linux/images/s31_full_flash.bin

Flash and open the console

Replace <serial-port> with the actual UART port, such as /dev/ttyUSB0 or /dev/cu.usbserial-*:

esptool --chip esp32s31 \
  --port <serial-port> \
  --baud 1152000 \
  write-flash 0x0 esp32-s31-linux/images/s31_full_flash.bin

The Linux console runs at 115200 baud:

picocom -b 115200 <serial-port>
# or
screen <serial-port> 115200

ESP32-S31 Linux BusyBox console displayed on a MacBook Pro over UART

UART console is the clearest baseline; peripherals and networking remain commit-specific.

Once BusyBox appears, I start with a small set of checks:

uname -a
cat /proc/cpuinfo
cat /proc/meminfo
mount
df -h
dmesg | tail -n 30

The first goal is to verify the kernel, memory, root filesystem, and console. A shell prompt alone does not prove that Wi-Fi, USB, SD, or every peripheral is ready.

The three current S31 Linux paths

PathKernelNotable status
Espressif ESP Linux BSP6.18 forkOfficial Buildroot/U-Boot preview; not recommended for production
GrieferPig esp32-s31-linux6.12Rootfs and reboot marked stable; Wi-Fi and many drivers remain experimental
annoyedmilk/esp32-s31-linux7.1 + OpenSBI 1.9LCD, microSD, USB HID, and Wi-Fi work in progress; many peripherals are still missing

Wi-Fi is the easiest feature to overstate. GrieferPig lists ESP-Hosted as experimental. The Linux 7.1 project keeps firmware on one hart to own the radio, but its README currently both documents a wifi command and lists association as unfinished. The official BSP does not yet publish a sufficiently clear driver matrix. For now, UART console support is the clearest baseline; networking must be verified against the exact commit and board.

Two cores do not mean Linux owns both

Community ports commonly leave one HART running ESP-IDF/FreeRTOS and the proprietary radio firmware while Linux uses the other HART. This is a practical way to retain Wi-Fi and Bluetooth without reimplementing the entire radio stack in Linux.

It is fair to say that FreeRTOS and Linux can coexist in these experiments, but that does not yet imply a stable product API for sharing workloads. IPC, cache coherency, DMA, security boundaries, and lifecycle updates remain difficult engineering problems.

Containers are not a realistic target either. The MMU improves the process model, but 16 MB of PSRAM is still far too small for Docker and ordinary container images. The nearer-term value is BusyBox, small networking daemons, compact POSIX tools, and selective reuse of the embedded Linux ecosystem.

Should it go into a product?

Not yet. Espressif says the preview receives irregular updates, may introduce breaking changes without notice, provides no API or ABI guarantees, and is supported on a best-effort basis. Driver coverage, shutdown behavior, security, PSRAM performance, and recovery still need much more validation.

I would use it to study the RISC-V boot flow, experiment with Buildroot on an MMU-equipped MCU, and measure how small a useful Linux workload can become. ESP-IDF and FreeRTOS remain safer for products that need deterministic timing, fast boot, and mature peripheral drivers. If the application genuinely needs a broad Linux userspace and much more memory, a small MPU or SBC will still save significant engineering time.

The important part is not simply that “an ESP32 can run Linux” — S3 already proved that through NOMMU ports. The new part is the combination of S31's MMU, a vendor boot stack, and active community ports. It is a real step forward, but it still belongs on the lab bench rather than the production line.

References

Share

LinkedInFacebookX

Keep exploring

Read next

Related articles

View more in Notes

Nastrotek uses cookies for analytics and ad personalization to help us understand how the site is used. You can accept or decline non-essential cookies.