Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
georgerennie committed Jan 23, 2021
0 parents commit b00fd5e
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 0 deletions.
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
add_library(bootsel_reset INTERFACE)

if (PICO_ON_DEVICE)
target_sources(bootsel_reset INTERFACE
${CMAKE_CURRENT_LIST_DIR}/bootsel_reset.c
)

target_link_libraries(bootsel_reset INTERFACE
pico_bootrom
pico_stdlib
)
endif()
80 changes: 80 additions & 0 deletions bootsel_reset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#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"
#include "pico/bootrom.h"

// Allow user override of the LED mask and check time (in ms)
#ifndef USB_BOOT_LED_ACTIVITY_MASK
#define USB_BOOT_LED_ACTIVITY_MASK 0
#endif
#ifndef BOOTSEL_RESET_PERIOD_MS
#define BOOTSEL_RESET_PERIOD_MS 100
#endif

// This function taken from pico-examples/src/picoboard/button/button.c
// Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
// SPDX-License-Identifier: BSD-3-Clause
//
// 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 < 500; ++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;
}

static bool repeating_timer_callback(struct repeating_timer *t) {
if (get_bootsel_button()) {
reset_usb_boot(USB_BOOT_LED_ACTIVITY_MASK, 0);
}
return true;
}

static struct repeating_timer timer;
static void __attribute__((constructor)) bootsel_reset() {
add_repeating_timer_ms(
BOOTSEL_RESET_PERIOD_MS,
repeating_timer_callback,
NULL,
&timer
);
}

1 change: 1 addition & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
18 changes: 18 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.12)

include(pico_sdk_import.cmake)
project(examples)
pico_sdk_init()

add_subdirectory(../ ${CMAKE_CURRENT_BINARY_DIR}/bootsel_reset)

add_executable(blinky_bootsel_reset
blinky_bootsel_reset.c
)

target_link_libraries(blinky_bootsel_reset
pico_stdlib
bootsel_reset
)

pico_add_extra_outputs(blinky_bootsel_reset)
17 changes: 17 additions & 0 deletions examples/blinky_bootsel_reset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "pico/stdlib.h"

// This just blinks the LED, however if bootsel_reset is linked with it,
// the bootsel button is automatically checked, and if pressed, the pico
// resets to boot mode
int main() {
const uint LED_PIN = 25;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);

while (true) {
gpio_put(LED_PIN, 1);
sleep_ms(250);
gpio_put(LED_PIN, 0);
sleep_ms(250);
}
}
62 changes: 62 additions & 0 deletions examples/pico_sdk_import.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake

# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()

if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()

if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()

if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()

set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the PICO SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")

if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
if (NOT pico_sdk)
message("Downloading PICO SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"PICO SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()

get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()

set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the PICO SDK")
endif ()

set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the PICO SDK" FORCE)

include(${PICO_SDK_INIT_CMAKE_FILE})

0 comments on commit b00fd5e

Please sign in to comment.