|
57 | 57 | #include "RP2350.h" // CMSIS
|
58 | 58 | #endif
|
59 | 59 |
|
| 60 | +#if CIRCUITPY_BOOT_BUTTON_NO_GPIO |
| 61 | +#include "hardware/gpio.h" |
| 62 | +#include "hardware/sync.h" |
| 63 | +#include "hardware/structs/ioqspi.h" |
| 64 | +#include "hardware/structs/sio.h" |
| 65 | +#endif |
| 66 | + |
60 | 67 | #include "supervisor/shared/serial.h"
|
61 | 68 |
|
62 | 69 | #include "tusb.h"
|
@@ -592,3 +599,53 @@ void port_boot_info(void) {
|
592 | 599 | mp_printf(&mp_plat_print, "\n");
|
593 | 600 | #endif
|
594 | 601 | }
|
| 602 | + |
| 603 | +#if CIRCUITPY_BOOT_BUTTON_NO_GPIO |
| 604 | +bool __no_inline_not_in_flash_func(port_boot_button_pressed)(void) { |
| 605 | + // Sense the state of the boot button. Because this function |
| 606 | + // disables flash, it cannot be safely called once the second |
| 607 | + // core has been started. When the BOOTSEL button is sensed as |
| 608 | + // pressed, return is delayed until the button is released and |
| 609 | + // a delay has passed in order to debounce the button. |
| 610 | + const uint32_t CS_PIN_INDEX = 1; |
| 611 | + #if defined(PICO_RP2040) |
| 612 | + const uint32_t CS_BIT = 1u << 1; |
| 613 | + #else |
| 614 | + const uint32_t CS_BIT = SIO_GPIO_HI_IN_QSPI_CSN_BITS; |
| 615 | + #endif |
| 616 | + uint32_t int_state = save_and_disable_interrupts(); |
| 617 | + // Wait for any outstanding XIP activity to finish. Flash |
| 618 | + // must be quiescent before disabling the chip select. Since |
| 619 | + // there's no XIP busy indication we can test, we delay a |
| 620 | + // generous 5 ms to allow any XIP activity to finish. |
| 621 | + busy_wait_us(5000); |
| 622 | + // Float the flash chip select pin. The line will HI-Z due to |
| 623 | + // the external 10K pull-up resistor. |
| 624 | + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, |
| 625 | + GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, |
| 626 | + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); |
| 627 | + // Delay 100 us to allow the CS line to stabilize. If BOOTSEL is |
| 628 | + // pressed, the line will be pulled low by the button and its |
| 629 | + // 1K external resistor to ground. |
| 630 | + busy_wait_us(100); |
| 631 | + bool button_pressed = !(sio_hw->gpio_hi_in & CS_BIT); |
| 632 | + // Wait for the button to be released. |
| 633 | + if (button_pressed) { |
| 634 | + while (!(sio_hw->gpio_hi_in & CS_BIT)) { |
| 635 | + tight_loop_contents(); |
| 636 | + } |
| 637 | + // Wait for 50 ms to debounce the button. |
| 638 | + busy_wait_us(50000); |
| 639 | + } |
| 640 | + // Restore the flash chip select pin to its original state. |
| 641 | + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, |
| 642 | + GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, |
| 643 | + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); |
| 644 | + // Delay 5 ms to allow the flash chip to re-enable and for the |
| 645 | + // flash CS pin to stabilize. |
| 646 | + busy_wait_us(5000); |
| 647 | + // Restore the interrupt state. |
| 648 | + restore_interrupts(int_state); |
| 649 | + return button_pressed; |
| 650 | +} |
| 651 | +#endif |
0 commit comments