Table of Contents

Linux on ESP32S3

Guide to install a minimal Linux distribution on the ESP32-S3-WROOM 1 and compile applications to be executed in the device.

After completing this tutorial, the following main functionalities should be available:

These instructions were tested in Ubuntu 22.04 LTS.

Credit to jcmvbkbc!

Build the toolchain

# Generate configuration for device
git clone https://github.com/jcmvbkbc/xtensa-dynconfig -b original
git clone https://github.com/jcmvbkbc/config-esp32s3 esp32s3
make -C xtensa-dynconfig ORIG=1 CONF_DIR=`pwd` esp32s3.so
export XTENSA_GNU_CONFIG=`pwd`/xtensa-dynconfig/esp32s3.so
 
# Build the actual toolchain
git clone https://github.com/jcmvbkbc/crosstool-NG.git -b xtensa-fdpic
pushd crosstool-NG
./bootstrap && ./configure --enable-local && make
./ct-ng xtensa-esp32s3-linux-uclibcfdpic
CT_PREFIX=`pwd`/builds nice ./ct-ng build
popd

This code may take a while and there will be a few errors when it finishes. Nevertheless, all the binary utilities will still be produced and can be found at crosstool-NG/builds/xtensa-esp32s3-linux-uclibcfdpic/bin/.

Compile an application

Here's an example of how to compile an application:

export PATH=`pwd`/crosstool-NG/builds/xtensa-esp32s3-linux-uclibcfdpic/bin/:$PATH
export XTENSA_GNU_CONFIG=`pwd`/xtensa-dynconfig/esp32s3.so
xtensa-esp32s3-linux-uclibcfdpic-gcc -mfdpic hello.c -o hello

Additionally, the following flags may be added to minimize application stack size: -Wl,-z,stack-size=….

Refer to the following documentation to use gpio]].

Build the kernel and the root filesystem

git clone https://github.com/jcmvbkbc/buildroot -b xtensa-2023.08-fdpic

If required, before compiling, buildroot may be reconfigured by typing.

make menuconfig

In addition, the name of the packages can be simply added to the configuration file, like so:

echo "BR2_PACKAGE_MTD=y" >> configs/esp32s3_defconfig
echo "BR2_PACKAGE_LINUX_TOOLS_GPIO=y" >> configs/esp32s3_defconfig

Furthermore, replace BR2_LINUX_KERNEL_CUSTOM_REPO_URL and BR2_LINUX_KERNEL_CUSTOM_REPO_VERSION by the following to enable runtime reconfigurable stack size.

@@ -13,8 +13,10 @@ BR2_ROOTFS_POST_FAKEROOT_SCRIPT="board/espressif/esp32s3/mkfs-etc.sh"
 BR2_ROOTFS_POST_IMAGE_SCRIPT="board/espressif/esp32s3/post-build.sh"
 BR2_LINUX_KERNEL=y
 BR2_LINUX_KERNEL_CUSTOM_GIT=y
-BR2_LINUX_KERNEL_CUSTOM_REPO_URL="https://github.com/jcmvbkbc/linux-xtensa.git"
-BR2_LINUX_KERNEL_CUSTOM_REPO_VERSION="xtensa-6.6-esp32-gpio"
+BR2_LINUX_KERNEL_CUSTOM_REPO_URL="https://github.com/joaomiguelvieira/linux-xtensa.git"
+BR2_LINUX_KERNEL_CUSTOM_REPO_VERSION="main"
 BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
 BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/espressif/esp32s3/linux.config"
 BR2_LINUX_KERNEL_IMAGE_TARGET_CUSTOM=y
nice make -C buildroot O=`pwd`/build-buildroot-esp32s3 esp32s3_defconfig
buildroot/utils/config --file build-buildroot-esp32s3/.config --set-str TOOLCHAIN_EXTERNAL_PATH `pwd`/crosstool-NG/builds/xtensa-esp32s3-linux-uclibcfdpic
buildroot/utils/config --file build-buildroot-esp32s3/.config --set-str TOOLCHAIN_EXTERNAL_PREFIX '$(ARCH)-esp32s3-linux-uclibcfdpic'
buildroot/utils/config --file build-buildroot-esp32s3/.config --set-str TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX '$(ARCH)-esp32s3-linux-uclibcfdpic'
nice make -C buildroot O=`pwd`/build-buildroot-esp32s3

At this point, the files xipImage, rootfs.cramfs, and etc.jffs2 can be found at build-buildroot-esp32s3/images.

Build the bootloader

IMPORTANT NOTE: A particular esp-idf toolchain will be downloaded to build the bootloader, which usually conflicts with other installations. It is recommended not to have any other installation present, otherwise, the setup might fail.

git clone https://github.com/jcmvbkbc/esp-hosted -b ipc
pushd esp-hosted/esp_hosted_ng/esp/esp_driver
cmake .
cd esp-idf
. export.sh
cd ../network_adapter
idf.py set-target esp32s3
cp sdkconfig.defaults.esp32s3 sdkconfig

Since both the configuration file and the partition table are designed for an 8M external expansion flash, these files can be changed in order to use the entire memory space. In this example, a new partition (opt) will be created using the remaining 8M to be used as writable user space in the device. Note that, by default, only /etc is writable.

~ # diff sdkconfig.defaults.esp32s3 sdkconfig
106,107c106,107
< CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
< # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
---
> # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
> CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
111c111
< CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
---
> CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
1186c1186
< CONFIG_SPIFFS_MAX_PARTITIONS=3
---
> CONFIG_SPIFFS_MAX_PARTITIONS=4
partition_table.esp32s3
## Label          type  ST       Offset      Length
nvs,              data, nvs,     0x0000a000, 0x00005000
phy_init,         data, phy,     0x0000f000, 0x00001000
factory,          app,  factory, 0x00010000, 0x000a0000
etc,              0x40, 0x1,     0x000b0000, 0x00070000
linux,            0x40, 0x0,     0x00120000, 0x00360000
rootfs,           0x40, 0x1,     0x00480000, 0x003d0000
opt,              0x40, 0x1,     0x00850000, 0x007a0000
idf.py build

The following files are now present:

Flash the device

Binary files

The following script requires a working installation of esp-idf. Considering that the name of the device in the system is /dev/ttyACM0, run the following to flash the device:

python ~/esp/esp-idf/components/esptool_py/esptool/esptool.py --chip esp32s3 -p /dev/ttyACM0 -b 921600 --before=default_reset --after=hard_reset write_flash 0x0 bootloader.bin 0x10000 network_adapter.bin 0x8000 partition-table.bin
python ~/esp/esp-idf/components/partition_table/parttool.py write_partition --partition-name linux --input xipImage
python ~/esp/esp-idf/components/partition_table/parttool.py write_partition --partition-name rootfs --input rootfs.cramfs
python ~/esp/esp-idf/components/partition_table/parttool.py write_partition --partition-name etc --input etc.jffs2

Connect to the device

+-----------------------------------------------------------------------+
| A -    Serial Device      : /dev/ttyACM0                              |
| B - Lockfile Location     : /var/lock                                 |
| C -   Callin Program      :                                           |
| D -  Callout Program      :                                           |
| E -    Bps/Par/Bits       : 115200 8N1                                |
| F - Hardware Flow Control : No                                        |
| G - Software Flow Control : No                                        |
|                                                                       |
|    Change which setting?                                              |
+-----------------------------------------------------------------------+

Prepare opt partition

flash_erase -j /dev/mtd6 0 122
echo "mtd:opt         /opt            jffs2   nofail          0       0" >> /etc/fstab
mount -a

Explanation:

Connect to wifi

cd /etc
cp wpa_supplicant.conf wpa_supplicant.conf.bak
cp wpa_supplicant.conf.example wpa_supplicant.conf

Edit the file “wpa_supplicant.conf” by entering your wifi credentials.

References