67 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			2.3 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 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.
 | |
| 
 | |
| 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() {
 | |
| #ifndef PICO_DEFAULT_LED_PIN
 | |
| #warning picoboard/button example requires a board with a regular LED
 | |
| #else
 | |
|     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() ^ PICO_DEFAULT_LED_PIN_INVERTED);
 | |
|         sleep_ms(10);
 | |
|     }
 | |
| #endif
 | |
| }
 |