Writing applications
Applications run in a small Buildroot environment with musl libc and a BusyBox shell. Hardware is accessed through Linux device files, sockets, and sysfs.
Build, install, and run a C program
Complete Build from source first, including the ESP-IDF environment. Run the host commands below from the project root. Deploy application updates with the complete verified image set, because rootfs carries the kernel’s matching radio module. See Build configuration.
Create hello.c on your development computer:
#include <stdio.h>
int main(void)
{
puts("Hello from ESP32-S31 Linux!");
return 0;
}
Compile it, put the binary in the board filesystem overlay, and build and flash
the updated rootfs. Replace /dev/ttyUSB0 with the board’s port and close the
serial monitor before flashing:
cache/toolchains/riscv32-esp-linux-musl/bin/riscv32-esp-linux-musl-gcc \
-Os -march=rv32imafbc_zicsr_zifencei_zaamo_zalrsc_zba_zbb_zbc_zbs \
-mabi=ilp32 -mtune=esp-base hello.c -o hello
install -D -m 0755 hello \
buildroot-external/board/esp32-s31/overlay/usr/bin/hello
make image
make flash-existing-all PORT=/dev/ttyUSB0
make image publishes the verified set to dist/current; flash-existing-all verifies
and writes that set without rebuilding. It preserves persist only on boards
already using the same flash layout. Reopen the serial console after flashing,
log in, and run on the board:
hello
The program prints Hello from ESP32-S31 Linux!. This workflow uses the existing
flashing connection; the default image has no SSH server. For repeated development
or applications with dependencies, use the Buildroot package
example instead of maintaining a
precompiled binary in the overlay.
Use libesp-simd
libesp-simd exposes the port’s XespV 2.2 memory and string operations through
esp_simd.h. The library package installs its header and libraries into
out/buildroot/staging, and the shared library into the image.
Create simd-demo.c on the host:
#include <stdio.h>
#include <string.h>
#include <esp_simd.h>
int main(void)
{
const char message[] = "SIMD copy";
char copy[sizeof(message)];
int rc = esp_simd_init();
if (rc) {
fprintf(stderr, "esp_simd_init: %s\n", strerror(-rc));
return 1;
}
esp_simd_memcpy(copy, message, sizeof(message));
printf("CPU%d: %s\n", esp_simd_cpu(), copy);
return strcmp(copy, message) != 0;
}
After a successful make rootfs, compile and install it with:
cache/toolchains/riscv32-esp-linux-musl/bin/riscv32-esp-linux-musl-gcc \
-Os -march=rv32imafbc_zicsr_zifencei_zaamo_zalrsc_zba_zbb_zbc_zbs \
-mabi=ilp32 -mtune=esp-base -Iout/buildroot/staging/usr/include \
simd-demo.c -Lout/buildroot/staging/usr/lib -lesp-simd -o simd-demo
install -D -m 0755 simd-demo \
buildroot-external/board/esp32-s31/overlay/usr/bin/simd-demo
make image
make flash-existing-all PORT=/dev/ttyUSB0
Run simd-demo from the board console. With initialization successful, it prints
CPU1: SIMD copy.
The library constructor attempts to pin the initial thread to CPU1 before
main(). SIMD operations also initialize each calling thread on its first use.
esp_simd_init() returns zero on success or a negative errno value on affinity
failure; the wrappers use scalar fallbacks if initialization fails. This affinity
change applies to the whole calling thread, including its non-SIMD work. Once
initialized, do not move that thread to CPU0 or broaden its CPU affinity: the
library caches successful initialization and does not recheck later affinity
changes. For raw instructions and compiler ABI choices, see
ISA and ABI.
The library implementation
and rootfs/s31_string_bench.c provide more examples. A Buildroot package using
the library should select BR2_PACKAGE_ESP_SIMD, add esp-simd to its package
dependencies, and link with -lesp-simd.
Access hardware
These interfaces are available when the corresponding kernel driver and hardware are enabled. The standard image selects the full board configuration.
Hardware |
Application interface |
|---|---|
UART |
TTY and termios |
GPIO |
GPIO character devices and libgpiod |
I2C |
|
SPI |
|
Audio |
ALSA PCM |
CAN |
SocketCAN |
Wi-Fi and Ethernet |
Network sockets |
Analog inputs and outputs |
IIO |
Watchdog |
Linux watchdog device |
LP core |
|
Bluetooth, default setup |
BTstack and |
Enable an optional peripheral’s overlay before opening it. The peripheral reference contains command-line examples.
Files, settings, and other tools
See Configuration for persistent and temporary storage. Deployment exceptions for package-owned files are documented in Adding a userspace tool. The command reference covers the included board configuration, overlay, LP, and test utilities.