Skip to content

Instantly share code, notes, and snippets.

@sqrtroot
Created August 22, 2021 20:44
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sqrtroot/09da3fbc5ea47504afcdc2ffb56c3694 to your computer and use it in GitHub Desktop.
Save sqrtroot/09da3fbc5ea47504afcdc2ffb56c3694 to your computer and use it in GitHub Desktop.
Did you get sick of unplugging and replugging your raspberry pi pico. Repurpose the bootsel button, hold it for ~500ms and it will restart into usb boot mode!
#include <cstdio>
#include <hardware/gpio.h>
#include <hardware/regs/psm.h>
#include <hardware/structs/ioqspi.h>
#include <hardware/structs/sio.h>
#include <hardware/sync.h>
#include <pico/bootrom.h>
#include <pico/critical_section.h>
#include <pico/stdlib.h>
class CriticalSection {
critical_section_t cs;
public:
CriticalSection() {
critical_section_init(&cs);
critical_section_enter_blocking(&cs);
}
CriticalSection(unsigned int locknum) {
critical_section_init_with_lock_num(&cs, locknum);
critical_section_enter_blocking(&cs);
}
~CriticalSection() {
critical_section_exit(&cs);
critical_section_deinit(&cs);
}
};
namespace BootselReset {
const uint CS_PIN_INDEX = 1;
void set_chip_select_override(const gpio_override override) {
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
override << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
}
bool __no_inline_not_in_flash_func(get_bootsel_button)() {
CriticalSection critSection;
set_chip_select_override(GPIO_OVERRIDE_LOW);
for (unsigned int i = 0; i < 1000; ++i) {
__asm("nop");
};
bool button_state = !(sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX));
set_chip_select_override(GPIO_OVERRIDE_NORMAL);
return button_state;
}
void check_for_bootsel_reset() {
if (get_bootsel_button()) {
sleep_ms(500);
if (get_bootsel_button()) {
reset_usb_boot(0, 0);
}
}
}
} // namespace BootselReset
int main() {
stdio_init_all();
sleep_ms(1000);
for (int i = INT32_MIN; true; i++) {
BootselReset::check_for_bootsel_reset();
std::printf("Hello world %d\n", i);
}
}
@riozebratubo
Copy link

Hello.

Nice snippet! It's an addition to the toolbox of every begginer on the Pico.

I tried running it in a existing project that uses multicore. While core1 runs stuff, just calling BootselReset::check_for_bootsel_reset() a few times would freeze the program. Perhaps you have any idea on why?

Thank you very much.

@sqrtroot
Copy link
Author

@riozebratubo Yes since the pico uses the pin for the boot button for the flash as well, flash access is temporarily disabled when checking the boot select pin (this is also why it's marked no inline and not_in_flash). If the second core tries to execute something from flash in that time it will crash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment