This guide was created on behalf of the Arm Software Developers team, follow us on Twitter: @ArmSoftwareDev and YouTube: Arm Software Developers for more resources!
AboutIf you are maintaining an open-source embedded project, it might be difficult to onboard new devs as the complexity and individuality of a particular setup can vary greatly. Furthermore, if you are going to receive contributions from the community, you might want to have a way of ensuring their validity via automated testing. For this reason, I've set out to find a workflow that will allow me to remotely flash embedded hardware (initially just a Raspberry Pi Pico) and integrate community PRs into a testing framework with GitHub actions. This will automatically ensure they pass a series of tests before merging the changes, and therefore reduce the friction of developing for embedded projects.
OverviewThis guide will focus on setting up the remote-flashing rig using GitHub codespaces which allows us to work on an existing embedded project remotely, change the code, then flash our Raspberry Pi Picos with new code directly from the online environment. This is enabled by a Raspberry Pi 4 running balenaOS which we connect to from our Codespace.
Benefits:
- Reproducible setup
- Easy onboarding
- Automatic testing on the target device
Downsides:
- Requires extra hardware
Part 1: balenaOSFirst, set up a Raspberry Pi 4 with balenaOS to easily connect to it later on.
1. Go to this repository
2. Click on the "deploy with Balena" button
3. Fill in the options as shown:
4. Fill in the options (including your Wi-Fi credentials so the Pi knows how to connect to the internet and then to Balena Cloud):
5. Download the balenaOS image
6. Flash your sd card with the image using Etcher
7. Plug your Raspberry Pi Pico into the Raspberry Pi 4
8. Wire the debug pins as shown on the Pico's documentation
With the Raspberry Pi 4 ready and the Pico connected, we can look into how to flash it remotely.
Part 2: Codespaces1. Fork this repo
2. Create a Codespace for the repo you just forked
3. Run chmod +x pico_setup.sh on your Codespace terminal
4. Run./pico_setup.sh
5. Run export PICO_SDK_PATH="/workspaces/fade/pico/pico-sdk"
Now you should be able to build a Pico project such as the LED fade example included on this repo:
6. Run the following to build the fade project (pwm_led.c):
mkdir build
cd build
cmake..
make
Alternatively, I've also included a bash script named compile.sh that will compile your pwm_led.c file again after you make changes to it. This way, you don't have to re-do the steps above each time.
Part 3: balena CLINext, use the balena CLI to easily tunnel into the Raspberry Pi device to send the compiled file we just made (/build/pwm_led.elf) to remotely flash our Pico.
To add Balena CLI, run the following commands:
export PATH="$PATH:/workspaces/fade/balena-cli"
balena login
Then choose the credentials option and sign in to your balena account.
Now that we have the balena CLI available, we should be able to tunnel into our Raspberry Pi 4 (which has the Pico connected to it) and deliver the.elf file directly to the Pico, in effect, flashing it remotely from within our codespace environment.
1. Run balena devices --app MCU-remote to find the UUID of the device running your application.
>>>https://dashboard.balena-cloud.com/devices/<YOUR_DEVICE_UUID>/summary
2. Run balena tunnel <YOUR_DEVICE_UUID> -p 22222:4321 to ensure we can get through the firewall.
3. Click on the + symbol to open another terminal window
From here, we need to stay in the second terminal window you just opened in Codespaces. Below are the manual steps to get our pwm_led.elf file onto our Pico. However, similar to before with the compile script, I have also provided an upload script that automates this step, so if you're short on time, feel free to skip this section.
4. Find your container ID and make a note of it, this will let us copy the file directly to the container running on the RPi4:
ssh -Tp 4321 root@127.0.0.1 balena ps -aqf "name=flashing"
>>> <YOUR_CONTAINER_ID>
4. Add file to RPi4 Host OS:
scp -P 4321./build/pwm_led.elf root@127.0.0.1:/mnt/data/
5. Copy the file in /mnt/data/pwm_led.elf (in Host OS) into the flashing container:
ssh -Tp 4321 root@127.0.0.1 balena cp /mnt/data/pwm_led.elf <YOUR_CONTAINER_ID>:/pico_flashing/pwm_led.elf
6. Run this to ssh into your RPi4 container and execute the command that grabs the.elf file and flashes it to your Pico using openocd:
ssh -p 4321 root@127.0.0.1 'balena exec <YOUR_CONTAINER_ID> openocd -f interface/raspberrypi-swd.cfg -f target/rp2040.cfg -c "program /pico_flashing/pwm_led.elf verify reset exit"'
To perform all of the upload steps automatically, just run the ./upload.sh script.
As a recap, you have deployed an image onto a Raspberry Pi 4 hooked to a Raspberry Pi Pico, then used GitHub codespaces to change the code on that repository, and reflash the board remotely by running the./compile.sh and./upload.sh scripts.
Now you can use this project as a boilerplate template to easily run code remotely on an embedded device (any supported by openocd should work), in this case, a Raspberry Pi Pico. Change the code on the pwm_led.c file (or add your own C/C++ Pico project) and run the compile & upload scripts to flash the Pico remotely in a single step.
I hope you found this helpful in your embedded projects, particularly if you're going to be onboarding new contributors. I'm also planning another tutorial on how to integrate GitHub actions upon receiving a PR to automatically run tests on the Pico itself, as well as be able to run GDB remotely to see the memory contents of the board as it's stepping through our code. Stay tuned for updates!
Comments