Merge pull request #299 from raspberrypi/back-merge-1.1.1
Back merge 1.1.1
This commit is contained in:
		@ -1,6 +1,5 @@
 | 
				
			|||||||
# PICO_CMAKE_CONFIG: PICO_TOOLCHAIN_PATH, Path to search for compiler, default=none (i.e. search system paths), group=build
 | 
					# PICO_CMAKE_CONFIG: PICO_TOOLCHAIN_PATH, Path to search for compiler, default=none (i.e. search system paths), group=build
 | 
				
			||||||
# Set your compiler path here if it's not in the PATH environment variable.
 | 
					set(PICO_TOOLCHAIN_PATH "${PICO_TOOLCHAIN_PATH}" CACHE INTERNAL "")
 | 
				
			||||||
set(PICO_TOOLCHAIN_PATH "" CACHE INTERNAL "")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Set a default build type if none was specified
 | 
					# Set a default build type if none was specified
 | 
				
			||||||
set(default_build_type "Release")
 | 
					set(default_build_type "Release")
 | 
				
			||||||
 | 
				
			|||||||
@ -52,8 +52,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
 | 
				
			|||||||
option(PICO_DEOPTIMIZED_DEBUG "Build debug builds with -O0" 0)
 | 
					option(PICO_DEOPTIMIZED_DEBUG "Build debug builds with -O0" 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# todo move to platform/Generix-xxx
 | 
					# todo move to platform/Generix-xxx
 | 
				
			||||||
set(ARM_GCC_COMMON_FLAGS " -march=armv6-m -mcpu=cortex-m0plus -mthumb")
 | 
					
 | 
				
			||||||
#set(ARM_GCC_COMMON_FLAGS " -mcpu=cortex-m0plus -mthumb")
 | 
					# on ARM -mcpu should not be mixed with -march
 | 
				
			||||||
 | 
					set(ARM_GCC_COMMON_FLAGS " -mcpu=cortex-m0plus -mthumb")
 | 
				
			||||||
foreach(LANG IN ITEMS C CXX ASM)
 | 
					foreach(LANG IN ITEMS C CXX ASM)
 | 
				
			||||||
    set(CMAKE_${LANG}_FLAGS_INIT "${ARM_GCC_COMMON_FLAGS}")
 | 
					    set(CMAKE_${LANG}_FLAGS_INIT "${ARM_GCC_COMMON_FLAGS}")
 | 
				
			||||||
    if (PICO_DEOPTIMIZED_DEBUG)
 | 
					    if (PICO_DEOPTIMIZED_DEBUG)
 | 
				
			||||||
 | 
				
			|||||||
@ -68,12 +68,16 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//------------- FLASH -------------//
 | 
					//------------- FLASH -------------//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Use slower generic flash access
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 4
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SIZE_BYTES
 | 
					#ifndef PICO_FLASH_SIZE_BYTES
 | 
				
			||||||
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
 | 
					#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// All boards have B1 RP2040
 | 
					// All boards have B1 RP2040
 | 
				
			||||||
 | 
				
			|||||||
@ -72,6 +72,9 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//------------- FLASH -------------//
 | 
					//------------- FLASH -------------//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -71,6 +71,9 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//------------- FLASH -------------//
 | 
					//------------- FLASH -------------//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// --- FLASH ---
 | 
					// --- FLASH ---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -107,10 +107,12 @@
 | 
				
			|||||||
#define KEYBOW2040_SW15_PIN 6
 | 
					#define KEYBOW2040_SW15_PIN 6
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef KEYBOW2040_NUM_SWITCHES
 | 
					#ifndef KEYBOW2040_NUM_SWITCHES_PINS
 | 
				
			||||||
#define KEYBOW2040_NUM_SWITCHES_PINS 16
 | 
					#define KEYBOW2040_NUM_SWITCHES_PINS 16
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -124,6 +124,8 @@
 | 
				
			|||||||
#define PICO_DEFAULT_LED_PIN_INVERTED 1
 | 
					#define PICO_DEFAULT_LED_PIN_INVERTED 1
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -76,6 +76,8 @@
 | 
				
			|||||||
#define PICO_DEFAULT_LED_PIN_INVERTED 1
 | 
					#define PICO_DEFAULT_LED_PIN_INVERTED 1
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_DEFAULT_UART
 | 
					#ifndef PICO_DEFAULT_UART
 | 
				
			||||||
#define PICO_DEFAULT_UART 0
 | 
					#define PICO_DEFAULT_UART 0
 | 
				
			||||||
#define
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_DEFAULT_UART_TX_PIN
 | 
					#ifndef PICO_DEFAULT_UART_TX_PIN
 | 
				
			||||||
#define PICO_DEFAULT_UART_TX_PIN 0
 | 
					#define PICO_DEFAULT_UART_TX_PIN 0
 | 
				
			||||||
@ -47,6 +47,8 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// spi flash
 | 
					// spi flash
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,8 @@
 | 
				
			|||||||
#define PICO_DEFAULT_I2C_SCL_PIN   17
 | 
					#define PICO_DEFAULT_I2C_SCL_PIN   17
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,9 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// spi flash
 | 
					// spi flash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PICO_FLASH_SPI_CLKDIV
 | 
					#ifndef PICO_FLASH_SPI_CLKDIV
 | 
				
			||||||
#define PICO_FLASH_SPI_CLKDIV 2
 | 
					#define PICO_FLASH_SPI_CLKDIV 2
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -26,8 +26,8 @@
 | 
				
			|||||||
#define VGABOARD_VGA_COLOR_PIN_BASE 0
 | 
					#define VGABOARD_VGA_COLOR_PIN_BASE 0
 | 
				
			||||||
#define VGABOARD_VGA_SYNC_PIN_BASE 16
 | 
					#define VGABOARD_VGA_SYNC_PIN_BASE 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Note DAT2/3 are shared with UART TX/RX (pull jumpers off header to access
 | 
					// Note DAT1/2 are shared with UART TX/RX (pull jumpers off header to access
 | 
				
			||||||
// UART pins and disconnect SD DAT2/3)
 | 
					// UART pins and disconnect SD DAT1/2)
 | 
				
			||||||
#define VGABOARD_SD_CLK_PIN 5
 | 
					#define VGABOARD_SD_CLK_PIN 5
 | 
				
			||||||
#define VGABOARD_SD_CMD_PIN 18
 | 
					#define VGABOARD_SD_CMD_PIN 18
 | 
				
			||||||
#define VGABOARD_SD_DAT0_PIN 19
 | 
					#define VGABOARD_SD_DAT0_PIN 19
 | 
				
			||||||
@ -57,10 +57,12 @@
 | 
				
			|||||||
#define PICO_SD_CMD_PIN VGABOARD_SD_CMD_PIN
 | 
					#define PICO_SD_CMD_PIN VGABOARD_SD_CMD_PIN
 | 
				
			||||||
#define PICO_SD_DAT0_PIN VGABOARD_SD_DAT0_PIN
 | 
					#define PICO_SD_DAT0_PIN VGABOARD_SD_DAT0_PIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 1 or 4
 | 
				
			||||||
#ifndef PICO_SD_DAT_PIN_COUNT
 | 
					#ifndef PICO_SD_DAT_PIN_COUNT
 | 
				
			||||||
#define PICO_SD_DAT_PIN_COUNT 4
 | 
					#define PICO_SD_DAT_PIN_COUNT 4
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 1 or -1
 | 
				
			||||||
#define PICO_SD_DAT_PIN_INCREMENT 1
 | 
					#define PICO_SD_DAT_PIN_INCREMENT 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PICO_AUDIO_I2S_DATA_PIN VGABOARD_I2S_DIN_PIN
 | 
					#define PICO_AUDIO_I2S_DATA_PIN VGABOARD_I2S_DIN_PIN
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ typedef unsigned int uint;
 | 
				
			|||||||
    \see update_us_since_boot()
 | 
					    \see update_us_since_boot()
 | 
				
			||||||
    \ingroup timestamp
 | 
					    \ingroup timestamp
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
#ifndef NDEBUG
 | 
					#ifdef NDEBUG
 | 
				
			||||||
typedef uint64_t absolute_time_t;
 | 
					typedef uint64_t absolute_time_t;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -40,7 +40,7 @@ typedef struct {
 | 
				
			|||||||
 * \ingroup timestamp
 | 
					 * \ingroup timestamp
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline uint64_t to_us_since_boot(absolute_time_t t) {
 | 
					static inline uint64_t to_us_since_boot(absolute_time_t t) {
 | 
				
			||||||
#ifndef NDEBUG
 | 
					#ifdef NDEBUG
 | 
				
			||||||
    return t;
 | 
					    return t;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    return t._private_us_since_boot;
 | 
					    return t._private_us_since_boot;
 | 
				
			||||||
@ -55,7 +55,7 @@ static inline uint64_t to_us_since_boot(absolute_time_t t) {
 | 
				
			|||||||
 * \ingroup timestamp
 | 
					 * \ingroup timestamp
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline void update_us_since_boot(absolute_time_t *t, uint64_t us_since_boot) {
 | 
					static inline void update_us_since_boot(absolute_time_t *t, uint64_t us_since_boot) {
 | 
				
			||||||
#ifndef NDEBUG
 | 
					#ifdef NDEBUG
 | 
				
			||||||
    *t = us_since_boot;
 | 
					    *t = us_since_boot;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    assert(us_since_boot <= INT64_MAX);
 | 
					    assert(us_since_boot <= INT64_MAX);
 | 
				
			||||||
@ -63,7 +63,7 @@ static inline void update_us_since_boot(absolute_time_t *t, uint64_t us_since_bo
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NDEBUG
 | 
					#ifdef NDEBUG
 | 
				
			||||||
#define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = value
 | 
					#define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = value
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = {value}
 | 
					#define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = {value}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,10 @@
 | 
				
			|||||||
 * \ingroup pico_util
 | 
					 * \ingroup pico_util
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    spin_lock_t *lock;
 | 
					    spin_lock_t *lock;
 | 
				
			||||||
    uint8_t *data;
 | 
					    uint8_t *data;
 | 
				
			||||||
@ -69,7 +73,7 @@ void queue_free(queue_t *q);
 | 
				
			|||||||
static inline uint queue_get_level_unsafe(queue_t *q) {
 | 
					static inline uint queue_get_level_unsafe(queue_t *q) {
 | 
				
			||||||
    int32_t rc = (int32_t)q->wptr - (int32_t)q->rptr;
 | 
					    int32_t rc = (int32_t)q->wptr - (int32_t)q->rptr;
 | 
				
			||||||
    if (rc < 0) {
 | 
					    if (rc < 0) {
 | 
				
			||||||
        rc += + q->element_count + 1;
 | 
					        rc += q->element_count + 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return (uint)rc;
 | 
					    return (uint)rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -181,4 +185,7 @@ void queue_remove_blocking(queue_t *q, void *data);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void queue_peek_blocking(queue_t *q, void *data);
 | 
					void queue_peek_blocking(queue_t *q, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -14,12 +14,19 @@ pico_add_subdirectory(pico_stdlib)
 | 
				
			|||||||
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
 | 
					pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro(pico_set_float_implementation TARGET IMPL)
 | 
					macro(pico_set_float_implementation TARGET IMPL)
 | 
				
			||||||
 | 
					    # ignore
 | 
				
			||||||
endmacro()
 | 
					endmacro()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro(pico_set_double_implementation TARGET IMPL)
 | 
					macro(pico_set_double_implementation TARGET IMPL)
 | 
				
			||||||
 | 
					    # ignore
 | 
				
			||||||
 | 
					endmacro()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macro(pico_set_binary_type TARGET IMPL)
 | 
				
			||||||
 | 
					    # ignore
 | 
				
			||||||
endmacro()
 | 
					endmacro()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro(pico_set_boot_stage2 TARGET IMPL)
 | 
					macro(pico_set_boot_stage2 TARGET IMPL)
 | 
				
			||||||
 | 
					    # ignore
 | 
				
			||||||
endmacro()
 | 
					endmacro()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(PICO_HOST_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
 | 
					set(PICO_HOST_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,24 @@
 | 
				
			|||||||
# 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
 | 
					# 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
 | 
				
			||||||
if (NOT PICO_DEFAULT_BOOT_STAGE2_FILE)
 | 
					# 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
 | 
				
			||||||
    set(PICO_DEFAULT_BOOT_STAGE2_FILE "${CMAKE_CURRENT_LIST_DIR}/boot2_w25q080.S")
 | 
					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()
 | 
					endif()
 | 
				
			||||||
 | 
					 | 
				
			||||||
set(PICO_DEFAULT_BOOT_STAGE2_FILE "${PICO_DEFAULT_BOOT_STAGE2_FILE}" CACHE STRING "boot_stage2 source file" FORCE)
 | 
					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})
 | 
					if (NOT EXISTS ${PICO_DEFAULT_BOOT_STAGE2_FILE})
 | 
				
			||||||
    message(FATAL_ERROR "Specified boot_stage2 source '${PICO_DEFAULT_BOOT_STAGE2_FILE}' does not exist.")
 | 
					    message(FATAL_ERROR "Specified boot_stage2 source '${PICO_DEFAULT_BOOT_STAGE2_FILE}' does not exist.")
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
@ -12,6 +26,9 @@ endif()
 | 
				
			|||||||
# needed by function below
 | 
					# needed by function below
 | 
				
			||||||
set(PICO_BOOT_STAGE2_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
 | 
					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
 | 
					# by convention the first source file name without extension is used for the binary info name
 | 
				
			||||||
function(pico_define_boot_stage2 NAME SOURCES)
 | 
					function(pico_define_boot_stage2 NAME SOURCES)
 | 
				
			||||||
    add_executable(${NAME}
 | 
					    add_executable(${NAME}
 | 
				
			||||||
@ -29,7 +46,7 @@ function(pico_define_boot_stage2 NAME SOURCES)
 | 
				
			|||||||
    # boot2_helpers include dir
 | 
					    # boot2_helpers include dir
 | 
				
			||||||
    target_include_directories(${NAME} PRIVATE ${PICO_BOOT_STAGE2_DIR}/asminclude)
 | 
					    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")
 | 
					    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)
 | 
					    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}
 | 
					            COMMAND ${Python3_EXECUTABLE} ${PICO_BOOT_STAGE2_DIR}/pad_checksum -s 0xffffffff ${ORIGINAL_BIN} ${PADDED_CHECKSUMMED_ASM}
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    add_library(${NAME}_library INTERFACE)
 | 
					    add_library(${NAME}_library INTERFACE)
 | 
				
			||||||
    add_dependencies(${NAME}_library ${NAME}_padded_checksummed_asm)
 | 
					    add_dependencies(${NAME}_library ${NAME}_padded_checksummed_asm)
 | 
				
			||||||
    # not strictly (or indeed actually) a link library, but this avoids dependency cycle
 | 
					    # 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 ${PADDED_CHECKSUMMED_ASM})
 | 
				
			||||||
 | 
					    target_link_libraries(${NAME}_library INTERFACE boot_stage2_headers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    list(GET SOURCES 0 FIRST_SOURCE)
 | 
					    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
 | 
					    # we only set the PICO_BUILD_STAGE2_NAME if it isn't 'compile_time_choice'
 | 
				
			||||||
            -DPICO_BOOT2_NAME="${BOOT2_BI_NAME}")
 | 
					    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()
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro(pico_set_boot_stage2 TARGET NAME)
 | 
					macro(pico_set_boot_stage2 TARGET NAME)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										29
									
								
								src/rp2_common/boot_stage2/compile_time_choice.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/rp2_common/boot_stage2/compile_time_choice.S
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/rp2_common/boot_stage2/include/boot_stage2/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/rp2_common/boot_stage2/include/boot_stage2/config.h
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
				
			||||||
@ -322,7 +322,7 @@ void clock_gpio_init(uint gpio, uint src, uint div) {
 | 
				
			|||||||
    if      (gpio == 21) gpclk = clk_gpout0;
 | 
					    if      (gpio == 21) gpclk = clk_gpout0;
 | 
				
			||||||
    else if (gpio == 23) gpclk = clk_gpout1;
 | 
					    else if (gpio == 23) gpclk = clk_gpout1;
 | 
				
			||||||
    else if (gpio == 24) gpclk = clk_gpout2;
 | 
					    else if (gpio == 24) gpclk = clk_gpout2;
 | 
				
			||||||
    else if (gpio == 26) gpclk = clk_gpout3;
 | 
					    else if (gpio == 25) gpclk = clk_gpout3;
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        invalid_params_if(CLOCKS, true);
 | 
					        invalid_params_if(CLOCKS, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -170,7 +170,7 @@ void clocks_enable_resus(resus_callback_t resus_callback);
 | 
				
			|||||||
/*! \brief Output an optionally divided clock to the specified gpio pin.
 | 
					/*! \brief Output an optionally divided clock to the specified gpio pin.
 | 
				
			||||||
 *  \ingroup hardware_clocks
 | 
					 *  \ingroup hardware_clocks
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 26. These GPIOs are connected to the GPOUT0-3 clock generators.
 | 
					 * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
 | 
				
			||||||
 * \param src  The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
 | 
					 * \param src  The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
 | 
				
			||||||
 * \param div  The amount to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock.
 | 
					 * \param div  The amount to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -279,7 +279,7 @@ static inline size_t i2c_get_read_available(i2c_inst_t *i2c) {
 | 
				
			|||||||
 * \param src Data to send
 | 
					 * \param src Data to send
 | 
				
			||||||
 * \param len Number of bytes to send
 | 
					 * \param len Number of bytes to send
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Writes directly to the to I2C TX FIFO which us mainly useful for
 | 
					 * Writes directly to the I2C TX FIFO which is mainly useful for
 | 
				
			||||||
 * slave-mode operation.
 | 
					 * slave-mode operation.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline void i2c_write_raw_blocking(i2c_inst_t *i2c, const uint8_t *src, size_t len) {
 | 
					static inline void i2c_write_raw_blocking(i2c_inst_t *i2c, const uint8_t *src, size_t len) {
 | 
				
			||||||
@ -291,14 +291,14 @@ static inline void i2c_write_raw_blocking(i2c_inst_t *i2c, const uint8_t *src, s
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! \brief Write direct to TX FIFO
 | 
					/*! \brief Read direct from RX FIFO
 | 
				
			||||||
 *  \ingroup hardware_i2c
 | 
					 *  \ingroup hardware_i2c
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param i2c Either \ref i2c0 or \ref i2c1
 | 
					 * \param i2c Either \ref i2c0 or \ref i2c1
 | 
				
			||||||
 * \param dst Buffer to accept data
 | 
					 * \param dst Buffer to accept data
 | 
				
			||||||
 * \param len Number of bytes to send
 | 
					 * \param len Number of bytes to read
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Reads directly from the I2C RX FIFO which us mainly useful for
 | 
					 * Reads directly from the I2C RX FIFO which is mainly useful for
 | 
				
			||||||
 * slave-mode operation.
 | 
					 * slave-mode operation.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline void i2c_read_raw_blocking(i2c_inst_t *i2c, uint8_t *dst, size_t len) {
 | 
					static inline void i2c_read_raw_blocking(i2c_inst_t *i2c, uint8_t *dst, size_t len) {
 | 
				
			||||||
 | 
				
			|||||||
@ -196,29 +196,6 @@ static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool
 | 
				
			|||||||
                  (bool_to_bit(pindirs) << PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB);
 | 
					                  (bool_to_bit(pindirs) << PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! \brief Set the state machine clock divider (from a floating point value) in a state machine configuration
 | 
					 | 
				
			||||||
 *  \ingroup sm_config
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The clock divider slows the state machine's execution by masking the
 | 
					 | 
				
			||||||
 * system clock on some cycles, in a repeating pattern, so that the state
 | 
					 | 
				
			||||||
 * machine does not advance. Effectively this produces a slower clock for the
 | 
					 | 
				
			||||||
 * state machine to run from, which can be used to generate e.g. a particular
 | 
					 | 
				
			||||||
 * UART baud rate. See the datasheet for further detail.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * \param c Pointer to the configuration structure to modify
 | 
					 | 
				
			||||||
 * \param div The fractional divisor to be set. 1 for full speed. An integer clock divisor of n
 | 
					 | 
				
			||||||
 *  will cause the state machine to run 1 cycle in every n.
 | 
					 | 
				
			||||||
 *  Note that for small n, the jitter introduced by a fractional divider (e.g. 2.5) may be unacceptable
 | 
					 | 
				
			||||||
 *  although it will depend on the use case.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline void sm_config_set_clkdiv(pio_sm_config *c, float div) {
 | 
					 | 
				
			||||||
    uint div_int = (uint)div;
 | 
					 | 
				
			||||||
    uint div_frac = (uint)((div - (float)div_int) * (1u << 8u));
 | 
					 | 
				
			||||||
    c->clkdiv =
 | 
					 | 
				
			||||||
            (div_frac << PIO_SM0_CLKDIV_FRAC_LSB) |
 | 
					 | 
				
			||||||
            (div_int << PIO_SM0_CLKDIV_INT_LSB);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*! \brief Set the state machine clock divider (from integer and fractional parts - 16:8) in a state machine configuration
 | 
					/*! \brief Set the state machine clock divider (from integer and fractional parts - 16:8) in a state machine configuration
 | 
				
			||||||
 *  \ingroup sm_config
 | 
					 *  \ingroup sm_config
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -238,6 +215,38 @@ static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_
 | 
				
			|||||||
            (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
 | 
					            (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void pio_calculate_clkdiv_from_float(float div, uint16_t *div_int, uint8_t *div_frac) {
 | 
				
			||||||
 | 
					    valid_params_if(PIO, div >= 1 && div <= 65536);
 | 
				
			||||||
 | 
					    *div_int = (uint16_t)div;
 | 
				
			||||||
 | 
					    if (*div_int == 0) {
 | 
				
			||||||
 | 
					        *div_frac = 0;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        *div_frac = (uint8_t)((div - (float)*div_int) * (1u << 8u));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! \brief Set the state machine clock divider (from a floating point value) in a state machine configuration
 | 
				
			||||||
 | 
					 *  \ingroup sm_config
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The clock divider slows the state machine's execution by masking the
 | 
				
			||||||
 | 
					 * system clock on some cycles, in a repeating pattern, so that the state
 | 
				
			||||||
 | 
					 * machine does not advance. Effectively this produces a slower clock for the
 | 
				
			||||||
 | 
					 * state machine to run from, which can be used to generate e.g. a particular
 | 
				
			||||||
 | 
					 * UART baud rate. See the datasheet for further detail.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \param c Pointer to the configuration structure to modify
 | 
				
			||||||
 | 
					 * \param div The fractional divisor to be set. 1 for full speed. An integer clock divisor of n
 | 
				
			||||||
 | 
					 *  will cause the state machine to run 1 cycle in every n.
 | 
				
			||||||
 | 
					 *  Note that for small n, the jitter introduced by a fractional divider (e.g. 2.5) may be unacceptable
 | 
				
			||||||
 | 
					 *  although it will depend on the use case.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void sm_config_set_clkdiv(pio_sm_config *c, float div) {
 | 
				
			||||||
 | 
					    uint16_t div_int;
 | 
				
			||||||
 | 
					    uint8_t div_frac;
 | 
				
			||||||
 | 
					    pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
 | 
				
			||||||
 | 
					    sm_config_set_clkdiv_int_frac(c, div_int, div_frac);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! \brief Set the wrap addresses in a state machine configuration
 | 
					/*! \brief Set the wrap addresses in a state machine configuration
 | 
				
			||||||
 *  \ingroup sm_config
 | 
					 *  \ingroup sm_config
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -978,23 +987,6 @@ static inline uint32_t pio_sm_get_blocking(PIO pio, uint sm) {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void pio_sm_drain_tx_fifo(PIO pio, uint sm);
 | 
					void pio_sm_drain_tx_fifo(PIO pio, uint sm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! \brief set the current clock divider for a state machine
 | 
					 | 
				
			||||||
 *  \ingroup hardware_pio
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * \param pio The PIO instance; either \ref pio0 or \ref pio1
 | 
					 | 
				
			||||||
 * \param sm State machine index (0..3)
 | 
					 | 
				
			||||||
 * \param div the floating point clock divider
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline void pio_sm_set_clkdiv(PIO pio, uint sm, float div) {
 | 
					 | 
				
			||||||
    check_pio_param(pio);
 | 
					 | 
				
			||||||
    check_sm_param(sm);
 | 
					 | 
				
			||||||
    uint div_int = (uint16_t) div;
 | 
					 | 
				
			||||||
    uint div_frac = (uint8_t) ((div - (float)div_int) * (1u << 8u));
 | 
					 | 
				
			||||||
    pio->sm[sm].clkdiv =
 | 
					 | 
				
			||||||
            (div_frac << PIO_SM0_CLKDIV_FRAC_LSB) |
 | 
					 | 
				
			||||||
            (div_int << PIO_SM0_CLKDIV_INT_LSB);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*! \brief set the current clock divider for a state machine using a 16:8 fraction
 | 
					/*! \brief set the current clock divider for a state machine using a 16:8 fraction
 | 
				
			||||||
 *  \ingroup hardware_pio
 | 
					 *  \ingroup hardware_pio
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -1011,6 +1003,22 @@ static inline void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int
 | 
				
			|||||||
            (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
 | 
					            (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! \brief set the current clock divider for a state machine
 | 
				
			||||||
 | 
					 *  \ingroup hardware_pio
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \param pio The PIO instance; either \ref pio0 or \ref pio1
 | 
				
			||||||
 | 
					 * \param sm State machine index (0..3)
 | 
				
			||||||
 | 
					 * \param div the floating point clock divider
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void pio_sm_set_clkdiv(PIO pio, uint sm, float div) {
 | 
				
			||||||
 | 
					    check_pio_param(pio);
 | 
				
			||||||
 | 
					    check_sm_param(sm);
 | 
				
			||||||
 | 
					    uint16_t div_int;
 | 
				
			||||||
 | 
					    uint8_t div_frac;
 | 
				
			||||||
 | 
					    pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
 | 
				
			||||||
 | 
					    pio_sm_set_clkdiv_int_frac(pio, sm, div_int, div_frac);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! \brief Clear a state machine's TX and RX FIFOs
 | 
					/*! \brief Clear a state machine's TX and RX FIFOs
 | 
				
			||||||
 *  \ingroup hardware_pio
 | 
					 *  \ingroup hardware_pio
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -92,13 +92,16 @@ bool rtc_get_datetime(datetime_t *t) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Note: RTC_0 should be read before RTC_1
 | 
					    // Note: RTC_0 should be read before RTC_1
 | 
				
			||||||
    t->dotw  = (rtc_hw->rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB;
 | 
					    uint32_t rtc_0 = rtc_hw->rtc_0;
 | 
				
			||||||
    t->hour  = (rtc_hw->rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB;
 | 
					    uint32_t rtc_1 = rtc_hw->rtc_1;
 | 
				
			||||||
    t->min   = (rtc_hw->rtc_0 & RTC_RTC_0_MIN_BITS  ) >> RTC_RTC_0_MIN_LSB;
 | 
					
 | 
				
			||||||
    t->sec   = (rtc_hw->rtc_0 & RTC_RTC_0_SEC_BITS  ) >> RTC_RTC_0_SEC_LSB;
 | 
					    t->dotw  = (rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB;
 | 
				
			||||||
    t->year  = (rtc_hw->rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB;
 | 
					    t->hour  = (rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB;
 | 
				
			||||||
    t->month = (rtc_hw->rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB;
 | 
					    t->min   = (rtc_0 & RTC_RTC_0_MIN_BITS  ) >> RTC_RTC_0_MIN_LSB;
 | 
				
			||||||
    t->day   = (rtc_hw->rtc_1 & RTC_RTC_1_DAY_BITS  ) >> RTC_RTC_1_DAY_LSB;
 | 
					    t->sec   = (rtc_0 & RTC_RTC_0_SEC_BITS  ) >> RTC_RTC_0_SEC_LSB;
 | 
				
			||||||
 | 
					    t->year  = (rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB;
 | 
				
			||||||
 | 
					    t->month = (rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB;
 | 
				
			||||||
 | 
					    t->day   = (rtc_1 & RTC_RTC_1_DAY_BITS  ) >> RTC_RTC_1_DAY_LSB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -166,8 +166,9 @@ bool hardware_alarm_set_target(uint alarm_num, absolute_time_t target) {
 | 
				
			|||||||
        // 1) actually set the hardware timer
 | 
					        // 1) actually set the hardware timer
 | 
				
			||||||
        spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_TIMER);
 | 
					        spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_TIMER);
 | 
				
			||||||
        uint32_t save = spin_lock_blocking(lock);
 | 
					        uint32_t save = spin_lock_blocking(lock);
 | 
				
			||||||
        timer_hw->intr = 1u << alarm_num;
 | 
					        uint8_t old_timer_callbacks_pending = timer_callbacks_pending;
 | 
				
			||||||
        timer_callbacks_pending |= (uint8_t)(1u << alarm_num);
 | 
					        timer_callbacks_pending |= (uint8_t)(1u << alarm_num);
 | 
				
			||||||
 | 
					        timer_hw->intr = 1u << alarm_num; // clear any IRQ
 | 
				
			||||||
        timer_hw->alarm[alarm_num] = (uint32_t) t;
 | 
					        timer_hw->alarm[alarm_num] = (uint32_t) t;
 | 
				
			||||||
        // Set the alarm. Writing time should arm it
 | 
					        // Set the alarm. Writing time should arm it
 | 
				
			||||||
        target_hi[alarm_num] = (uint32_t)(t >> 32u);
 | 
					        target_hi[alarm_num] = (uint32_t)(t >> 32u);
 | 
				
			||||||
@ -178,18 +179,26 @@ bool hardware_alarm_set_target(uint alarm_num, absolute_time_t target) {
 | 
				
			|||||||
            assert(timer_hw->ints & 1u << alarm_num);
 | 
					            assert(timer_hw->ints & 1u << alarm_num);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if (time_us_64() >= t) {
 | 
					            if (time_us_64() >= t) {
 | 
				
			||||||
                // ok well it is time now; the irq isn't being handled yet because of the spin lock
 | 
					                // we are already at or past the right time; there is no point in us racing against the IRQ
 | 
				
			||||||
                // however the other core might be in the IRQ handler itself about to do a callback
 | 
					                // we are about to generate. note however that, if there was already a timer pending before,
 | 
				
			||||||
                // we do the firing ourselves (and indicate to the IRQ handler if any that it shouldn't
 | 
					                // then we still let the IRQ fire, as whatever it was, is not handled by our setting missed=true here
 | 
				
			||||||
                missed = true;
 | 
					                missed = true;
 | 
				
			||||||
                // disarm the timer
 | 
					                if (timer_callbacks_pending != old_timer_callbacks_pending) {
 | 
				
			||||||
                timer_hw->armed = 1u << alarm_num;
 | 
					                    // disarm the timer
 | 
				
			||||||
                timer_hw->intr = 1u << alarm_num; // clear the IRQ too
 | 
					                    timer_hw->armed = 1u << alarm_num;
 | 
				
			||||||
                // and set flag in case we're already in the IRQ handler waiting on the spinlock (on the other core)
 | 
					                    // clear the IRQ...
 | 
				
			||||||
                timer_callbacks_pending &= (uint8_t)~(1u << alarm_num);
 | 
					                    timer_hw->intr = 1u << alarm_num;
 | 
				
			||||||
 | 
					                    // ... including anything pending on the processor - perhaps unnecessary, but
 | 
				
			||||||
 | 
					                    // our timer flag says we aren't expecting anything.
 | 
				
			||||||
 | 
					                    irq_clear(harware_alarm_irq_number(alarm_num));
 | 
				
			||||||
 | 
					                    // and clear our flag so that if the IRQ handler is already active (because it is on
 | 
				
			||||||
 | 
					                    // the other core) it will also skip doing anything
 | 
				
			||||||
 | 
					                    timer_callbacks_pending = old_timer_callbacks_pending;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        spin_unlock(lock, save);
 | 
					        spin_unlock(lock, save);
 | 
				
			||||||
 | 
					        // note at this point any pending timer IRQ can likely run
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return missed;
 | 
					    return missed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -175,9 +175,9 @@ void *_sbrk(int incr) {
 | 
				
			|||||||
    prev_heap_end = heap_end;
 | 
					    prev_heap_end = heap_end;
 | 
				
			||||||
    char *next_heap_end = heap_end + incr;
 | 
					    char *next_heap_end = heap_end + incr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (__builtin_expect(next_heap_end >= (&__StackLimit), false)) {
 | 
					    if (__builtin_expect(next_heap_end > (&__StackLimit), false)) {
 | 
				
			||||||
#if PICO_USE_OPTIMISTIC_SBRK
 | 
					#if PICO_USE_OPTIMISTIC_SBRK
 | 
				
			||||||
        if (next_heap_end == &__StackLimit) {
 | 
					        if (heap_end == &__StackLimit) {
 | 
				
			||||||
//        errno = ENOMEM;
 | 
					//        errno = ENOMEM;
 | 
				
			||||||
            return (char *) -1;
 | 
					            return (char *) -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ if (NOT TARGET pico_standard_link)
 | 
				
			|||||||
        target_link_options(pico_standard_link INTERFACE "LINKER:-nostdlib")
 | 
					        target_link_options(pico_standard_link INTERFACE "LINKER:-nostdlib")
 | 
				
			||||||
    endif ()
 | 
					    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)
 | 
					    function(pico_add_link_depend TARGET dependency)
 | 
				
			||||||
        get_target_property(target_type ${TARGET} TYPE)
 | 
					        get_target_property(target_type ${TARGET} TYPE)
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if !PICO_NO_BINARY_INFO && !PICO_NO_PROGRAM_INFO
 | 
					#if !PICO_NO_BINARY_INFO && !PICO_NO_PROGRAM_INFO
 | 
				
			||||||
#include "pico/binary_info.h"
 | 
					#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
 | 
					// 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
 | 
					// (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
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !PICO_NO_BI_BOOT2_NAME
 | 
					#if !PICO_NO_BI_BOOT_STAGE2_NAME
 | 
				
			||||||
#ifdef PICO_BOOT2_NAME
 | 
					#ifdef PICO_BOOT_STAGE2_NAME
 | 
				
			||||||
bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BOOT2_NAME, PICO_BOOT2_NAME))
 | 
					bi_decl(bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BOOT2_NAME, PICO_BOOT_STAGE2_NAME))
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ static bool resetd_control_request_cb(uint8_t __unused rhport, tusb_control_requ
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT
 | 
					#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT
 | 
				
			||||||
        if (request->bRequest == RESET_REQUEST_FLASH) {
 | 
					        if (request->bRequest == RESET_REQUEST_FLASH) {
 | 
				
			||||||
            watchdog_reboot(0, SRAM_END, PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS);
 | 
					            watchdog_reboot(0, 0, PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -10,12 +10,13 @@
 | 
				
			|||||||
#include "pico/time.h"
 | 
					#include "pico/time.h"
 | 
				
			||||||
#include "pico/stdio/driver.h"
 | 
					#include "pico/stdio/driver.h"
 | 
				
			||||||
#include "pico/binary_info.h"
 | 
					#include "pico/binary_info.h"
 | 
				
			||||||
 | 
					#include "pico/mutex.h"
 | 
				
			||||||
#include "hardware/irq.h"
 | 
					#include "hardware/irq.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static_assert(PICO_STDIO_USB_LOW_PRIORITY_IRQ > RTC_IRQ, ""); // note RTC_IRQ is currently the last one
 | 
					static_assert(PICO_STDIO_USB_LOW_PRIORITY_IRQ > RTC_IRQ, ""); // note RTC_IRQ is currently the last one
 | 
				
			||||||
static mutex_t stdio_usb_mutex;
 | 
					static mutex_t stdio_usb_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void low_priority_worker_irq() {
 | 
					static void low_priority_worker_irq(void) {
 | 
				
			||||||
    // if the mutex is already owned, then we are in user code
 | 
					    // if the mutex is already owned, then we are in user code
 | 
				
			||||||
    // in this file which will do a tud_task itself, so we'll just do nothing
 | 
					    // in this file which will do a tud_task itself, so we'll just do nothing
 | 
				
			||||||
    // until the next tick; we won't starve
 | 
					    // until the next tick; we won't starve
 | 
				
			||||||
 | 
				
			|||||||
@ -89,7 +89,7 @@ static const tusb_desc_device_t usbd_desc_device = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
 | 
					static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
 | 
				
			||||||
    TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN,
 | 
					    TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN,
 | 
				
			||||||
        TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA),
 | 
					        0, USBD_MAX_POWER_MA),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD,
 | 
					    TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD,
 | 
				
			||||||
        USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE),
 | 
					        USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE),
 | 
				
			||||||
 | 
				
			|||||||
@ -83,6 +83,7 @@ int main(void) {
 | 
				
			|||||||
    dma_channel_configure(0, &config, &dma_to, &dma_from, 1, true);
 | 
					    dma_channel_configure(0, &config, &dma_to, &dma_from, 1, true);
 | 
				
			||||||
    dma_channel_set_config(0, &config, false);
 | 
					    dma_channel_set_config(0, &config, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // note this loop expects to cause a breakpoint!!
 | 
				
			||||||
    for (int i = 0; i < 20; i++) {
 | 
					    for (int i = 0; i < 20; i++) {
 | 
				
			||||||
        puts("sleepy");
 | 
					        puts("sleepy");
 | 
				
			||||||
        sleep_ms(1000);
 | 
					        sleep_ms(1000);
 | 
				
			||||||
@ -94,4 +95,6 @@ int main(void) {
 | 
				
			|||||||
            irq_remove_handler(DMA_IRQ_1, dma_handler_b);
 | 
					            irq_remove_handler(DMA_IRQ_1, dma_handler_b);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    // this should compile as we are Cortex M0+
 | 
				
			||||||
 | 
					    __asm volatile("SVC #3");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -64,12 +64,13 @@ static bool repeating_timer_callback(struct repeating_timer *t) {
 | 
				
			|||||||
#define RESOLUTION_ALLOWANCE PICO_HARDWARE_TIMER_RESOLUTION_US
 | 
					#define RESOLUTION_ALLOWANCE PICO_HARDWARE_TIMER_RESOLUTION_US
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int issue_195_test(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main() {
 | 
					int main() {
 | 
				
			||||||
    setup_default_uart();
 | 
					    setup_default_uart();
 | 
				
			||||||
    alarm_pool_init_default();
 | 
					    alarm_pool_init_default();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PICOTEST_START();
 | 
					    PICOTEST_START();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    struct alarm_pool *pools[NUM_TIMERS];
 | 
					    struct alarm_pool *pools[NUM_TIMERS];
 | 
				
			||||||
    for(uint i=0; i<NUM_TIMERS; i++) {
 | 
					    for(uint i=0; i<NUM_TIMERS; i++) {
 | 
				
			||||||
        if (i == alarm_pool_hardware_alarm_num(alarm_pool_get_default())) {
 | 
					        if (i == alarm_pool_hardware_alarm_num(alarm_pool_get_default())) {
 | 
				
			||||||
@ -215,6 +216,35 @@ int main() {
 | 
				
			|||||||
    PICOTEST_CHECK(absolute_time_diff_us(near_the_end_of_time, at_the_end_of_time) > 0, "near the end of time should be before the end of time")
 | 
					    PICOTEST_CHECK(absolute_time_diff_us(near_the_end_of_time, at_the_end_of_time) > 0, "near the end of time should be before the end of time")
 | 
				
			||||||
    PICOTEST_END_SECTION();
 | 
					    PICOTEST_END_SECTION();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (issue_195_test()) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PICOTEST_END_TEST();
 | 
					    PICOTEST_END_TEST();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ISSUE_195_TIMER_DELAY 50
 | 
				
			||||||
 | 
					volatile int issue_195_counter;
 | 
				
			||||||
 | 
					int64_t issue_195_callback(alarm_id_t id, void *user_data) {
 | 
				
			||||||
 | 
					    issue_195_counter++;
 | 
				
			||||||
 | 
					    return -ISSUE_195_TIMER_DELAY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int issue_195_test(void) {
 | 
				
			||||||
 | 
					    PICOTEST_START_SECTION("Issue #195 race condition - without fix may hang on gcc 10.2.1 release builds");
 | 
				
			||||||
 | 
					    absolute_time_t t1 = get_absolute_time();
 | 
				
			||||||
 | 
					    int id = add_alarm_in_us(ISSUE_195_TIMER_DELAY, issue_195_callback, NULL, true);
 | 
				
			||||||
 | 
					    for(uint i=0;i<5000;i++) {
 | 
				
			||||||
 | 
					        sleep_us(100);
 | 
				
			||||||
 | 
					        sleep_us(100);
 | 
				
			||||||
 | 
					        uint delay = 9; // 9 seems to be the magic number (at least for reproducing on 10.2.1)
 | 
				
			||||||
 | 
					        sleep_us(delay);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    absolute_time_t t2 = get_absolute_time();
 | 
				
			||||||
 | 
					    cancel_alarm(id);
 | 
				
			||||||
 | 
					    int expected_count = absolute_time_diff_us(t1, t2) / ISSUE_195_TIMER_DELAY;
 | 
				
			||||||
 | 
					    printf("Timer fires approx_expected=%d actual=%d\n", expected_count, issue_195_counter);
 | 
				
			||||||
 | 
					    PICOTEST_END_SECTION();
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -59,16 +59,19 @@ struct address_range {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef std::vector<address_range> address_ranges;
 | 
					typedef std::vector<address_range> address_ranges;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAIN_RAM_START 0x20000000u
 | 
					#define MAIN_RAM_START        0x20000000u
 | 
				
			||||||
#define MAIN_RAM_END   0x20042000u
 | 
					#define MAIN_RAM_END          0x20042000u
 | 
				
			||||||
#define FLASH_START    0x10000000u
 | 
					#define FLASH_START           0x10000000u
 | 
				
			||||||
#define FLASH_END      0x15000000u
 | 
					#define FLASH_END             0x15000000u
 | 
				
			||||||
#define XIP_SRAM_START 0x15000000u
 | 
					#define XIP_SRAM_START        0x15000000u
 | 
				
			||||||
#define XIP_SRAM_END   0x15004000u
 | 
					#define XIP_SRAM_END          0x15004000u
 | 
				
			||||||
 | 
					#define MAIN_RAM_BANKED_START 0x21000000u
 | 
				
			||||||
 | 
					#define MAIN_RAM_BANKED_END   0x21040000u
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const address_ranges rp2040_address_ranges_flash {
 | 
					const address_ranges rp2040_address_ranges_flash {
 | 
				
			||||||
    address_range(FLASH_START, FLASH_END, address_range::type::CONTENTS),
 | 
					    address_range(FLASH_START, FLASH_END, address_range::type::CONTENTS),
 | 
				
			||||||
    address_range(MAIN_RAM_START, MAIN_RAM_END, address_range::type::NO_CONTENTS)
 | 
					    address_range(MAIN_RAM_START, MAIN_RAM_END, address_range::type::NO_CONTENTS),
 | 
				
			||||||
 | 
					    address_range(MAIN_RAM_BANKED_START, MAIN_RAM_BANKED_END, address_range::type::NO_CONTENTS)
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const address_ranges rp2040_address_ranges_ram {
 | 
					const address_ranges rp2040_address_ranges_ram {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user