I've long had my computers set to dual boot between Linux and Windows, but always had to push keys at just the right time during the boot sequence to make my OS selection.  Get distracted and the system boots into its default OS, even if that wasn't what I wanted.  The solution is to have a hardware toggle which can be flipped beforehand and that the computer will read during boot to determine which OS it will boot into.  After seeing Stephen Holdaway's Hardware boot selection switch, I knew I wanted to have one as part of my latest home computer build.

In his build, Stephen uses an STM32 microcontroller acting as a USB mass-storage device to report the state of an attached toggle switch.  The microcontroller serves up a dynamic file whose contents can be "sourced" by the grub booting software, setting a variable which will be used to select the desired boot OS.  (He later describes a Simplified hardware boot switch which doesn't need a microcontroller, but merely enables/disables a USB flash drive.  But that's not the route I followed.)

RP2040 Microcontrollers

Because of their current popularity, low cost, and ready availability, I chose to base this project on one of the numerous RP2040 microcontrollers, the pilot of which is the Raspberry Pi Pico.  Not having ventured into the realm of microcontrollers before, I obtained a number of likely candidates and started experimenting.  

One nice feature of the RP2040 boards (though not unique to them) is that most come w/ USB connectors already attached and contain a UF2 bootloader which, when triggered, causes the microcontroller to appear as a USB mass-storage device to which program files may be drag-and-dropped for installation.  Alas, this will not function as the dynamic USB mass-storage we want for this project, but it shows that such behavior is possible, and greatly simplifies the development process.

Trying Python

Another (again, not unique) feature of the RP2040 boards is that they can run MicroPython or CircuitPython allowing programming with a high-level language with no compilers needed and drag-and-drop copying of Python scripts to the microcontroller.  Further,  Micro/CircuitPython can be run in a REPL (read-eval-print) mode providing direct type-and-try access to the microcontroller.

Having some experience w/ Python, I decided to try this approach first.  There were examples available of using an RP2040 board as a USB logging device and reading the resulting file from USB storage which looked promising.  So I wired a toggle switch to an RP2040 microcontroller and went to coding.

The results were less than desired.  I was readily able to configure and read the toggle switch and write the results to a file in the USB-exposed storage area, but there was a hitch in trying to read this file from the booting computer.  Or rather, in reading the current state of the file.  Due to some caching, or optimization, or something, the results I read wouldn't track the switch position in real-time.

Perhaps there was some bit I hadn't twiddled, some incantation I hadn't uttered, or some elder god I hadn't placated.  Perhaps a more knowledgeable practitioner of the Pythonic arts could have made it work.  But as for me, I was stuck.  Python was giving me no joy.

A New Approach

I began searching the web for a possible solution to my dilemma, and came across a posting Hardware Boot Select Switch Using Pico by Madrajib Lab.  He too had seen Stephen Holdaway's original article and created a version of it with the Raspberry Pi Pico. This is what I was looking for!

In his version, Madrajib used the Raspberry Pi Pico SDK and the tinyusb library.  With these and the cdc_msc example from the tinyusb library, he created a USB mass-storage emulation program which served up a single file named switch.cfg whose contents were dynamically created from...

Read more »