Automatic BOOTSEL mode

Hello guys,

I am building an RP2040 Connect based device and I would like to make firmware update a user-friendly process.
Currently I see two possibilities:

  • Disassembling the whole device for reaching reset button
  • Installing Arduino IDE + Core + Libs

Both ways are very suboptimal, and second- also requires disclosing the source code, which I would not like to do

Optimal way would be some official, easily available GUI app that would put the board into BOOTSEL mode, allowing drag-n-drop updated UF2 binary, but that does not exist, as far as I am aware
So another approach, that seems very doable- would be sending RP into BOOTSEL automatically, when USB connection is detected. It is supplied via VIN, and usb operation is not part of a normal use-case, so no conflicts should arise.
I saw some data online about corresponding registers, that help identify USB enumeration, but I am not quite sure how to use those. Restarting it into BOOTSEL programmatically seems possible as well.
If you have some more data on that, or, ideally, some related usable code- I would totally appreciate that!

Thanks!

TinyUSB does the trick

#include "WiFiNINA.h"
#include "Adafruit_TinyUSB.h"
#include "pico/bootrom.h"

void autoBOOTSEL(){
  for(int i=0; i<10; i++){
    if(TinyUSBDevice.mounted()){
      reset_usb_boot(1 << DigitalPinToPinName(LED_BUILTIN), 0);
    }
    else{
      delay(100);
    }
  }
}

void setup() {
  // put your setup code here, to run once:
  autoBOOTSEL();
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LEDB, HIGH);
  delay(300);
  digitalWrite(LEDB, LOW);
  delay(300);
}

It unfortunately takes a while to detect the connection.
400mS in my case (macOS), so I gave it twice that time
Could be a better and quicker way, but that is perfectly good for me

Blinks blue if powered via VIN or USB wall charger, and goes BOOTSEL if connected to a computer

I use pico core, and I failed to compile it for mbed, but I am pretty sure that can be figured

Hi @kaws. You can put the board into boot mode by opening its serial port on the PC, with the port configured for 1200 baud, then closing the port again.

This is how Arduino IDE puts the board into boot mode when you do an upload.

Sure, but again
Imagine making people not just download the software they absolutely don't need, but also dance around with it in a very specific matter, like click that, and then that, be careful not to choose the wrong option, yadayada, that's a ridiculous user experience

I never said anything about the user downloading software they don't need and "dancing".

If you don't want the user to use Arduino IDE, you are free to create your own PC application that activates the boot mode by doing a "1200 bps touch" on the board's port. This is the reason I shared the information about the specific mechanism for triggering the boot mode externally.

I appreciate your suggestion, @ptillisch, and I am sorry, if my message sounded mean
And hi :upside_down_face:

The problem with self-written program is, for example, macOS being not happy with it, cause it's not signed and stuff, so you'll have to specifically allow it to run.
And since my particular application does not utilise usb anyways- I see no good reason to struggle. Even a bit :wink:

Signing and notarizing your application is actually not very difficult thanks to some excellent tools the open source community has created (Arduino uses gon).

You do need a certificate, which is obtained by paying $99/year to join the Apple Developer Program. That expense can be a barrier for hobby developers, but is insignificant if you are developing a commercial product. Since you don't want to share your precious source code, I have to assume you are in the latter category.

1 Like

Who says hobby developer can not do a commercial product :stuck_out_tongue_winking_eye:
They can at least try, to miserably fail then, hehe

Thanks for valuable information, I am definitely taking note of that

Here comes the native one, no TinyUSB needed, works both for Mbed and Pico

#include "WiFiNINA.h"
#include "pico/bootrom.h"
#include "hardware/structs/usb.h"

void autoBOOTSELnative(){
    // Check if the USB is connected for 10ms
    for (unsigned u = 0; u < 10; u++)
    {
        if ((usb_hw->phy_direct & (USB_USBPHY_DIRECT_RX_DP_BITS | USB_USBPHY_DIRECT_RX_DM_BITS)) ==  USB_USBPHY_DIRECT_RX_DP_BITS)
        {
            reset_usb_boot(1 << digitalPinToPinName(LED_BUILTIN), 0);
        }
        busy_wait_ms(1);
    }
}

void setup() {
  // put your setup code here, to run once:
  autoBOOTSELnative();
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LEDB, HIGH);
  delay(300);
  digitalWrite(LEDB, LOW);
  delay(300);
}

1 Like