Docker-based ESP32 Development Environment
In the previous article, I discussed the benefits of using Docker containers for building and managing development environments. In this post, I would like to describe how I use the Docker Dev Environment to create a development environment for building ESP32 applications. Additionally, it is also possible to flash the application directly to an ESP board from within the container.
Luckily for us, Espressif has provided a Docker image (espressif/idf
) for building applications and libraries with specific versions of ESP-IDF. It appears that the image is regularly, making it reasonably safe to employ it for our setup.
Setup
- For this setup, you are using a host system running Windows OS with WSL2 enabled. The WSL2 will be used so that we can access the ESP development board from within the container.
Docker Desktop installed
The IDE used here is VSCode with the Dev Containers installed. It lets you use a Docker container as a full-featured development environment.
Constructing compose-dev.yaml
To use the Docker Dev Environment, we need to create the compose-dev.yaml
file. It is quite simple with a few additions.
services:
build-env:
image: espressif/idf
command: sleep infinity
devices:
- '/dev:/dev'
init: true
volumes:
- ..:/workspaces
I added devices: '/dev:/dev'
to map /dev
directory from the WSL2 environment to the Docker container. This is useful for the next step when we want to communicate with the ESP board from inside the container.
Open Docker Desktop and go to Dev Environments. Simply click on the Create button and create the new environment. The container will stay running and you will see the following results.
Flashing and Monitoring ESP32
The ESP-IDF Programming Guide page outlines a method to communicate with the development boards from within the container. The idea is to use the remote serial port protocol (RFC2217). So I tried to follow the method described in the document, but it was not successful for me. Luckily there is another way to achieve this.
An alternative way for accessing the ESP development board from inside the container is using WSL2. By default, WSL2 does not support USB devices. Fortunately, there is a project officially supported by Microsoft that enables WSL2 to be able to access connected USB devices on Windows OS via a USB/IP mechanism. The project is called usbipd-win
.
Setting up usbipd-win
Firstly we need to install
usbipd-win
. We just need to follow the installation instructions described on its Github repository page. It is pretty straightforward.Open the WSL2 terminal and execute
uname -a
. If it reports a kernel version of 5.10.60.1 or later, then you don't need to do anything. Otherwise, follow the instructions on installing USB/IP client tools on WSL2 here.Run Powershell as Administrator and execute the following command.
### Powershell PS C:\Windows\system32> usbipd wsl list BUSID VID:PID DEVICE STATE 2-1 303a:1001 USB Serial Device (COM3), USB JTAG/serial debug unit Not attached 2-2 046d:c534 USB Input Device Not attached 2-3 0bda:4853 Realtek Bluetooth Adapter Not attached 3-1 04f2:b758 Integrated Camera, Integrated IR Camera, Camera DFU Device Not attached
Find the USB device of your ESP development board connected. In this example, it is assigned BUSID 2-1
Attach the USB device to WSL2 by running this command.
### Powershell PS C:\Windows\system32> usbipd wsl attach --busid 2-1 usbipd: info: Using default WSL distribution 'Ubuntu-22.04'; specify the '--distribution' option to select a different one.
Go back to the WSL2 terminal and run
lsusb
to see that the ESP32 development can be accessed from WSL2 now via/dev/ttyACM0
(or/dev/ttyUSB0
).### WSL2 > lsusb Bus 001 Device 014: ID 303a:1001 Espressif USB JTAG/serial debug unit > ls -al /dev/tty* ... crw------- 1 root root 166, 0 Aug 26 17:27 /dev/ttyACM0 ...
Now we need to change the permission so that the device can be accessed by non-root users.
### WSL2 > sudo chmod 666 /dev/ttyACM0
If you remember, we added an extra field in the compose-dev.yaml
file. With this option, we map the /dev
directory of WSL2 into the Docker container. Hence, it is possible to access your development board from inside the container.
...
devices:
- '/dev:/dev'
...
Automating usbipd
Attaching USB devices using usbipd
requires manual steps that need to be executed whenever we plug or re-plug our ESP development board. It can be quite annoying over time. Luckily, there is a convenient GUI that can automate all these steps. This project was created by Andrew Leech. You can just download the package from here and install it.
The GUI is quite self-explanatory. You just need to find your ESP development board and click on 'Auto-Attach'. With this feature enabled, your ESP development board will be attached automatically.
udev
On WSL2, we have to configure the attached USB device so that non-root users can access it. We can use the chmod
command to configure it manually, but then we have to do it every time the USB device is re-attached. To avoid all the hassles, we can create a udev
rule.
Create a new file called 99-usbftdi.rules
on /etc/udev/rules.d/
and add the following information to the file. The {idVendor}
and {idProduct}
values can be obtained from lsusb
> lsusb
Bus 001 Device 014: ID 303a:1001 Espressif USB JTAG/serial debug unit
> cat /etc/udev/rules.d/99-usbftdi.rules
SUBSYSTEM=='usb', ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="0666"
# Then reload udevadm and restart the udev service
> udevadm control --reload
> sudo service udev restart
Now, every time the development board is plugged in, it will be automatically attached to your WSL2 environment and can be readily accessed from the container.
Final Result
Upon the successful creation of the development environment, the container can be opened in VSCode. The VSCode extensions, such as CMake and C++, will also be automatically installed.
If everything is correctly configured, it is possible to build the application inside the container
Since the container can access the USB device via WSL2, we are also able to directly flash the image to the ESP development board.
In this article, we discuss creating a Docker container using the Docker Dev Environment for building ESP32 applications and flashing them directly to an ESP board from within the Docker container. This streamlined workflow simplifies the development process and ensures a consistent development environment across different systems.
You can see the full setup on my Github repository.