diff --git a/cores/rp2040/Arduino.h b/cores/rp2040/Arduino.h index 7b224ea..7240fa3 100644 --- a/cores/rp2040/Arduino.h +++ b/cores/rp2040/Arduino.h @@ -59,7 +59,6 @@ void delay(unsigned long); void delayMicroseconds(unsigned int us); unsigned long millis(); - #ifdef __cplusplus } // extern "C" #endif @@ -68,6 +67,7 @@ unsigned long millis(); #include "SerialUSB.h" #include "SerialUART.h" #include "RP2040.h" +#include "Bootsel.h" // Template which will evaluate at *compile time* to a single 32b number // with the specified bits set. diff --git a/cores/rp2040/Bootsel.cpp b/cores/rp2040/Bootsel.cpp new file mode 100644 index 0000000..63a2717 --- /dev/null +++ b/cores/rp2040/Bootsel.cpp @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/sync.h" +#include "hardware/structs/ioqspi.h" +#include "hardware/structs/sio.h" + +// This example blinks the Pico LED when the BOOTSEL button is pressed. +// +// Picoboard has a button attached to the flash CS pin, which the bootrom +// checks, and jumps straight to the USB bootcode if the button is pressed +// (pulling flash CS low). We can check this pin in by jumping to some code in +// SRAM (so that the XIP interface is not required), floating the flash CS +// pin, and observing whether it is pulled low. +// +// This doesn't work if others are trying to access flash at the same time, +// e.g. XIP streamer, or the other core. + +static bool __no_inline_not_in_flash_func(get_bootsel_button)() { + const uint CS_PIN_INDEX = 1; + + // Must disable interrupts, as interrupt handlers may be in flash, and we + // are about to temporarily disable flash access! + uint32_t flags = save_and_disable_interrupts(); + + // Set chip select to Hi-Z + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, + GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); + + // Note we can't call into any sleep functions in flash right now + for (volatile int i = 0; i < 1000; ++i); + + // The HI GPIO registers in SIO can observe and control the 6 QSPI pins. + // Note the button pulls the pin *low* when pressed. + bool button_state = !(sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX)); + + // Need to restore the state of chip select, else we are going to have a + // bad time when we return to code in flash! + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, + GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); + + restore_interrupts(flags); + + return button_state; +} + +__Bootsel::operator bool() { + return get_bootsel_button(); +} + +__Bootsel BOOTSEL; diff --git a/cores/rp2040/Bootsel.h b/cores/rp2040/Bootsel.h new file mode 100644 index 0000000..b081ed6 --- /dev/null +++ b/cores/rp2040/Bootsel.h @@ -0,0 +1,29 @@ +/* + * Simple BOOTSEL reader object + * + * Copyright (c) 2021 Earle F. Philhower, III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +class __Bootsel { +public: + __Bootsel() { } + operator bool(); +}; + +extern __Bootsel BOOTSEL; diff --git a/libraries/rp2040/examples/Bootsel/Bootsel.ino b/libraries/rp2040/examples/Bootsel/Bootsel.ino new file mode 100644 index 0000000..773a1b4 --- /dev/null +++ b/libraries/rp2040/examples/Bootsel/Bootsel.ino @@ -0,0 +1,17 @@ +/* Simple sketch to do something on a BOOTSEL press */ +/* Releaed into the public domain */ + +void setup() { + Serial.begin(115200); + delay(5000); + Serial.println("I dare you to hit the BOOTSEL button..."); +} + +int c = 0; +void loop() { + if (BOOTSEL) { + Serial.printf("\a\aYou pressed BOOTSEL %d times!\n", ++c); + // Wait for BOOTSEL to be released + while (BOOTSEL) { delay(1); } + } +} diff --git a/libraries/rp2040/keywords.txt b/libraries/rp2040/keywords.txt new file mode 100644 index 0000000..2a5ca1f --- /dev/null +++ b/libraries/rp2040/keywords.txt @@ -0,0 +1 @@ +BOOTSEL KEYWORD1