62 lines
2.2 KiB
C
62 lines
2.2 KiB
C
/**
|
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#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 Picoboard 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.
|
|
|
|
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;
|
|
}
|
|
|
|
int main() {
|
|
gpio_init(PICO_DEFAULT_LED_PIN);
|
|
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
|
while (true) {
|
|
gpio_put(PICO_DEFAULT_LED_PIN, get_bootsel_button());
|
|
sleep_ms(10);
|
|
}
|
|
} |