From 7f2f186bcc9a7723312bf9a1cce3303389a80e5b Mon Sep 17 00:00:00 2001 From: Graham Sanderson Date: Thu, 1 Apr 2021 16:42:53 -0500 Subject: [PATCH] build: allow board config header to specify bootstage 2 without using custom per board cmake (#293) * build: allow compile time - and hence via board config header - choice of boot stage2 via a default compile_time_choice.S boot stage 2 which conditionally includes others adafruit_rp2040_feather: fix flash size/clkdiv * fixup GENERIC_03H #define names --- .../include/boards/adafruit_feather_rp2040.h | 8 +++- .../boards/adafruit_itsybitsy_rp2040.h | 3 ++ .../include/boards/adafruit_qtpy_rp2040.h | 3 ++ src/boards/include/boards/pico.h | 2 + .../include/boards/pimoroni_keybow2040.h | 2 + .../include/boards/pimoroni_picosystem.h | 2 + src/boards/include/boards/pimoroni_tiny2040.h | 2 + src/boards/include/boards/sparkfun_micromod.h | 2 + src/boards/include/boards/sparkfun_promicro.h | 2 + .../include/boards/sparkfun_thingplus.h | 3 ++ src/rp2_common/boot_stage2/CMakeLists.txt | 42 ++++++++++++++----- .../boot_stage2/compile_time_choice.S | 29 +++++++++++++ .../boot_stage2/include/boot_stage2/config.h | 38 +++++++++++++++++ .../pico_standard_link/CMakeLists.txt | 2 +- .../pico_standard_link/binary_info.c | 7 ++-- 15 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 src/rp2_common/boot_stage2/compile_time_choice.S create mode 100644 src/rp2_common/boot_stage2/include/boot_stage2/config.h diff --git a/src/boards/include/boards/adafruit_feather_rp2040.h b/src/boards/include/boards/adafruit_feather_rp2040.h index 631c52d..a27f9a3 100644 --- a/src/boards/include/boards/adafruit_feather_rp2040.h +++ b/src/boards/include/boards/adafruit_feather_rp2040.h @@ -68,12 +68,16 @@ #endif //------------- FLASH -------------// + +// Use slower generic flash access +#define PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1 + #ifndef PICO_FLASH_SPI_CLKDIV -#define PICO_FLASH_SPI_CLKDIV 2 +#define PICO_FLASH_SPI_CLKDIV 4 #endif #ifndef PICO_FLASH_SIZE_BYTES -#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024) +#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024) #endif // All boards have B1 RP2040 diff --git a/src/boards/include/boards/adafruit_itsybitsy_rp2040.h b/src/boards/include/boards/adafruit_itsybitsy_rp2040.h index 55015c6..dd29d64 100644 --- a/src/boards/include/boards/adafruit_itsybitsy_rp2040.h +++ b/src/boards/include/boards/adafruit_itsybitsy_rp2040.h @@ -72,6 +72,9 @@ #endif //------------- FLASH -------------// + +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/adafruit_qtpy_rp2040.h b/src/boards/include/boards/adafruit_qtpy_rp2040.h index cfe68ab..570fb3d 100644 --- a/src/boards/include/boards/adafruit_qtpy_rp2040.h +++ b/src/boards/include/boards/adafruit_qtpy_rp2040.h @@ -71,6 +71,9 @@ #endif //------------- FLASH -------------// + +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/pico.h b/src/boards/include/boards/pico.h index cf45311..d681dc4 100644 --- a/src/boards/include/boards/pico.h +++ b/src/boards/include/boards/pico.h @@ -61,6 +61,8 @@ // --- FLASH --- +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/pimoroni_keybow2040.h b/src/boards/include/boards/pimoroni_keybow2040.h index eeab409..011212e 100644 --- a/src/boards/include/boards/pimoroni_keybow2040.h +++ b/src/boards/include/boards/pimoroni_keybow2040.h @@ -111,6 +111,8 @@ #define KEYBOW2040_NUM_SWITCHES_PINS 16 #endif +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/pimoroni_picosystem.h b/src/boards/include/boards/pimoroni_picosystem.h index c249469..72d4789 100644 --- a/src/boards/include/boards/pimoroni_picosystem.h +++ b/src/boards/include/boards/pimoroni_picosystem.h @@ -124,6 +124,8 @@ #define PICO_DEFAULT_LED_PIN_INVERTED 1 #endif +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/pimoroni_tiny2040.h b/src/boards/include/boards/pimoroni_tiny2040.h index 29194e4..6cf86b4 100644 --- a/src/boards/include/boards/pimoroni_tiny2040.h +++ b/src/boards/include/boards/pimoroni_tiny2040.h @@ -76,6 +76,8 @@ #define PICO_DEFAULT_LED_PIN_INVERTED 1 #endif +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/sparkfun_micromod.h b/src/boards/include/boards/sparkfun_micromod.h index 973a9e1..d082131 100644 --- a/src/boards/include/boards/sparkfun_micromod.h +++ b/src/boards/include/boards/sparkfun_micromod.h @@ -47,6 +47,8 @@ #endif // spi flash +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/sparkfun_promicro.h b/src/boards/include/boards/sparkfun_promicro.h index d63ab41..b042d6e 100644 --- a/src/boards/include/boards/sparkfun_promicro.h +++ b/src/boards/include/boards/sparkfun_promicro.h @@ -46,6 +46,8 @@ #define PICO_DEFAULT_I2C_SCL_PIN 17 #endif +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/boards/include/boards/sparkfun_thingplus.h b/src/boards/include/boards/sparkfun_thingplus.h index eac3aa4..d2a0d73 100644 --- a/src/boards/include/boards/sparkfun_thingplus.h +++ b/src/boards/include/boards/sparkfun_thingplus.h @@ -43,6 +43,9 @@ #endif // spi flash + +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + #ifndef PICO_FLASH_SPI_CLKDIV #define PICO_FLASH_SPI_CLKDIV 2 #endif diff --git a/src/rp2_common/boot_stage2/CMakeLists.txt b/src/rp2_common/boot_stage2/CMakeLists.txt index 4eda064..99adf40 100644 --- a/src/rp2_common/boot_stage2/CMakeLists.txt +++ b/src/rp2_common/boot_stage2/CMakeLists.txt @@ -1,17 +1,34 @@ -# PICO_CMAKE_CONFIG: PICO_DEFAULT_BOOT_STAGE2_FILE, Default stage2 file to use unless overridden by pico_set_boot_stage2 on the TARGET, type=bool, default=.../boot2_w25q080.S, group=build -if (NOT PICO_DEFAULT_BOOT_STAGE2_FILE) - set(PICO_DEFAULT_BOOT_STAGE2_FILE "${CMAKE_CURRENT_LIST_DIR}/boot2_w25q080.S") +# PICO_CMAKE_CONFIG: PICO_DEFAULT_BOOT_STAGE2_FILE, Default stage2 file to use unless overridden by pico_set_boot_stage2 on the TARGET; this setting is useful when explicitly setting the default build from a per board CMake file, group=build +# PICO_CMAKE_CONFIG: PICO_DEFAULT_BOOT_STAGE2, Simpler alternative to specifying PICO_DEFAULT_BOOT_STAGE2_FILE where the file is src/boards/{PICO_DEFAULT_BOOT_STAGE2_FILE}.S, default=compile_time_choice, group=build +if (DEFINED ENV{PICO_DEFAULT_BOOT_STAGE2_FILE}) + set(PICO_DEFAULT_BOOT_STAGE2_FILE $ENV{PICO_DEFAULT_BOOT_STAGE2_FILE}) + message("Using PICO_DEFAULT_BOOT_STAGE2_FILE from environment ('${PICO_DEFAULT_BOOT_STAGE2_FILE}')") endif() - set(PICO_DEFAULT_BOOT_STAGE2_FILE "${PICO_DEFAULT_BOOT_STAGE2_FILE}" CACHE STRING "boot_stage2 source file" FORCE) +set(PICO_BOOT_STAGE2_COMPILE_TIME_CHOICE_NAME compile_time_choice) # local var +if (NOT PICO_DEFAULT_BOOT_STAGE2_FILE) + if (DEFINED ENV{PICO_DEFAULT_BOOT_STAGE2}) + set(PICO_DEFAULT_BOOT_STAGE2 $ENV{PICO_DEFAULT_BOOT_STAGE2}) + message("Using PICO_DEFAULT_BOOT_STAGE2 from environment ('${PICO_DEFAULT_BOOT_STAGE2}')") + endif() + if (NOT DEFINED PICO_DEFAULT_BOOT_STAGE2) + set(PICO_DEFAULT_BOOT_STAGE2 ${PICO_BOOT_STAGE2_COMPILE_TIME_CHOICE_NAME}) + endif() + set(PICO_DEFAULT_BOOT_STAGE2 "${PICO_DEFAULT_BOOT_STAGE2}" CACHE STRING "boot_stage2 short name" FORCE) + set(PICO_DEFAULT_BOOT_STAGE2_FILE "${CMAKE_CURRENT_LIST_DIR}/${PICO_DEFAULT_BOOT_STAGE2}.S") +endif() + if (NOT EXISTS ${PICO_DEFAULT_BOOT_STAGE2_FILE}) - message(FATAL_ERROR "Specified boot_stage2 source '${PICO_BOOT_STAGE2_FILE}' does not exist.") + message(FATAL_ERROR "Specified boot_stage2 source '${PICO_DEFAULT_BOOT_STAGE2_FILE}' does not exist.") endif() # needed by function below set(PICO_BOOT_STAGE2_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "") +add_library(boot_stage2_headers INTERFACE) +target_include_directories(boot_stage2_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) + # by convention the first source file name without extension is used for the binary info name function(pico_define_boot_stage2 NAME SOURCES) add_executable(${NAME} @@ -29,7 +46,7 @@ function(pico_define_boot_stage2 NAME SOURCES) # boot2_helpers include dir target_include_directories(${NAME} PRIVATE ${PICO_BOOT_STAGE2_DIR}/asminclude) - target_link_libraries(${NAME} hardware_regs) + target_link_libraries(${NAME} hardware_regs boot_stage2_headers) target_link_options(${NAME} PRIVATE "LINKER:--script=${PICO_BOOT_STAGE2_DIR}/boot_stage2.ld") set_target_properties(${NAME} PROPERTIES LINK_DEPENDS ${PICO_BOOT_STAGE2_DIR}/boot_stage2.ld) @@ -49,17 +66,22 @@ function(pico_define_boot_stage2 NAME SOURCES) COMMAND ${Python3_EXECUTABLE} ${PICO_BOOT_STAGE2_DIR}/pad_checksum -s 0xffffffff ${ORIGINAL_BIN} ${PADDED_CHECKSUMMED_ASM} ) - add_library(${NAME}_library INTERFACE) add_dependencies(${NAME}_library ${NAME}_padded_checksummed_asm) # not strictly (or indeed actually) a link library, but this avoids dependency cycle target_link_libraries(${NAME}_library INTERFACE ${PADDED_CHECKSUMMED_ASM}) + target_link_libraries(${NAME}_library INTERFACE boot_stage2_headers) list(GET SOURCES 0 FIRST_SOURCE) - get_filename_component(BOOT2_BI_NAME ${FIRST_SOURCE} NAME_WE) + get_filename_component(BOOT_STAGE2_BI_NAME ${FIRST_SOURCE} NAME_WE) - target_compile_definitions(${NAME}_library INTERFACE - -DPICO_BOOT2_NAME="${BOOT2_BI_NAME}") + # we only set the PICO_BUILD_STAGE2_NAME if it isn't 'compile_time_choice' + if (NOT BOOT_STAGE2_BI_NAME STREQUAL PICO_BOOT_STAGE2_COMPILE_TIME_CHOICE_NAME) + target_compile_definitions(${NAME} INTERFACE + -DPICO_BUILD_BOOT_STAGE2_NAME="${BOOT_STAGE2_BI_NAME}") + target_compile_definitions(${NAME}_library INTERFACE + -DPICO_BUILD_BOOT_STAGE2_NAME="${BOOT_STAGE2_BI_NAME}") + endif() endfunction() macro(pico_set_boot_stage2 TARGET NAME) diff --git a/src/rp2_common/boot_stage2/compile_time_choice.S b/src/rp2_common/boot_stage2/compile_time_choice.S new file mode 100644 index 0000000..cacb9aa --- /dev/null +++ b/src/rp2_common/boot_stage2/compile_time_choice.S @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------- +// Second stage boot code +// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. +// SPDX-License-Identifier: BSD-3-Clause +// ---------------------------------------------------------------------------- +// +// This implementation uses the PICO_BOOT_STAGE2_CHOOSE_ preprocessor defines to pick +// amongst a menu of known boot stage 2 implementations, allowing the board +// configuration header to be able to specify the boot stage 2 + +#include "boot_stage2/config.h" + +#ifdef PICO_BUILD_BOOT_STAGE2_NAME + // boot stage2 is configured by cmake, so use the name specified there + #error PICO_BUILD_BOOT_STAGE2_NAME should not be defined for compile_time_choice builds +#else + // boot stage2 is selected by board configu header, so we have to do some work + #if PICO_BOOT_STAGE2_CHOOSE_IS25LP080 + #include "boot2_is25lp080.S" + #elif PICO_BOOT_STAGE2_CHOOSE_W25Q080 + #include "boot2_w28q080.S" + #elif PICO_BOOT_STAGE2_CHOOSE_W25X10CL + #include "boot2_w25x10cl.S" + #elif PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H + #include "boot2_generic_03h.S" + #else + #error unknown boot stage2 choice + #endif +#endif diff --git a/src/rp2_common/boot_stage2/include/boot_stage2/config.h b/src/rp2_common/boot_stage2/include/boot_stage2/config.h new file mode 100644 index 0000000..f6fdb9f --- /dev/null +++ b/src/rp2_common/boot_stage2/include/boot_stage2/config.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BOOT_STAGE2_CONFIG_H_ +#define _BOOT_STAGE2_CONFIG_H_ + +// NOTE THIS HEADER IS INCLUDED FROM ASSEMBLY + +// PICO_CONFIG: PICO_BUILD_BOOT_STAGE2_NAME, The name of the boot stage 2 if selected by the build, group=boot_stage2 +// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_IS25LP080, Select boot2_is25lp080 as the boot stage 2 when no boot stage2 selection is made by the CMake build, type=bool, default=false, group=boot_stage2 +// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_W25Q080, Select boot2_w28q080 as the boot stage 2 when no boot stage2 selection is made by the CMake build, type=bool, default=false, group=boot_stage2 +// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_W25X10CL, Select boot2_is25lp080 as the boot stage 2 when no boot stage2 selection is made by the CMake build, type=bool, default=false, group=boot_stage2 +// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H, Select boot2_generic_03h as the boot stage 2 when no boot stage2 selection is made by the CMake build, type=bool, default=true, group=boot_stage2 + +#ifdef PICO_BUILD_BOOT_STAGE2_NAME + // boot stage2 is configured by cmake, so use the name specified there + #define PICO_BOOT_STAGE2_NAME PICO_BUILD_BOOT_STAGE2_NAME +#else + // boot stage2 is selected by board configu header, so we have to do some work + // NOTE: this switch is mirrored in compile_time_choice.S + #if PICO_BOOT_STAGE2_CHOOSE_IS25LP080 + #define PICO_BOOT_STAGE2_NAME "boot2_is25lp080" + #elif PICO_BOOT_STAGE2_CHOOSE_W25Q080 + #define PICO_BOOT_STAGE2_NAME "boot2_w28q080" + #elif PICO_BOOT_STAGE2_CHOOSE_W25X10CL + #define PICO_BOOT_STAGE2_NAME "boot2_w25x10cl" + #elif PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H || !defined(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H) + #undef PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H + #define PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1 + #define PICO_BOOT_STAGE2_NAME "boot2_generic_03h" + #else + #error no bootstage2 is defined by PICO_BOOT_STAGE2_CHOOSE_ macro + #endif +#endif +#endif \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 489594c..c58096d 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -14,7 +14,7 @@ if (NOT TARGET pico_standard_link) target_link_options(pico_standard_link INTERFACE "LINKER:-nostdlib") endif () - target_link_libraries(pico_standard_link INTERFACE hardware_regs pico_bootrom pico_binary_info pico_cxx_options) + target_link_libraries(pico_standard_link INTERFACE hardware_regs boot_stage2_headers pico_bootrom pico_binary_info pico_cxx_options) function(pico_add_link_depend TARGET dependency) get_target_property(target_type ${TARGET} TYPE) diff --git a/src/rp2_common/pico_standard_link/binary_info.c b/src/rp2_common/pico_standard_link/binary_info.c index ba5dad8..bde2027 100644 --- a/src/rp2_common/pico_standard_link/binary_info.c +++ b/src/rp2_common/pico_standard_link/binary_info.c @@ -6,6 +6,7 @@ #if !PICO_NO_BINARY_INFO && !PICO_NO_PROGRAM_INFO #include "pico/binary_info.h" +#include "boot_stage2/config.h" // Note we put at most 4 pieces of binary info in the reset section because that's how much spare space we had // (picked the most common ones)... if there is a link failure because of .reset section overflow then move @@ -66,9 +67,9 @@ bi_decl(bi_program_url(PICO_PROGRAM_URL)) #endif #endif -#if !PICO_NO_BI_BOOT2_NAME -#ifdef PICO_BOOT2_NAME -bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BOOT2_NAME, PICO_BOOT2_NAME)) +#if !PICO_NO_BI_BOOT_STAGE2_NAME +#ifdef PICO_BOOT_STAGE2_NAME +bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BOOT2_NAME, PICO_BOOT_STAGE2_NAME)) #endif #endif