This guide provides a step-by-step workflow to bridge physical STM32 hardware into a virtualized ROS 2 DevContainer.
It leverages PlatformIO and usbipd to enable firmware flashing from a Docker environment.
Github project for this tutorial:
Shopping list:
In order to get WSL, simply open a PowerShell terminal in Admin mode:
Right click the Windows Start menu > Windows PowerShell (Admin).
In the terminal type the following command:
wsl --installIt downloads the last Ubuntu (by default) Linux distribution.
In order to activate the WSL 2 version (useful for Docker and USB tools) we have to specify it:
wsl --set-default-version 2
Restart your computer to apply changes.
For this tutorial we use the 5.3.0 version of usbipd (for Windows).
Once downloaded, install it by double clicking the usbipd-win_5.3.0_x64.msi file.
From a PowerShell command, type this command:
usbipd list
Connected: BUSID VID:PID DEVICE STATE 3-1 0483:3748 STM32 STLink Not shared
We obtain a busID (3-1 in our case) that we have to share with WSL.
Type the following command:
usbipd attach --wsl --busid 3-1
usbipd: info: Using WSL distribution 'Ubuntu-24.04' to attach; the device will be available in all WSL 2 distributions. usbipd: info: Loading vhci_hcd module. usbipd: info: Detected networking mode 'nat'. usbipd: info: Using IP address 172.29.26.1 to reach the host.
usbipd list
Connected: BUSID VID:PID DEVICE STATE 3-1 0483:3748 STM32 STLink Attached
So your device is now shared from Windows to Ubuntu (Linux) and the STM32 board is available from our container inside Ubuntu.
If you encounter errors, then, uninstall usbipd, restart your computer and reinstall it.
And above all, each time you remove your board, you'll have to attach again the board with usbipd.
For this tutorial we are going to create a bind mount between our local project folder and the container created by Docker.
It means our local project and the container's workspace are always in sync, any change made in one is immediately reflected in the other.
So every modification will be syncronized on the both directories.
For example, my local project is named ros2.
The specificity of using WSL 2 is that this directory can be reached through 3 different paths, depending on where you are looking from:
Despite these different names, they are exactly the same set of files, changing a line of code in /workspaces/ros2 will instantly update the file at /home/mika/p/ros2 and also from the Windows network.
From Ubuntu, create a .devcontainer folder inside your project directory (/home/mika/p/ros2) in order to have this directory tree:
/home/mika/p/ros2/.devcontainer/ros-dev-ok/ ├── Dockerfile └── devcontainer.json
We have now 2 files inside the .devcontainer directory.
Copy and paste the content of these 2 files from Github.
The Dockerfile:
The devcontainer.json file explains how to build and configure the container:
In order to activate all features from your Dockerfile and devcontainer.json files, your board has to be connected before building your container.
Otherwise you won't have the persmissions to read and use your board.
Furthermore, the postStartCommand line has to be changed if you have rebuild the project from another folder name (different from our example ros2) and modify the part "/worskspaces/YOUR_FOLDER_NAME/".
Then to open our project in the DevContainers extension, simply type CTRL + SHIFT + P in order to open the palette feature of VSCode.
Choose the option in the list: Dev Containers: Rebuild and Reopen in container.
If everything went OK you are now in the container.
You can check from your Docker container that your board is seen by your container, with the following commnand:
st-info --probe
Found 1 stlink programmers version: V2J24 serial: 56FE73964985155216130889 flash: 262144 (pagesize: 2048) sram: 40960 chipid: 0x422 dev-type: STM32F302_F303_358
But even if every seems fine, the PlatformIO extension needs at least 2 minutes to load, so wait a bit for the extension to work and install automatically.
A new popup will appear to show that the PlatformIO has been successfully installed and inviting you to Reload Window.
Click Reload Window.
A new ant icon will then appear on the left menu bar.
If it's the case, then click it in order to open the PlaftformIO panel.
Inside the PIO Home directory, select the Project & Configuration line.
On the center of VSCode you should see the PIO Home.
Note that the following project code is already on Github, so either create a new one with a different name or use the one already available.
Click Create a New Project.
Then:
Don't worry for the Arduino framework, it brings all the files necessary, even for the STM32 boards.
Then click Finish.
The PlatformIO is going to download files for your project, so "Please wait..." about 5 minutes because it has to download a lot of files from Internet.
Once the downloads done, your project name has been generated with double backslashes ("\\") like it was on Windows.
This is a bug and we are going to move the project from the wrong path to the ros2 folder.
Let's start by setting your path to /workspaces/ros2 (if not already done):
cd /workspaces/ros2/
By default the projects are created in the following directory and should look to something like this:
Let's move it to the right directory:
mv ~/Documents/PlatformIO/Projects\\stm32-project-1/ /workspaces/ros2/
Even with this move, there is still one backslash:
/workspaces/ros2/Projects\stm32-project-1
Let's finish it by removing it totally:
mv 'Projects\stm32-project-1'/ stm32-project-1
Your PlatformIO project is now ready to be used.
Let's enter in this new directory:
cd stm32-project-1
You can see all the following files:
/workspaces/ros2/stm32-project-1 |-- .gitignore |-- .vscode |-- include |-- lib |-- platformio.ini |-- src `-- test
Let's now open the following file:
/home/mika/p/ros2/stm32-project-1/src/main.cpp
And replace the content of this file by the following code:
We are now ready to flash (upload) the firmware (code) to the board.
Let's set the path to:
cd /home/mika/p/ros2/stm32-project-1
Then type the command:
pio run --target upload
You should see something like this appears on your terminal:
Processing disco_f303vc (platform: ststm32; board: disco_f303vc; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------------------
Tool Manager: Installing platformio/tool-stm32flash @ ~0.7.0
Downloading [####################################] 100%
Unpacking [####################################] 100%
Tool Manager: tool-stm32flash@0.7.0 has been installed!
Tool Manager: Installing platformio/tool-stm32duino @ ~1.0.1
Downloading [####################################] 100%
Unpacking [####################################] 100%
Tool Manager: tool-stm32duino@1.0.1 has been installed!
Tool Manager: Installing platformio/tool-openocd @ ~3.1200.0
Downloading [####################################] 100%
Unpacking [####################################] 100%
Tool Manager: tool-openocd@3.1200.0 has been installed!
Tool Manager: Installing platformio/tool-dfuutil @ ~1.11.0
Downloading [####################################] 100%
Unpacking [####################################] 100%
Tool Manager: tool-dfuutil@1.11.0 has been installed!
Tool Manager: Installing platformio/tool-dfuutil-arduino @ ~1.11.0
Downloading [####################################] 100%
Unpacking [####################################] 100%
Tool Manager: tool-dfuutil-arduino@1.11.0 has been installed!
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/disco_f303vc.html
PLATFORM: ST STM32 (19.5.0) > ST STM32F3DISCOVERY
HARDWARE: STM32F303VCT6 72MHz, 40KB RAM, 256KB Flash
DEBUG: Current (stlink) On-board (stlink) External (blackmagic, cmsis-dap, jlink)
PACKAGES:
- framework-arduinoststm32 @ 4.21200.0 (2.12.0)
- framework-cmsis @ 2.60300.0 (6.3.0)
- framework-cmsis-dsp @ 1.16.2
- tool-dfuutil @ 1.11.0
- tool-dfuutil-arduino @ 1.11.0
- tool-openocd @ 3.1200.0 (12.0)
- tool-stm32duino @ 1.0.1
- tool-stm32flash @ 0.7.0
- toolchain-gccarmnoneeabi @ 1.120301.0 (12.3.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 14 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Compiling .pio/build/disco_f303vc/FrameworkArduinoVariant/PeripheralPins.c.o
...
Compiling .pio/build/disco_f303vc/SrcWrapper/src/HAL/stm32yyxx_hal.c.o
...
Compiling .pio/build/disco_f303vc/SrcWrapper/src/HardwareTimer.cpp.o
Compiling .pio/build/disco_f303vc/SrcWrapper/src/LL/stm32yyxx_ll_adc.c.o
...
Compiling .pio/build/disco_f303vc/SrcWrapper/src/new.cpp.o
...
Compiling .pio/build/disco_f303vc/SrcWrapper/src/syscalls.c.o
Compiling .pio/build/disco_f303vc/src/main.cpp.o
Compiling .pio/build/disco_f303vc/FrameworkArduino/HardwareSerial.cpp.o
...
Archiving .pio/build/disco_f303vc/libFrameworkArduino.a
Indexing .pio/build/disco_f303vc/libFrameworkArduino.a
Linking .pio/build/disco_f303vc/firmware.elf
Checking size .pio/build/disco_f303vc/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM: [ ] 3.1% (used 1264 bytes from 40960 bytes)
Flash: [= ] 5.5% (used 14308 bytes from 262144 bytes)
Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, jlink, mbed, stlink
CURRENT: upload_protocol = stlink
Uploading .pio/build/disco_f303vc/firmware.elf
xPack Open On-Chip Debugger 0.12.0-01004-g9ea7f3d64-dirty (2023-01-30-15:03)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
debug_level: 1
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
[stm32f3x.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08002678 msp: 0x2000a000
** Programming Started **
Warn : Adding extra erase range, 0x08003984 .. 0x08003fff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked
================================================== [SUCCESS] Took 46.16 seconds ==================================================If yes, then your board should blink the blue LED on your board.
You have now connected your device through a large process from Windows, WSL, Ubuntu, DevContainers and PlatformIO.
Well done!! ![]()
Add new comment