====== 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: * Boot into a minimalistic Linux environment; * Connect to a wifi network; * Configure default application stack size; * Read and write GPIOs; * Cross-compile C/C++ applications to be executed on the device. These instructions were tested in Ubuntu 22.04 LTS. **Credit to [[https://github.com/jcmvbkbc | 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 [[https://www.kernel.org/doc/html/latest/driver-api/gpio/legacy.html#paths-in-sysfs | 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 ## 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: * ''build/bootloader/bootloader.bin'', * ''build/partition_table/partition-table.bin'', * ''build/network_adapter.bin''. ===== Flash the device ===== {{ :binaries.tar.gz |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:** * There are 7 partitions in the system, with ''opt'' being the seventh (id=6). Therefore, it is identified as ''/dev/mtd6''. The ''flash_erase'' tool has usage ''flash_erase [options] MTD_DEVICE ''. * Since ''opt'' has a total of 0x007a0000 bytes and blocks are 64KB, there are 122 blocks in opt. ===== 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 ===== - [[https://github.com/jcmvbkbc | Github jcmvbkbc]] - [[http://wiki.osll.ru/doku.php/etc:users:jcmvbkbc:linux-xtensa:esp32s3 | Wiki jcmvbkbc]] - [[https://github.com/ESP32DE | Github ESP32DE]] - [[https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/28339/episode-623-how-to-run-linux-on-an-esp32?CMP=SOM-YOUTUBE-PRG-E14PRESENTS-e14Presents-623 | Element14 Episode 623]]