Use peripherals
These examples cover the standard full board image. Run target commands as root
on the S31; run the explicitly marked build commands on the Linux build host.
Prepare the image using Build from source
in the standard full board configuration. The rootfs includes libgpiod v2 tools, I2C tools,
spidev_test, aplay/arecord, candump, and cansend. The CAN recipe below
also needs full iproute2, and the external-codec recipe needs extra kernel
options.
The examples follow the drivers, shipped overlays, and existing helper/HIL usages. Consult the support matrix for recorded hardware status, and the peripheral reference for controller limits and errors.
Before connecting anything
Use the board default routes to find SoC GPIO numbers, then use your board’s schematic to locate the corresponding pads or connector pins. The repository does not supply a complete header map. Match the electrical levels and connect a common ground where required.
Run one example at a time: UART1, SPI2, and I2S0 defaults reuse GPIO42–45. Inspect active overlays and available routes first:
s31-overlay list
s31-overlay routes uart1
s31-overlay routes gpspi2
s31-overlay routes i2s0
Stop users of conflicting pins and remove the corresponding temporary
overlay before proceeding. Each example uses --volatile, so it does not
change the saved boot selection. A saved overlay restored at boot can still
conflict with a temporary example. Stop if an apply command fails; do not
continue with an assumed device or pin route.
Configure GPIO
Choose Interfaces → GPIO in esp32-config, select a pin, and set its mode:
Mode |
Effect |
|---|---|
Application controlled |
Release the pin for an application or driver |
Input |
Hold an input, with no pull, pull-up, or pull-down |
Output low |
Hold the output at logical 0 |
Output high |
Hold the output at logical 1 |
Select Save and apply to use the setting immediately and restore it when Linux starts. Returning before this step discards the page’s edits. The pin list shows current use and any saved setting that has not been applied. Reserved pins and pins used by another application or interface cannot be claimed by the configuration tool.
For example, with GPIO42 free:
esp32-config gpio list
esp32-config gpio set 42 high
The output remains held after the command or menu exits. To configure GPIO43 as an input with a pull-up, then read it:
esp32-config gpio set 43 input up
esp32-config gpio read 43
The helper holds these requests while it runs. Before using the pins from libgpiod or an interface, release them:
esp32-config gpio set 42 application
esp32-config gpio set 43 application
Selecting application control removes that pin’s saved assignment. Releasing a pin does not promise a particular electrical level afterwards. Startup restoration begins with the Linux service; use board hardware or earlier firmware for a level required from power-on.
GPIO from an application
With GPIO42 and GPIO43 free, connect GPIO42 to GPIO43 for a digital loopback. Inspect the lines:
gpioinfo -c gpiochip0
In one terminal, hold GPIO42 high:
gpioset -c gpiochip0 42=1
In another terminal, read GPIO43. It should report an active/high input:
gpioget --unquoted -c gpiochip0 43
Press Ctrl-C in the first terminal to release the output request, then
repeat with 42=0; GPIO43 should report inactive/low. Ctrl-C releases the
line; applications must not rely on its output level after ownership ends.
Remove the loopback wire before assigning these pins to a peripheral.
These commands use the libgpiod v2 syntax used by the GPIO HIL runner.
UART1 wire loopback
The shipped uart1 overlay routes TX to GPIO42 and RX to GPIO43. Connect
those two pins together, without another transmitter driving RX, and run:
s31-overlay apply uart1 --volatile
s31-hil-io uart /dev/ttyS1 115200 256
s31-overlay remove uart1 --volatile
The helper configures a raw 115200-baud port, sends a 256-byte pattern, and
compares the returned bytes. A successful run prints PASS uart; a missing
wire, timeout, or mismatch fails the command. This uses a physical echo path;
uart-loopback is the helper’s separate internal-loopback operation.
For an external UART device, connect its TX to S31 RX and its RX to S31 TX,
and match framing and baud rate. Keep UART0 available for the console.
See the UART helper implementation
and UART1 routes.
SPI host: wire loopback
For the unmodified gpspi2 overlay, SCLK is GPIO42, MOSI is GPIO43, CS0 is
GPIO44, and MISO is GPIO45. Connect only MOSI to MISO for this loopback.
Run an 8-bit transfer at 100 kHz:
s31-overlay apply gpspi2 --volatile
spidev_test -D /dev/spidev2.0 -s 100000 -b 8 -v -p '\x01\x02\x03\x04'
s31-overlay remove gpspi2 --volatile
The verbose TX and RX byte sequences should match. For a real peripheral, remove the loopback wire, connect SCLK/MOSI/MISO/CS as required, and use that peripheral’s mode, transaction format, and permitted clock rate. The host driver accepts only 8-bit words; 16/32-bit support belongs to target mode. The shipped spidev child also caps transfers at 20 MHz.
The existing s31-hil-io spi helper expects an external responder that returns
a specific transformed pattern; it is not a MOSI/MISO echo checker. Sources:
host word mask,
overlay defaults,
spidev_test options.
SD card and USB storage
Before changing or disabling an SDMMC interface, unmount its filesystems and stop any SD-backed swap. Both card slots share the controller, so check both slots. The configuration menu refuses changes while any SD card is mounted or used as swap; saving unchanged settings leaves the controller running.
The following commands assume an existing FAT partition. Check the detected
devices and replace the example partition name if necessary; a whole-device
filesystem uses the disk node instead of a p1/1 partition node.
For SDMMC0, connect a suitable card socket to the fixed pins in the board
table. The stock overlay selects a 4-bit bus; a 1-bit wired socket needs
bus-width=1 when applying it. Ensure the card socket provides a 10 kΩ
pull-up on the card’s DAT3 pin even if DAT3 is disconnected from the S31.
DAT3 must stay high during initialization for native SD mode; a pull-up on
an unconnected S31 pad cannot bias the card pin. See the pinned
S31 card wiring and 1-bit note
and Linux’s SD initialization requirement.
With the socket wired and powered, run:
s31-overlay apply sdmmc0 --volatile
ls /sys/class/mmc_host
cat /proc/partitions
mkdir -p /mnt/sd
mount -t vfat -o ro /dev/mmcblk0p1 /mnt/sd
ls /mnt/sd
umount /mnt/sd
s31-overlay remove sdmmc0 --volatile
USB host mode is selected by the base tree. Ensure usb-device is not active,
connect the drive through the board’s DWC2 host connection, and inspect the
new disk before mounting it:
cat /proc/partitions
dmesg | tail -n 30
mkdir -p /mnt/usb
mount -t vfat -o ro /dev/sda1 /mnt/usb
ls /mnt/usb
umount /mnt/usb
Successful directory listing establishes access to that filesystem. If no device enumerates, inspect power, wiring, the driver probe messages, and the selected role. If the disk appears but mounting fails, check the partition and filesystem type. The full kernel includes VFAT and EXT4; this example mounts VFAT read-only. The repository also provides SD read and USB mount HIL cases.
Audio with an external codec
Follow Audio with an external codec for a complete PCM5102A playback integration, including wiring, kernel options, the card overlay, and playback checks. That guide also covers capture with the shipped clock-consuming I2S overlays.
USB CDC ACM gadget
Follow USB CDC ACM gadget to switch the DWC2 role, configure a serial function, discover its device node, and return to host mode after cleanup.
CAN with an external transceiver
Connect TWAI0 TX/RX to a suitable CAN transceiver using the board table, then connect a correctly terminated bus with another active node at the same bit rate. That node supplies acknowledgments and can transmit a known frame for the receive check.
The rootfs selects candump and cansend, but the current source defconfig
does not select iproute2. Before using the ip ... type can command below,
set this in buildroot-external/configs/esp32s31_rootfs_defconfig on the host,
replacing its existing disabled entry, then save, reconfigure and rebuild the
matched image set:
BR2_PACKAGE_IPROUTE2=y
make buildroot-reconfigure
make fetch
make image
make flash-existing-all PORT=/dev/ttyUSB0
On the S31, configure a 500 kbit/s bus:
s31-overlay apply twai0 --volatile
ip link set can0 type can bitrate 500000
ip link set can0 up
ip -details -statistics link show can0
candump can0
While candump runs, send this frame from a second terminal and inspect it
on the peer. Have the peer send a known frame back and inspect candump:
cansend can0 123#11223344
Stop candump with Ctrl-C, then release the interface:
ip link set can0 down
s31-overlay remove twai0 --volatile
Inspect error counters and peer reception if transmission fails. CAN remains work in progress in the support matrix. Sources: rootfs package choices, SocketCAN bitrate setup.
Ethernet with the shipped PHY configuration
The gmac overlay enables the base RGMII configuration for a YT8531DC-CA PHY
at MDIO address 0, with reset on GPIO7. Use the board table and the base DTS to
match the RGMII/MDIO wiring, PHY address, reset, and delays; describe a different PHY in
a board-specific device tree.
On a matching board connected to a DHCP network:
s31-overlay apply gmac --volatile
ip link set eth0 up
cat /sys/class/net/eth0/carrier
udhcpc -n -q -i eth0
ip addr show dev eth0
Carrier should become 1; a successful DHCP exchange supplies an address.
Use that address for a packet exchange with a known peer. If DHCP fails,
inspect link state and the network’s address service separately. After closing applications
using Ethernet:
ip link set eth0 down
s31-overlay remove gmac --volatile
The recipe follows the specific PHY description and existing Ethernet probe/link checks. Record your board revision, PHY, kernel/configuration, link partner, and observations when reporting hardware results.