Created
August 22, 2021 20:44
-
-
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!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 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
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.