I’m looking more for a brain-storming session than to find specific answers.
I think there’s more than one “right way” to solve this.
A bunch of context
I’m working on a Nix based robotics platform. It’s going really well! I took a Roomba, slapped a Pi on it, enabled the Bluetooth, and started driving it around with a PS4 controller. I wanted to make it do more but the Roomba’s power limitations are stopping me (can’t use more than 25% of the CPU or attach sensors)
Here is the project for that robot
There’s a lot more work to be done before I think these tools are ready for public use but currently it can cross compile, build disk images (with unattended installers), push updates over ssh (supports automatic ssh jumping), and tools to help manage the NixOS firewall for ROS users since DDS tends to be a bit insanitary.
The next objective
This project has always required hardware. It started by just deploying software to a computer on a bench. From there I taped a Raspberry Pi to the top of a Roomba. Now it is time to build my own robot hardware.
Microcontrollers are necessary in robotics for low-level hardware control. Their crude IO, fast reaction times, and simpler (more reliable) software makes them ideal for managing batteries, sensors, and motors. This will be necessary for developing custom hardware for robots.
My current plan
Let’s call the computer on the robot running NixOS “the SoC”, and the Microcontroller we want to flash a binary to “the MCU”.
In prior research I discovered that Nix can be used to build Arduino sketches. The output of that can be passed to a flashing tool. There is no reason alternative platforms can’t be used, as long as a compatible binary is produced. With this, my current “deploy over ssh” solution can be used to get the binary onto the SoC.
The hard part is getting the binary from the SoC onto the MCU.
Putting together a simple tool to flash the binary to the MCU should be pretty simple. The probe-rs project already supports a lot of boards. A shell script wrapping Arduino CLI is probably another good option.
The complex part is determining if we should flash the MCU. Flashing the MCU every time we boot up will significantly reduce the lifespan of its memory. I’ve thought through a few ways to do this, but these two seemed the most practical.
Tracking the software version ourselves
Write the hash of the binary under /var/lib/flash_utility/last_install
after we’ve installed it to the MCU. We then use that to check if we need to update it whenever the system powers up or rebuilds. The only downside I can think of to this is if you were to move the SoC to a new robot body where the firmware is out of sync with /var/lib/flash_utility/last_install
. In that situation, I think it is reasonable for the user to just delete that file and run the flash utility again. As far as I know, the flash utility will need to run as root to access /var/lib
. If it wasn’t for that, we would only need to run the flash utility under a user with dialout
permissions or access to the necessary USB probes.
Asking the MCU for the software version
If the developer adds a way for the flash utility to ask the MCU for the hash of its current firmware, we could use that to check if its up to date. This depends on:
- The developer having implemented that feature
- The MCU being in a working state (actually having firmware on it to begin with)
I’ve chosen not to go with this approach because it felt like too much work to adapt already existing embedded software to. For example, we’d have to make sure they support the flash utilities communication protocol, and that a matching hash algorithm is implemented in whatever is running on that MCU (could be C, C++, Arduino C, Some proprietary fork of C, Rust, Micro Python, lots of others)
Known caveats with my current plan
This only works for boards with some kind of flashing tool attached. Most Arduino compatible devkits will fit this just fine. Some devices that expect to be flashed over Ethernet, I2C, SPI, UART, etc, will not work and will require a custom flash tool. That’s something I think is worth researching into later but I think it’s currently unnecessary.