diff --git a/.github/workflows/choco_packages.config b/.github/workflows/choco_packages.config
index d443f751..9f1dea0e 100644
--- a/.github/workflows/choco_packages.config
+++ b/.github/workflows/choco_packages.config
@@ -2,5 +2,5 @@
-
+
diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel
index 4e622af5..3d75654e 100644
--- a/bazel/config/BUILD.bazel
+++ b/bazel/config/BUILD.bazel
@@ -186,6 +186,12 @@ int_flag(
build_setting_default = 0,
)
+# PICO_BAZEL_CONFIG: PICO_TINYUSB_CONFIG, [Bazel only] The library that provides TinyUSB config header (e.g. tusb_config.h), default=//src/rp2_common/pico_stdio_usb:tusb_config, group=build
+label_flag(
+ name = "PICO_TINYUSB_CONFIG",
+ build_setting_default = "//src/rp2_common/pico_stdio_usb:tusb_config",
+)
+
# PICO_BAZEL_CONFIG: PICO_TINYUSB_LIB, [Bazel only] The library that provides TinyUSB, default=@tinyusb//:tinyusb, group=build
label_flag(
name = "PICO_TINYUSB_LIB",
diff --git a/cmake/pico_pre_load_platform.cmake b/cmake/pico_pre_load_platform.cmake
index df9aebdd..ea112757 100644
--- a/cmake/pico_pre_load_platform.cmake
+++ b/cmake/pico_pre_load_platform.cmake
@@ -122,7 +122,7 @@ if (PICO_PREVIOUS_PLATFORM AND NOT PICO_PREVIOUS_PLATFORM STREQUAL PICO_PLATFORM
The best practice is to use separate build directories for different platforms.")
endif()
set(PICO_PLATFORM ${PICO_PLATFORM} CACHE STRING "PICO Build platform (e.g. rp2040, rp2350, rp2350-riscv, host)" FORCE)
-set(PICO_PREVIOUS_PLATFORM ${PICO_PLATFORM} CACHE STRING "Saved PICO Build platform (e.g. rp2040, rp2350, rp2350-riscv, host)" INTERNAL)
+set(PICO_PREVIOUS_PLATFORM ${PICO_PLATFORM} CACHE INTERNAL "Saved PICO Build platform (e.g. rp2040, rp2350, rp2350-riscv, host)")
# PICO_CMAKE_CONFIG: PICO_CMAKE_PRELOAD_PLATFORM_FILE, Custom CMake file to use to set up the platform environment, type=string, group=build
set(PICO_CMAKE_PRELOAD_PLATFORM_FILE ${PICO_CMAKE_PRELOAD_PLATFORM_FILE} CACHE INTERNAL "")
diff --git a/docs/index.h b/docs/index.h
index b760936c..a4f88a43 100644
--- a/docs/index.h
+++ b/docs/index.h
@@ -48,9 +48,9 @@
* \cond hardware_watchdog \defgroup hardware_watchdog hardware_watchdog \endcond
* \cond hardware_xip_cache \defgroup hardware_xip_cache hardware_xip_cache \endcond
* \cond hardware_xosc \defgroup hardware_xosc hardware_xosc \endcond
- * \cond hardware_powman hardware_powman
- * \cond hardware_hazard3 hardware_hazard3
- * \cond hardware_riscv hardware_riscv
+ * \cond hardware_powman \defgroup hardware_powman hardware_powman \endcond
+ * \cond hardware_hazard3 \defgroup hardware_hazard3 hardware_hazard3 \endcond
+ * \cond hardware_riscv \defgroup hardware_riscv hardware_riscv \endcond
* @}
*
diff --git a/src/BUILD.bazel b/src/BUILD.bazel
index 58d564ba..a397b486 100644
--- a/src/BUILD.bazel
+++ b/src/BUILD.bazel
@@ -19,6 +19,7 @@ alias(
"//src/rp2_common/boot_bootrom_headers:__pkg__",
"//src/rp2_common/hardware_boot_lock:__pkg__",
"//src/rp2_common/pico_flash:__pkg__",
+ "//src/rp2_common/hardware_rcp:__pkg__",
],
)
diff --git a/src/boards/include/boards/amethyst_fpga.h b/src/boards/include/boards/amethyst_fpga.h
index ea6b9a2d..190a0767 100644
--- a/src/boards/include/boards/amethyst_fpga.h
+++ b/src/boards/include/boards/amethyst_fpga.h
@@ -9,8 +9,6 @@
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
-// FIXME delete this file before release (board file for Amethyst FPGA platform)
-
// pico_cmake_set PICO_PLATFORM=rp2350
#ifndef _BOARDS_AMETHYST_FPGA_H
diff --git a/src/boards/include/boards/eelectronicparts_picomini_16mb.h b/src/boards/include/boards/eelectronicparts_picomini_16mb.h
new file mode 100644
index 00000000..52a53081
--- /dev/null
+++ b/src/boards/include/boards/eelectronicparts_picomini_16mb.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the E Electronic Parts "Pico_Mini RP2040"
+//
+// This header may be included by other board headers as "boards/eelectronicparts_picomini_16mb.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2040
+
+#ifndef _BOARDS_EELECTRONICPARTS_PICOMINI_16MB_H
+#define _BOARDS_EELECTRONICPARTS_PICOMINI_16MB_H
+
+// For board detection
+#define EELECTRONICPARTS_PICOMINI_16MB
+
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 16
+#endif
+
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 16
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 17
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 10
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 11
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 12
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 13
+#endif
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (16 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+// This board comes in 2MB, 4MB, 8MB, and 16MB variants
+#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
+#endif
+// All boards have B1 RP2040
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/eelectronicparts_picomini_2mb.h b/src/boards/include/boards/eelectronicparts_picomini_2mb.h
new file mode 100644
index 00000000..e0fcab1f
--- /dev/null
+++ b/src/boards/include/boards/eelectronicparts_picomini_2mb.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the E Electronic Parts "Pico_Mini RP2040"
+//
+// This header may be included by other board headers as "boards/eelectronicparts_picomini_2mb.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2040
+
+#ifndef _BOARDS_EELECTRONICPARTS_PICOMINI_2MB_H
+#define _BOARDS_EELECTRONICPARTS_PICOMINI_2MB_H
+
+// For board detection
+#define EELECTRONICPARTS_PICOMINI_2MB
+
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 16
+#endif
+
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 16
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 17
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 10
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 11
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 12
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 13
+#endif
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (2 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+// This board comes in 2MB, 4MB, 8MB, and 16MB variants
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+// All boards have B1 RP2040
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/eelectronicparts_picomini_4mb.h b/src/boards/include/boards/eelectronicparts_picomini_4mb.h
new file mode 100644
index 00000000..132dc0c9
--- /dev/null
+++ b/src/boards/include/boards/eelectronicparts_picomini_4mb.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the E Electronic Parts "Pico_Mini RP2040"
+//
+// This header may be included by other board headers as "boards/eelectronicparts_picomini_4mb.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2040
+
+#ifndef _BOARDS_EELECTRONICPARTS_PICOMINI_4MB_H
+#define _BOARDS_EELECTRONICPARTS_PICOMINI_4MB_H
+
+// For board detection
+#define EELECTRONICPARTS_PICOMINI_4MB
+
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 16
+#endif
+
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 16
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 17
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 10
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 11
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 12
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 13
+#endif
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (4 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+// This board comes in 2MB, 4MB, 8MB, and 16MB variants
+#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
+#endif
+// All boards have B1 RP2040
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/eelectronicparts_picomini_8mb.h b/src/boards/include/boards/eelectronicparts_picomini_8mb.h
new file mode 100644
index 00000000..479e1105
--- /dev/null
+++ b/src/boards/include/boards/eelectronicparts_picomini_8mb.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the E Electronic Parts "Pico_Mini RP2040"
+//
+// This header may be included by other board headers as "boards/eelectronicparts_picomini_8mb.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2040
+
+#ifndef _BOARDS_EELECTRONICPARTS_PICOMINI_8MB_H
+#define _BOARDS_EELECTRONICPARTS_PICOMINI_8MB_H
+
+// For board detection
+#define EELECTRONICPARTS_PICOMINI_8MB
+
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 16
+#endif
+
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 16
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 17
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 10
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 11
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 12
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 13
+#endif
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+// This board comes in 2MB, 4MB, 8MB, and 16MB variants
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+// All boards have B1 RP2040
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/hellbender_0001.h b/src/boards/include/boards/hellbender_0001.h
index 9091f912..9f43803e 100644
--- a/src/boards/include/boards/hellbender_0001.h
+++ b/src/boards/include/boards/hellbender_0001.h
@@ -138,7 +138,7 @@
#define HELLBENDER_0001_BLACKBOX_FLASH_SIZE_BYTES (16 * 1024 * 1024)
// --- RP2350 VARIANT ---
-#define PICO_RP2350B 1
+#define PICO_RP2350A 0
// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
#ifndef PICO_RP2350_A2_SUPPORTED
diff --git a/src/boards/include/boards/pimoroni_pga2350.h b/src/boards/include/boards/pimoroni_pga2350.h
index f4f0a3d2..1bd02dc4 100644
--- a/src/boards/include/boards/pimoroni_pga2350.h
+++ b/src/boards/include/boards/pimoroni_pga2350.h
@@ -20,6 +20,9 @@
#define PIMORONI_PGA2350
#define PIMORONI_PGA2350_16MB
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 0
+
// --- BOARD SPECIFIC ---
#define PIMORONI_PGA2350_PSRAM_CS_PIN 47
diff --git a/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h b/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h
index 34c5fb38..40fff17d 100644
--- a/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h
+++ b/src/boards/include/boards/pimoroni_pico_plus2_rp2350.h
@@ -19,6 +19,9 @@
// For board detection
#define PIMORONI_PICO_PLUS2_RP2350
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 0
+
// --- BOARD SPECIFIC ---
#define SPCE_SPI 0
#define SPCE_TX_MISO_PIN 32
diff --git a/src/boards/include/boards/pimoroni_pico_plus2_w_rp2350.h b/src/boards/include/boards/pimoroni_pico_plus2_w_rp2350.h
index ba3c0e56..7a4f1741 100644
--- a/src/boards/include/boards/pimoroni_pico_plus2_w_rp2350.h
+++ b/src/boards/include/boards/pimoroni_pico_plus2_w_rp2350.h
@@ -20,6 +20,9 @@
// For board detection
#define PIMORONI_PICO_PLUS2_W_RP2350
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 0
+
// --- BOARD SPECIFIC ---
#define PIMORONI_PICO_PLUS2_W_USER_SW_PIN 45
#define PIMORONI_PICO_PLUS2_W_PSRAM_CS_PIN 47
diff --git a/src/boards/include/boards/seeed_xiao_rp2350.h b/src/boards/include/boards/seeed_xiao_rp2350.h
index 52e16365..69a2ba40 100644
--- a/src/boards/include/boards/seeed_xiao_rp2350.h
+++ b/src/boards/include/boards/seeed_xiao_rp2350.h
@@ -17,6 +17,9 @@
// For board detection
#define SEEED_XIAO_RP2350
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 1
+
//------------- UART -------------//
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 0
diff --git a/src/boards/include/boards/sparkfun_xrp_controller.h b/src/boards/include/boards/sparkfun_xrp_controller.h
new file mode 100644
index 00000000..70c2f13c
--- /dev/null
+++ b/src/boards/include/boards/sparkfun_xrp_controller.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+// Board definition for the SparkFun XRP Controller
+//
+// This header may be included by other board headers as "boards/sparkfun_xrp_controller.h"
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+// pico_cmake_set PICO_CYW43_SUPPORTED = 1
+
+#ifndef _BOARDS_SPARKFUN_XRP_CONTROLLER_H
+#define _BOARDS_SPARKFUN_XRP_CONTROLLER_H
+
+// For board detection
+#define SPARKFUN_XRP_CONTROLLER
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 0
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 12
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 13
+#endif
+
+// --- LED ---
+// no PICO_DEFAULT_LED_PIN - LED is on Wireless chip
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 37
+#endif
+
+// --- I2C --- Qwiic connector is on these pins
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (16 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
+#endif
+
+#ifndef CYW43_WL_GPIO_COUNT
+#define CYW43_WL_GPIO_COUNT 3
+#endif
+
+#ifndef CYW43_WL_GPIO_LED_PIN
+#define CYW43_WL_GPIO_LED_PIN 0
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+// cyw43 SPI pins can't be changed at runtime
+#ifndef CYW43_PIN_WL_DYNAMIC
+#define CYW43_PIN_WL_DYNAMIC 0
+#endif
+
+// gpio pin to power up the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_REG_ON
+#define CYW43_DEFAULT_PIN_WL_REG_ON 26u
+#endif
+
+// gpio pin for spi data out to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_OUT
+#define CYW43_DEFAULT_PIN_WL_DATA_OUT 29u
+#endif
+
+// gpio pin for spi data in from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_DATA_IN
+#define CYW43_DEFAULT_PIN_WL_DATA_IN 29u
+#endif
+
+// gpio (irq) pin for the irq line from the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_HOST_WAKE
+#define CYW43_DEFAULT_PIN_WL_HOST_WAKE 29u
+#endif
+
+// gpio pin for the spi clock line to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CLOCK
+#define CYW43_DEFAULT_PIN_WL_CLOCK 28u
+#endif
+
+// gpio pin for the spi chip select to the cyw43 chip
+#ifndef CYW43_DEFAULT_PIN_WL_CS
+#define CYW43_DEFAULT_PIN_WL_CS 27u
+#endif
+
+#endif
diff --git a/src/cmake/rp2_common.cmake b/src/cmake/rp2_common.cmake
index 726bab93..9e6f9f3f 100644
--- a/src/cmake/rp2_common.cmake
+++ b/src/cmake/rp2_common.cmake
@@ -82,6 +82,7 @@ endif()
# Basic bootrom headers
pico_add_subdirectory(rp2_common/boot_bootrom_headers)
+pico_add_subdirectory(rp2_common/pico_platform_common)
pico_add_subdirectory(rp2_common/pico_platform_compiler)
pico_add_subdirectory(rp2_common/pico_platform_sections)
pico_add_subdirectory(rp2_common/pico_platform_panic)
diff --git a/src/common/pico_base_headers/BUILD.bazel b/src/common/pico_base_headers/BUILD.bazel
index 5525c309..c22f9ae8 100644
--- a/src/common/pico_base_headers/BUILD.bazel
+++ b/src/common/pico_base_headers/BUILD.bazel
@@ -112,6 +112,7 @@ cc_library(
"//src/rp2_common/hardware_watchdog:__pkg__",
"//src/rp2_common/hardware_xosc:__pkg__",
"//src/rp2_common/pico_crt0:__pkg__",
+ "//src/rp2_common/pico_platform_common:__pkg__",
"//src/rp2_common/pico_printf:__pkg__",
"//src/rp2_common/pico_runtime:__pkg__",
"//src/rp2_common/pico_runtime_init:__pkg__",
diff --git a/src/common/pico_base_headers/include/pico/types.h b/src/common/pico_base_headers/include/pico/types.h
index 2e9c3964..010181ee 100644
--- a/src/common/pico_base_headers/include/pico/types.h
+++ b/src/common/pico_base_headers/include/pico/types.h
@@ -23,18 +23,18 @@ typedef unsigned int uint;
#endif
/*! \typedef absolute_time_t
- \brief An opaque 64 bit timestamp in microseconds
-
- The type is used instead of a raw uint64_t to prevent accidentally passing relative times or times in the wrong
- time units where an absolute time is required.
-
- note: As of SDK 2.0.0 this type defaults to being a uin64_t (i.e. no protection); it is enabled
- by setting PICO_OPAQUE_ABSOLUTE_TIME_T to 1
-
- \see to_us_since_boot()
- \see update_us_since_boot()
- \ingroup timestamp
-*/
+ * \brief An opaque 64 bit timestamp in microseconds
+ *
+ * The type is used instead of a raw uint64_t to prevent accidentally passing relative times or times in the wrong
+ * time units where an absolute time is required.
+ *
+ * note: As of SDK 2.0.0 this type defaults to being a uin64_t (i.e. no protection); it is enabled
+ * by setting PICO_OPAQUE_ABSOLUTE_TIME_T to 1
+ *
+ * \see to_us_since_boot()
+ * \see update_us_since_boot()
+ * \ingroup timestamp
+ */
#if PICO_OPAQUE_ABSOLUTE_TIME_T
typedef struct {
uint64_t _private_us_since_boot;
diff --git a/src/common/pico_sync/include/pico/critical_section.h b/src/common/pico_sync/include/pico/critical_section.h
index 0e9907a9..9874f9ff 100644
--- a/src/common/pico_sync/include/pico/critical_section.h
+++ b/src/common/pico_sync/include/pico/critical_section.h
@@ -7,6 +7,7 @@
#ifndef _PICO_CRITICAL_SECTION_H
#define _PICO_CRITICAL_SECTION_H
+#include "pico.h"
#include "pico/lock_core.h"
#ifdef __cplusplus
@@ -58,7 +59,7 @@ void critical_section_init_with_lock_num(critical_section_t *crit_sec, uint lock
*
* \param crit_sec Pointer to critical_section structure
*/
-static inline void critical_section_enter_blocking(critical_section_t *crit_sec) {
+__force_inline static void critical_section_enter_blocking(critical_section_t *crit_sec) {
crit_sec->save = spin_lock_blocking(crit_sec->spin_lock);
}
@@ -67,7 +68,7 @@ static inline void critical_section_enter_blocking(critical_section_t *crit_sec)
*
* \param crit_sec Pointer to critical_section structure
*/
-static inline void critical_section_exit(critical_section_t *crit_sec) {
+__force_inline static void critical_section_exit(critical_section_t *crit_sec) {
spin_unlock(crit_sec->spin_lock, crit_sec->save);
}
diff --git a/src/common/pico_time/include/pico/time.h b/src/common/pico_time/include/pico/time.h
index 771fe42d..43d5ed7a 100644
--- a/src/common/pico_time/include/pico/time.h
+++ b/src/common/pico_time/include/pico/time.h
@@ -216,7 +216,7 @@ static inline bool is_nil_time(absolute_time_t t) {
* \note These functions should not be called from an IRQ handler.
*
* \note Lower powered sleep requires use of the \link alarm_pool_get_default default alarm pool\endlink which may
- * be disabled by the PICO_TIME_DEFAULT_ALARM_POOL_DISABLED #define or currently full in which case these functions
+ * be disabled by the PICO_TIME_DEFAULT_ALARM_POOL_DISABLED \#define or currently full in which case these functions
* become busy waits instead.
*
* \note Whilst \a sleep_ functions are preferable to \a busy_wait functions from a power perspective, the \a busy_wait equivalent function
@@ -420,7 +420,7 @@ alarm_pool_timer_t *alarm_pool_get_default_timer(void);
* \param max_timers the maximum number of timers
* \note For implementation reasons this is limited to PICO_PHEAP_MAX_ENTRIES which defaults to 255
* \sa alarm_pool_get_default()
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
static inline alarm_pool_t *alarm_pool_create(uint timer_alarm_num, uint max_timers) {
return alarm_pool_create_on_timer(alarm_pool_get_default_timer(), timer_alarm_num, max_timers);
@@ -443,7 +443,7 @@ alarm_pool_t *alarm_pool_create_on_timer_with_unused_hardware_alarm(alarm_pool_t
* \param max_timers the maximum number of timers
* \note For implementation reasons this is limited to PICO_PHEAP_MAX_ENTRIES which defaults to 255
* \sa alarm_pool_get_default()
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
static inline alarm_pool_t *alarm_pool_create_with_unused_hardware_alarm(uint max_timers) {
return alarm_pool_create_on_timer_with_unused_hardware_alarm(alarm_pool_get_default_timer(), max_timers);
diff --git a/src/host/hardware_irq/include/hardware/irq.h b/src/host/hardware_irq/include/hardware/irq.h
index 0e881b7a..ef90ee70 100644
--- a/src/host/hardware_irq/include/hardware/irq.h
+++ b/src/host/hardware_irq/include/hardware/irq.h
@@ -128,7 +128,7 @@ extern "C" {
typedef void (*irq_handler_t)(void);
static inline void check_irq_param(__unused uint num) {
- invalid_params_if(HARDWARE_IRQ, num >= NUM_IRQS);
+ invalid_params_if(HARDWARE_IRQ, num >= PICO_NUM_VTABLE_IRQS);
}
/*! \brief Set specified interrupt's priority
diff --git a/src/host/hardware_irq/irq.c b/src/host/hardware_irq/irq.c
index ad793c19..db452ab1 100644
--- a/src/host/hardware_irq/irq.c
+++ b/src/host/hardware_irq/irq.c
@@ -96,7 +96,7 @@ void PICO_WEAK_FUNCTION_IMPL_NAME(irq_init_priorities)() {
}
static uint get_user_irq_claim_index(uint irq_num) {
- invalid_params_if(HARDWARE_IRQ, irq_num < FIRST_USER_IRQ || irq_num >= NUM_IRQS);
+ invalid_params_if(HARDWARE_IRQ, irq_num < FIRST_USER_IRQ || irq_num >= PICO_NUM_VTABLE_IRQS);
// we count backwards from the last, to match the existing hard coded uses of user IRQs in the SDK which were previously using 31
static_assert(NUM_IRQS - FIRST_USER_IRQ <= 8, ""); // we only use a single byte's worth of claim bits today.
return NUM_IRQS - irq_num - 1u;
diff --git a/src/host/pico_platform/include/pico/platform.h b/src/host/pico_platform/include/pico/platform.h
index 2854ab6f..0338354e 100644
--- a/src/host/pico_platform/include/pico/platform.h
+++ b/src/host/pico_platform/include/pico/platform.h
@@ -60,6 +60,12 @@ extern void tight_loop_contents();
#define __noinline __attribute__((noinline))
#endif
+#ifndef __force_inline
+// don't think it is critical to inline in host mode, and this is simpler than picking the
+// correct attribute incantation for always_inline on different compiler versions
+#define __force_inline inline
+#endif
+
#ifndef __aligned
#define __aligned(x) __attribute__((aligned(x)))
#endif
diff --git a/src/rp2040/hardware_regs/RP2040.svd b/src/rp2040/hardware_regs/RP2040.svd
index 2bac8265..50a5a93f 100644
--- a/src/rp2040/hardware_regs/RP2040.svd
+++ b/src/rp2040/hardware_regs/RP2040.svd
@@ -51022,5 +51022,38 @@ SPDX-License-Identifier: BSD-3-Clause
+
+ SPARE_IRQ
+ 0x00000000
+
+ 0
+ 4
+ reserved
+
+
+ SPARE_IRQ_0
+ 26
+
+
+ SPARE_IRQ_1
+ 27
+
+
+ SPARE_IRQ_2
+ 28
+
+
+ SPARE_IRQ_3
+ 29
+
+
+ SPARE_IRQ_4
+ 30
+
+
+ SPARE_IRQ_5
+ 31
+
+
diff --git a/src/rp2040/hardware_regs/include/hardware/regs/intctrl.h b/src/rp2040/hardware_regs/include/hardware/regs/intctrl.h
index 3190b413..71c6eb90 100644
--- a/src/rp2040/hardware_regs/include/hardware/regs/intctrl.h
+++ b/src/rp2040/hardware_regs/include/hardware/regs/intctrl.h
@@ -39,6 +39,12 @@
#define I2C0_IRQ 23
#define I2C1_IRQ 24
#define RTC_IRQ 25
+#define SPARE_IRQ_0 26
+#define SPARE_IRQ_1 27
+#define SPARE_IRQ_2 28
+#define SPARE_IRQ_3 29
+#define SPARE_IRQ_4 30
+#define SPARE_IRQ_5 31
#else
/**
* \brief Interrupt numbers on RP2040 (used as typedef \ref irq_num_t)
@@ -71,6 +77,12 @@ typedef enum irq_num_rp2040 {
I2C0_IRQ = 23, ///< Select I2C0's IRQ output
I2C1_IRQ = 24, ///< Select I2C1's IRQ output
RTC_IRQ = 25, ///< Select RTC's IRQ output
+ SPARE_IRQ_0 = 26, ///< Select SPARE IRQ 0
+ SPARE_IRQ_1 = 27, ///< Select SPARE IRQ 1
+ SPARE_IRQ_2 = 28, ///< Select SPARE IRQ 2
+ SPARE_IRQ_3 = 29, ///< Select SPARE IRQ 3
+ SPARE_IRQ_4 = 30, ///< Select SPARE IRQ 4
+ SPARE_IRQ_5 = 31, ///< Select SPARE IRQ 5
IRQ_COUNT
} irq_num_t;
#endif
@@ -101,6 +113,12 @@ typedef enum irq_num_rp2040 {
#define isr_i2c0 isr_irq23
#define isr_i2c1 isr_irq24
#define isr_rtc isr_irq25
+#define isr_spare_0 isr_irq26
+#define isr_spare_1 isr_irq27
+#define isr_spare_2 isr_irq28
+#define isr_spare_3 isr_irq29
+#define isr_spare_4 isr_irq30
+#define isr_spare_5 isr_irq31
#endif // _INTCTRL_H
diff --git a/src/rp2040/pico_platform/BUILD.bazel b/src/rp2040/pico_platform/BUILD.bazel
index bc860f1f..47b90e43 100644
--- a/src/rp2040/pico_platform/BUILD.bazel
+++ b/src/rp2040/pico_platform/BUILD.bazel
@@ -27,6 +27,7 @@ cc_library(
deps = [
"//src/rp2040/hardware_regs",
"//src/rp2040/hardware_regs:platform_defs",
+ "//src/rp2_common/pico_platform_common:pico_platform_common_headers",
"//src/rp2_common/pico_platform_compiler",
"//src/rp2_common/pico_platform_panic:pico_platform_panic_headers",
"//src/rp2_common/pico_platform_sections",
@@ -44,6 +45,7 @@ cc_library(
"//src/rp2040/hardware_regs",
"//src/rp2040/hardware_regs:platform_defs",
"//src/rp2_common/hardware_base",
+ "//src/rp2_common/pico_platform_common",
"//src/rp2_common/pico_platform_compiler",
"//src/rp2_common/pico_platform_panic",
"//src/rp2_common/pico_platform_sections",
diff --git a/src/rp2040/pico_platform/CMakeLists.txt b/src/rp2040/pico_platform/CMakeLists.txt
index f7c607a4..9c91df3e 100644
--- a/src/rp2040/pico_platform/CMakeLists.txt
+++ b/src/rp2040/pico_platform/CMakeLists.txt
@@ -17,6 +17,7 @@ if (NOT TARGET pico_platform)
target_link_libraries(pico_platform_headers INTERFACE hardware_regs)
pico_mirrored_target_link_libraries(pico_platform INTERFACE
+ pico_platform_common
pico_platform_compiler
pico_platform_panic
pico_platform_sections
diff --git a/src/rp2040/pico_platform/include/pico/platform.h b/src/rp2040/pico_platform/include/pico/platform.h
index 5c157f53..437ff31f 100644
--- a/src/rp2040/pico_platform/include/pico/platform.h
+++ b/src/rp2040/pico_platform/include/pico/platform.h
@@ -23,6 +23,7 @@
#include "pico/platform/compiler.h"
#include "pico/platform/sections.h"
#include "pico/platform/panic.h"
+#include "pico/platform/common.h"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/sio.h"
@@ -66,10 +67,6 @@
#define PICO_RP2040_B2_SUPPORTED 1
#endif
-#ifndef PICO_RAM_VECTOR_TABLE_SIZE
-#define PICO_RAM_VECTOR_TABLE_SIZE (VTABLE_FIRST_IRQ + NUM_IRQS)
-#endif
-
// PICO_CONFIG: PICO_CLKDIV_ROUND_NEAREST, True if floating point clock divisors should be rounded to the nearest possible clock divisor by default rather than rounding down, type=bool, default=1, group=pico_platform
#ifndef PICO_CLKDIV_ROUND_NEAREST
#define PICO_CLKDIV_ROUND_NEAREST 1
@@ -80,16 +77,6 @@
#ifdef __cplusplus
extern "C" {
#endif
-
-/*! \brief No-op function for the body of tight loops
- * \ingroup pico_platform
- *
- * No-op function intended to be called by any tight hardware polling loop. Using this ubiquitously
- * makes it much easier to find tight loops, but also in the future \#ifdef-ed support for lockup
- * debugging might be added
- */
-static __force_inline void tight_loop_contents(void) {}
-
/*! \brief Helper method to busy-wait for at least the given number of cycles
* \ingroup pico_platform
*
@@ -112,17 +99,6 @@ static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) {
);
}
-// PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
-#ifndef PICO_NO_FPGA_CHECK
-#define PICO_NO_FPGA_CHECK 1
-#endif
-
-#if PICO_NO_FPGA_CHECK
-static inline bool running_on_fpga(void) {return false;}
-#else
-bool running_on_fpga(void);
-#endif
-
/*! \brief Execute a breakpoint instruction
* \ingroup pico_platform
*/
@@ -158,9 +134,6 @@ static __force_inline uint __get_current_exception(void) {
return exception;
}
-#define host_safe_hw_ptr(x) ((uintptr_t)(x))
-#define native_safe_hw_ptr(x) host_safe_hw_ptr(x)
-
/*! \brief Returns the RP2040 chip revision number
* \ingroup pico_platform
* @return the RP2040 chip revision number (1 for B0/B1, 2 for B2)
diff --git a/src/rp2040/pico_platform/platform.c b/src/rp2040/pico_platform/platform.c
index 9b001653..5468670d 100644
--- a/src/rp2040/pico_platform/platform.c
+++ b/src/rp2040/pico_platform/platform.c
@@ -6,23 +6,8 @@
#include "pico.h"
#include "hardware/address_mapped.h"
-#include "hardware/regs/tbman.h"
#include "hardware/regs/sysinfo.h"
-// Note we leave the FPGA check in by default so that we can run bug repro
-// binaries coming in from the wild on the FPGA platform. It takes up around
-// 48 bytes if you include all the calls, so you can pass PICO_NO_FPGA_CHECK=1
-// to remove it. The FPGA check is used to skip initialisation of hardware
-// (mainly clock generators and oscillators) that aren't present on FPGA.
-
-#if !PICO_NO_FPGA_CHECK
-// Inline stub provided in header if this code is unused (so folding can be
-// done in each TU instead of relying on LTO)
-bool running_on_fpga(void) {
- return (*(io_ro_32 *)TBMAN_BASE) & TBMAN_PLATFORM_FPGA_BITS;
-}
-#endif
-
#define MANUFACTURER_RPI 0x927
#define PART_RP2 0x2
diff --git a/src/rp2350/hardware_regs/RP2350.svd b/src/rp2350/hardware_regs/RP2350.svd
index fc6479eb..c942b3a5 100644
--- a/src/rp2350/hardware_regs/RP2350.svd
+++ b/src/rp2350/hardware_regs/RP2350.svd
@@ -105846,5 +105846,40 @@ SPDX-License-Identifier: BSD-3-Clause
+
+
+ SPARE_IRQ
+ 0x00000000
+
+ 0
+ 4
+ reserved
+
+
+ SPARE_IRQ_0
+ 46
+
+
+ SPARE_IRQ_1
+ 47
+
+
+ SPARE_IRQ_2
+ 48
+
+
+ SPARE_IRQ_3
+ 49
+
+
+ SPARE_IRQ_4
+ 50
+
+
+ SPARE_IRQ_5
+ 51
+
+
+
diff --git a/src/rp2350/hardware_regs/include/hardware/regs/intctrl.h b/src/rp2350/hardware_regs/include/hardware/regs/intctrl.h
index 96ce815e..4db58399 100644
--- a/src/rp2350/hardware_regs/include/hardware/regs/intctrl.h
+++ b/src/rp2350/hardware_regs/include/hardware/regs/intctrl.h
@@ -59,12 +59,12 @@
#define PLL_USB_IRQ 43
#define POWMAN_IRQ_POW 44
#define POWMAN_IRQ_TIMER 45
-#define SPAREIRQ_IRQ_0 46
-#define SPAREIRQ_IRQ_1 47
-#define SPAREIRQ_IRQ_2 48
-#define SPAREIRQ_IRQ_3 49
-#define SPAREIRQ_IRQ_4 50
-#define SPAREIRQ_IRQ_5 51
+#define SPARE_IRQ_0 46
+#define SPARE_IRQ_1 47
+#define SPARE_IRQ_2 48
+#define SPARE_IRQ_3 49
+#define SPARE_IRQ_4 50
+#define SPARE_IRQ_5 51
#else
/**
* \brief Interrupt numbers on RP2350 (used as typedef \ref irq_num_t)
diff --git a/src/rp2350/pico_platform/BUILD.bazel b/src/rp2350/pico_platform/BUILD.bazel
index 8b51a2dd..b24291a2 100644
--- a/src/rp2350/pico_platform/BUILD.bazel
+++ b/src/rp2350/pico_platform/BUILD.bazel
@@ -27,6 +27,7 @@ cc_library(
deps = [
"//src/rp2350/hardware_regs",
"//src/rp2350/hardware_regs:platform_defs",
+ "//src/rp2_common/pico_platform_common:pico_platform_common_headers",
"//src/rp2_common/pico_platform_compiler",
"//src/rp2_common/pico_platform_panic:pico_platform_panic_headers",
"//src/rp2_common/pico_platform_sections",
@@ -44,6 +45,7 @@ cc_library(
"//src/rp2350/hardware_regs",
"//src/rp2350/hardware_regs:platform_defs",
"//src/rp2_common/hardware_base",
+ "//src/rp2_common/pico_platform_common",
"//src/rp2_common/pico_platform_compiler",
"//src/rp2_common/pico_platform_panic",
"//src/rp2_common/pico_platform_sections",
diff --git a/src/rp2350/pico_platform/CMakeLists.txt b/src/rp2350/pico_platform/CMakeLists.txt
index 80a5103e..7f875bf3 100644
--- a/src/rp2350/pico_platform/CMakeLists.txt
+++ b/src/rp2350/pico_platform/CMakeLists.txt
@@ -23,6 +23,7 @@ if (NOT TARGET pico_platform)
hardware_regs
)
pico_mirrored_target_link_libraries(pico_platform INTERFACE
+ pico_platform_common
pico_platform_compiler
pico_platform_panic
pico_platform_sections
diff --git a/src/rp2350/pico_platform/include/pico/platform.h b/src/rp2350/pico_platform/include/pico/platform.h
index 35a6a0bd..571efd8b 100644
--- a/src/rp2350/pico_platform/include/pico/platform.h
+++ b/src/rp2350/pico_platform/include/pico/platform.h
@@ -23,13 +23,14 @@
#include "pico/platform/compiler.h"
#include "pico/platform/sections.h"
#include "pico/platform/panic.h"
+#include "pico/platform/common.h"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/sio.h"
#ifdef __riscv
#include "hardware/regs/rvcsr.h"
#endif
-// PICO_CONFIG: PICO_RP2350A, Whether the current board has an RP2350 in an A (30 GPIO) package, type=bool, default=Usually provided via board header, group=pico_platform
+// PICO_CONFIG: PICO_RP2350A, Whether the current board has an RP2350 in an A (30 GPIO) package - set to 0 for RP2350 in a B (48 GPIO) package, type=bool, default=Usually provided via board header, group=pico_platform
#if 0 // make tooling checks happy
#define PICO_RP2350A 0
#endif
@@ -54,10 +55,6 @@
#define PICO_NO_RAM_VECTOR_TABLE 0
#endif
-#ifndef PICO_RAM_VECTOR_TABLE_SIZE
-#define PICO_RAM_VECTOR_TABLE_SIZE (VTABLE_FIRST_IRQ + NUM_IRQS)
-#endif
-
// PICO_CONFIG: PICO_USE_STACK_GUARDS, Enable/disable stack guards, type=bool, default=0, advanced=true, group=pico_platform
#ifndef PICO_USE_STACK_GUARDS
#define PICO_USE_STACK_GUARDS 0
@@ -73,16 +70,6 @@
#ifdef __cplusplus
extern "C" {
#endif
-
-/*! \brief No-op function for the body of tight loops
- * \ingroup pico_platform
- *
- * No-op function intended to be called by any tight hardware polling loop. Using this ubiquitously
- * makes it much easier to find tight loops, but also in the future \#ifdef-ed support for lockup
- * debugging might be added
- */
-static __force_inline void tight_loop_contents(void) {}
-
/*! \brief Helper method to busy-wait for at least the given number of cycles
* \ingroup pico_platform
*
@@ -116,27 +103,6 @@ static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) {
);
}
-// PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
-#ifndef PICO_NO_FPGA_CHECK
-#define PICO_NO_FPGA_CHECK 1
-#endif
-
-// PICO_CONFIG: PICO_NO_SIM_CHECK, Remove the SIM platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
-#ifndef PICO_NO_SIM_CHECK
-#define PICO_NO_SIM_CHECK 1
-#endif
-
-#if PICO_NO_FPGA_CHECK
-static inline bool running_on_fpga(void) {return false;}
-#else
-bool running_on_fpga(void);
-#endif
-#if PICO_NO_SIM_CHECK
-static inline bool running_in_sim(void) {return false;}
-#else
-bool running_in_sim(void);
-#endif
-
/*! \brief Execute a breakpoint instruction
* \ingroup pico_platform
*/
@@ -221,9 +187,6 @@ __force_inline static bool pico_processor_state_is_nonsecure(void) {
#endif
}
-#define host_safe_hw_ptr(x) ((uintptr_t)(x))
-#define native_safe_hw_ptr(x) host_safe_hw_ptr(x)
-
/*! \brief Returns the RP2350 chip revision number
* \ingroup pico_platform
* @return the RP2350 chip revision number (1 for B0/B1, 2 for B2)
diff --git a/src/rp2350/pico_platform/platform.c b/src/rp2350/pico_platform/platform.c
index 97960478..a71b8a0a 100644
--- a/src/rp2350/pico_platform/platform.c
+++ b/src/rp2350/pico_platform/platform.c
@@ -6,28 +6,8 @@
#include "pico.h"
#include "hardware/address_mapped.h"
-#include "hardware/regs/tbman.h"
#include "hardware/regs/sysinfo.h"
-// Note we leave the FPGA check in by default so that we can run bug repro
-// binaries coming in from the wild on the FPGA platform. It takes up around
-// 48 bytes if you include all the calls, so you can pass PICO_NO_FPGA_CHECK=1
-// to remove it. The FPGA check is used to skip initialisation of hardware
-// (mainly clock generators and oscillators) that aren't present on FPGA.
-
-#if !PICO_NO_FPGA_CHECK
-// Inline stub provided in header if this code is unused (so folding can be
-// done in each TU instead of relying on LTO)
-bool __attribute__((weak)) running_on_fpga(void) {
- return (*(io_ro_32 *)TBMAN_BASE) & TBMAN_PLATFORM_FPGA_BITS;
-}
-#endif
-#if !PICO_NO_SIM_CHECK
-bool __attribute__((weak)) running_in_sim(void) {
- return (*(io_ro_32 *)TBMAN_BASE) & TBMAN_PLATFORM_HDLSIM_BITS;
-}
-#endif
-
#define MANUFACTURER_RPI 0x926
#define PART_RP4 0x4
@@ -36,9 +16,9 @@ uint8_t rp2350_chip_version(void) {
uint32_t chip_id = *((io_ro_32*)(SYSINFO_BASE + SYSINFO_CHIP_ID_OFFSET));
uint32_t __unused manufacturer = chip_id & SYSINFO_CHIP_ID_MANUFACTURER_BITS;
uint32_t __unused part = (chip_id & SYSINFO_CHIP_ID_PART_BITS) >> SYSINFO_CHIP_ID_PART_LSB;
- assert(manufacturer == MANUFACTURER_RPI);
- assert(part == PART_RP4);
+ assert(manufacturer == MANUFACTURER_RPI && part == PART_RP4);
// 0 == A0, 1 == A1, 2 == A2
- uint version = (chip_id & SYSINFO_CHIP_ID_REVISION_BITS) >> SYSINFO_CHIP_ID_REVISION_LSB;
+ uint32_t version = (chip_id & SYSINFO_CHIP_ID_REVISION_BITS) >> SYSINFO_CHIP_ID_REVISION_LSB;
+ version = (version & 3u) | ((version & 8u) >> 1);
return (uint8_t)version;
}
\ No newline at end of file
diff --git a/src/rp2_common/hardware_dma/include/hardware/dma.h b/src/rp2_common/hardware_dma/include/hardware/dma.h
index 94b74cb7..27dd9228 100644
--- a/src/rp2_common/hardware_dma/include/hardware/dma.h
+++ b/src/rp2_common/hardware_dma/include/hardware/dma.h
@@ -123,7 +123,7 @@ int dma_claim_unused_channel(bool required);
* \param channel the dma channel
* \return true if the channel is claimed, false otherwise
* \see dma_channel_claim
- * \see dma_channel_claim_mask
+ * \see dma_claim_mask
*/
bool dma_channel_is_claimed(uint channel);
diff --git a/src/rp2_common/hardware_exception/exception.c b/src/rp2_common/hardware_exception/exception.c
index d3134fbc..52a5b64c 100644
--- a/src/rp2_common/hardware_exception/exception.c
+++ b/src/rp2_common/hardware_exception/exception.c
@@ -31,12 +31,14 @@ static inline exception_handler_t *get_exception_table(void) {
#endif
}
+#if !PICO_NO_RAM_VECTOR_TABLE
static void set_raw_exception_handler_and_restore_interrupts(enum exception_number num, exception_handler_t handler, uint32_t save) {
// update vtable (vtable_handler may be same or updated depending on cases, but we do it anyway for compactness)
get_exception_table()[num] = handler;
__dmb();
restore_interrupts_from_disabled(save);
}
+#endif
static inline void check_exception_param(__unused enum exception_number num) {
invalid_params_if(HARDWARE_EXCEPTION, num < MIN_EXCEPTION_NUM || num > MAX_EXCEPTION_NUM);
@@ -54,10 +56,12 @@ exception_handler_t exception_set_exclusive_handler(enum exception_number num, e
exception_handler_t current = exception_get_vtable_handler(num);
hard_assert(handler == current || exception_is_compile_time_default(current));
set_raw_exception_handler_and_restore_interrupts(num, handler, save);
+ return current;
#else
+ ((void)num);
+ ((void)handler);
panic_unsupported();
#endif
- return current;
}
void exception_restore_handler(enum exception_number num, exception_handler_t original_handler) {
@@ -66,6 +70,8 @@ void exception_restore_handler(enum exception_number num, exception_handler_t or
uint32_t save = save_and_disable_interrupts();
set_raw_exception_handler_and_restore_interrupts(num, original_handler, save);
#else
+ ((void)num);
+ ((void)original_handler);
panic_unsupported();
#endif
}
diff --git a/src/rp2_common/hardware_gpio/include/hardware/gpio.h b/src/rp2_common/hardware_gpio/include/hardware/gpio.h
index bd1f4b68..f05bc000 100644
--- a/src/rp2_common/hardware_gpio/include/hardware/gpio.h
+++ b/src/rp2_common/hardware_gpio/include/hardware/gpio.h
@@ -204,6 +204,11 @@ enum gpio_irq_level {
*/
typedef void (*gpio_irq_callback_t)(uint gpio, uint32_t event_mask);
+/*! \brief GPIO override modes
+ * \ingroup hardware_gpio
+ *
+ * \sa gpio_set_irqover, gpio_set_outover, gpio_set_inover, gpio_set_oeover
+ */
enum gpio_override {
GPIO_OVERRIDE_NORMAL = 0, ///< peripheral signal selected via \ref gpio_set_function
GPIO_OVERRIDE_INVERT = 1, ///< invert peripheral signal selected via \ref gpio_set_function
@@ -782,6 +787,8 @@ static inline void gpio_add_raw_irq_handler(uint gpio, irq_handler_t handler) {
*
* This method removes such a callback, and enables the "default" callback for the specified GPIOs.
*
+ * \note You should always use the same gpio_mask as you used when you added the raw IRQ handler.
+ *
* @param gpio_mask a bit mask of the GPIO numbers that will now be passed to the default callback for this core
* @param handler the handler to remove from the list of GPIO IRQ handlers for this core
*/
diff --git a/src/rp2_common/hardware_i2c/include/hardware/i2c.h b/src/rp2_common/hardware_i2c/include/hardware/i2c.h
index 604b89f9..5453752e 100644
--- a/src/rp2_common/hardware_i2c/include/hardware/i2c.h
+++ b/src/rp2_common/hardware_i2c/include/hardware/i2c.h
@@ -324,10 +324,10 @@ int i2c_write_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t
* (for example) without having to send address byte(s) repeatedly
*
* \param i2c Either \ref i2c0 or \ref i2c1
- * \param addr 7-bit address of device to read from
- * \param dst Pointer to buffer to receive data
- * \param len Length of data in bytes to receive
- * \return Number of bytes read, or PICO_ERROR_GENERIC if address not acknowledged or no device present.
+ * \param addr 7-bit address of device to write to
+ * \param src Pointer to data to send
+ * \param len Length of data in bytes to send
+ * \return Number of bytes written, or PICO_ERROR_GENERIC if address not acknowledged or no device present.
*/
int i2c_write_burst_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len);
diff --git a/src/rp2_common/hardware_interp/include/hardware/interp.h b/src/rp2_common/hardware_interp/include/hardware/interp.h
index 634af0f4..befe1f8c 100644
--- a/src/rp2_common/hardware_interp/include/hardware/interp.h
+++ b/src/rp2_common/hardware_interp/include/hardware/interp.h
@@ -107,7 +107,7 @@ void interp_unclaim_lane(interp_hw_t *interp, uint lane);
*/
bool interp_lane_is_claimed(interp_hw_t *interp, uint lane);
-/*! \brief Release previously claimed interpolator lanes \see interp_claim_lane_mask
+/*! \brief Release previously claimed interpolator lanes, see \ref interp_claim_lane_mask
* \ingroup hardware_interp
*
* \param interp Interpolator on which to release lanes. interp0 or interp1
diff --git a/src/rp2_common/hardware_irq/include/hardware/irq.h b/src/rp2_common/hardware_irq/include/hardware/irq.h
index d671903d..0dcc49d5 100644
--- a/src/rp2_common/hardware_irq/include/hardware/irq.h
+++ b/src/rp2_common/hardware_irq/include/hardware/irq.h
@@ -195,7 +195,7 @@ extern "C" {
typedef void (*irq_handler_t)(void);
static inline void check_irq_param(__unused uint num) {
- invalid_params_if(HARDWARE_IRQ, num >= NUM_IRQS);
+ invalid_params_if(HARDWARE_IRQ, num >= PICO_NUM_VTABLE_IRQS);
}
/*! \brief Set specified interrupt's priority
diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c
index b06db13c..9b6f5ecd 100644
--- a/src/rp2_common/hardware_irq/irq.c
+++ b/src/rp2_common/hardware_irq/irq.c
@@ -15,6 +15,12 @@
PICO_RUNTIME_INIT_FUNC_PER_CORE(runtime_init_per_core_irq_priorities, PICO_RUNTIME_INIT_PER_CORE_IRQ_PRIORITIES);
#endif
+static_assert(IRQ_COUNT == NUM_IRQS, "");
+// "USER IRQs" use the spare irq numbers
+#if NUM_USER_IRQS
+static_assert(IRQ_COUNT - NUM_USER_IRQS == SPARE_IRQ_0, "");
+#endif
+
#if PICO_VTABLE_PER_CORE
static uint8_t user_irq_claimed[NUM_CORES];
static inline uint8_t *user_irq_claimed_ptr(void) {
@@ -51,13 +57,6 @@ static inline void *remove_thumb_bit(void *addr) {
#endif
}
-static void set_raw_irq_handler_and_unlock(uint num, irq_handler_t handler, uint32_t save) {
- // update vtable (vtable_handler may be same or updated depending on cases, but we do it anyway for compactness)
- get_vtable()[VTABLE_FIRST_IRQ + num] = handler;
- __dmb();
- spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_IRQ), save);
-}
-
void irq_set_enabled(uint num, bool enabled) {
check_irq_param(num);
// really should update irq_set_mask_enabled?
@@ -76,7 +75,7 @@ bool irq_is_enabled(uint num) {
}
static inline void irq_set_mask_n_enabled_internal(uint n, uint32_t mask, bool enabled) {
- invalid_params_if(HARDWARE_IRQ, n * 32u >= ((NUM_IRQS + 31u) & ~31u));
+ invalid_params_if(HARDWARE_IRQ, n * 32u >= ((PICO_NUM_VTABLE_IRQS + 31u) & ~31u));
#if defined(__riscv)
if (enabled) {
hazard3_irqarray_clear(RVCSR_MEIFA_OFFSET, 2 * n, mask & 0xffffu);
@@ -129,7 +128,7 @@ void irq_set_pending(uint num) {
#endif
}
-#if !PICO_DISABLE_SHARED_IRQ_HANDLERS
+#if !PICO_DISABLE_SHARED_IRQ_HANDLERS && !PICO_NO_RAM_VECTOR_TABLE
// limited by 8 bit relative links (and reality)
static_assert(PICO_MAX_SHARED_IRQ_HANDLERS >= 1 && PICO_MAX_SHARED_IRQ_HANDLERS < 0x7f, "");
@@ -197,31 +196,38 @@ static inline bool is_shared_irq_raw_handler(irq_handler_t raw_handler) {
return (uintptr_t)raw_handler - (uintptr_t)irq_handler_chain_slots < sizeof(irq_handler_chain_slots);
}
-bool irq_has_handler(uint irq_num) {
- check_irq_param(irq_num);
- irq_handler_t handler = irq_get_vtable_handler(irq_num);
- return handler && handler != __unhandled_user_irq;
-}
-
bool irq_has_shared_handler(uint irq_num) {
check_irq_param(irq_num);
irq_handler_t handler = irq_get_vtable_handler(irq_num);
return is_shared_irq_raw_handler(handler);
}
-#else // PICO_DISABLE_SHARED_IRQ_HANDLERS
+static void set_raw_irq_handler_and_unlock(uint num, irq_handler_t handler, uint32_t save) {
+ // update vtable (vtable_handler may be same or updated depending on cases, but we do it anyway for compactness)
+ get_vtable()[VTABLE_FIRST_IRQ + num] = handler;
+ __dmb();
+ spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_IRQ), save);
+}
+
+#else // PICO_DISABLE_SHARED_IRQ_HANDLERS && PICO_NO_RAM_VECTOR_TABLE
#define is_shared_irq_raw_handler(h) false
bool irq_has_shared_handler(uint irq_num) {
+ ((void)irq_num);
return false;
}
#endif
-
irq_handler_t irq_get_vtable_handler(uint num) {
check_irq_param(num);
return get_vtable()[VTABLE_FIRST_IRQ + num];
}
+bool irq_has_handler(uint irq_num) {
+ check_irq_param(irq_num);
+ irq_handler_t handler = irq_get_vtable_handler(irq_num);
+ return handler && handler != __unhandled_user_irq;
+}
+
void irq_set_exclusive_handler(uint num, irq_handler_t handler) {
check_irq_param(num);
#if !PICO_NO_RAM_VECTOR_TABLE
@@ -231,6 +237,7 @@ void irq_set_exclusive_handler(uint num, irq_handler_t handler) {
hard_assert(current == __unhandled_user_irq || current == handler);
set_raw_irq_handler_and_unlock(num, handler, save);
#else
+ ((void)handler);
panic_unsupported();
#endif
}
@@ -252,7 +259,7 @@ irq_handler_t irq_get_exclusive_handler(uint num) {
}
-#if !PICO_DISABLE_SHARED_IRQ_HANDLERS
+#if !PICO_DISABLE_SHARED_IRQ_HANDLERS && !PICO_NO_RAM_VECTOR_TABLE
#ifndef __riscv
@@ -362,6 +369,8 @@ static inline int8_t get_slot_index(struct irq_handler_chain_slot *slot) {
void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_priority) {
check_irq_param(num);
#if PICO_NO_RAM_VECTOR_TABLE
+ ((void)handler);
+ ((void)order_priority);
panic_unsupported();
#elif PICO_DISABLE_SHARED_IRQ_HANDLERS
irq_set_exclusive_handler(num, handler);
@@ -455,7 +464,7 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
#endif // !PICO_NO_RAM_VECTOR_TABLE && !PICO_DISABLE_SHARED_IRQ_HANDLERS
}
-#if !PICO_DISABLE_SHARED_IRQ_HANDLERS
+#if !PICO_DISABLE_SHARED_IRQ_HANDLERS && !PICO_NO_RAM_VECTOR_TABLE
static inline irq_handler_t handler_from_slot(struct irq_handler_chain_slot *slot) {
#ifndef __riscv
return slot->handler;
@@ -580,6 +589,8 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
}
set_raw_irq_handler_and_unlock(num, vtable_handler, save);
#else
+ ((void)num);
+ ((void)handler);
panic_unsupported();
#endif
}
@@ -620,7 +631,7 @@ uint irq_get_priority(uint num) {
#endif
}
-#if !PICO_DISABLE_SHARED_IRQ_HANDLERS
+#if !PICO_DISABLE_SHARED_IRQ_HANDLERS && !PICO_NO_RAM_VECTOR_TABLE
// used by irq_handler_chain.S to remove the last link in a handler chain after it executes
// note this must be called only with the last slot in a chain (and during the exception)
void irq_add_tail_to_free_list(struct irq_handler_chain_slot *slot) {
@@ -664,7 +675,7 @@ __weak void runtime_init_per_core_irq_priorities(void) {
*p++ = prio4;
}
#else
- for (uint i = 0; i < NUM_IRQS; ++i) {
+ for (uint i = 0; i < PICO_NUM_VTABLE_IRQS; ++i) {
irq_set_priority(i, PICO_DEFAULT_IRQ_PRIORITY);
}
#endif
@@ -672,7 +683,7 @@ __weak void runtime_init_per_core_irq_priorities(void) {
}
static uint get_user_irq_claim_index(uint irq_num) {
- invalid_params_if(HARDWARE_IRQ, irq_num < FIRST_USER_IRQ || irq_num >= NUM_IRQS);
+ invalid_params_if(HARDWARE_IRQ, irq_num < FIRST_USER_IRQ || irq_num >= PICO_NUM_VTABLE_IRQS);
// we count backwards from the last, to match the existing hard coded uses of user IRQs in the SDK which were previously using 31
static_assert(NUM_IRQS - FIRST_USER_IRQ <= 8, ""); // we only use a single byte's worth of claim bits today.
return NUM_IRQS - irq_num - 1u;
diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h
index b1173309..8654d32a 100644
--- a/src/rp2_common/hardware_pio/include/hardware/pio.h
+++ b/src/rp2_common/hardware_pio/include/hardware/pio.h
@@ -680,7 +680,7 @@ static inline void sm_config_set_out_shift(pio_sm_config *c, bool shift_right, b
* \ingroup sm_config
*
* \param c Pointer to the configuration structure to modify
- * \param join Specifies the join type. \see enum pio_fifo_join
+ * \param join Specifies the join type. See \ref pio_fifo_join
*/
static inline void sm_config_set_fifo_join(pio_sm_config *c, enum pio_fifo_join join) {
valid_params_if(HARDWARE_PIO, join == PIO_FIFO_JOIN_NONE || join == PIO_FIFO_JOIN_TX || join == PIO_FIFO_JOIN_RX
@@ -720,7 +720,7 @@ static inline void sm_config_set_out_special(pio_sm_config *c, bool sticky, bool
* \ingroup sm_config
*
* \param c Pointer to the configuration structure to modify
- * \param status_sel the status operation selector. \see enum pio_mov_status_type
+ * \param status_sel the status operation selector. See \ref pio_mov_status_type
* \param status_n parameter for the mov status operation (currently a bit count)
*/
static inline void sm_config_set_mov_status(pio_sm_config *c, enum pio_mov_status_type status_sel, uint status_n) {
@@ -849,7 +849,7 @@ static inline uint pio_get_index(PIO pio) {
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \return the PIO instance number (0, 1, ...)
- * \see gpio_function
+ * \see gpio_function_t
*/
static inline uint pio_get_funcsel(PIO pio) {
check_pio_param(pio);
@@ -948,7 +948,7 @@ bool pio_can_add_program_at_offset(PIO pio, const pio_program_t *program, uint o
/*! \brief Attempt to load the program
* \ingroup hardware_pio
*
- * \see pio_can_add_program() if you need to check whether the program can be loaded
+ * See pio_can_add_program() if you need to check whether the program can be loaded
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param program the program definition
@@ -960,7 +960,7 @@ int pio_add_program(PIO pio, const pio_program_t *program);
/*! \brief Attempt to load the program at the specified instruction memory offset
* \ingroup hardware_pio
*
- * \see pio_can_add_program_at_offset() if you need to check whether the program can be loaded
+ * See pio_can_add_program_at_offset() if you need to check whether the program can be loaded
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
* \param program the program definition
@@ -998,7 +998,7 @@ void pio_clear_instruction_memory(PIO pio);
*
* The state machine is left disabled on return from this call.
*
-* * \if rp2350_specific
+ * \if rp2350_specific
* See \ref sm_config_pins "sm_config_ pins" for more detail on why this method might fail on RP2350B
* \endif
*
@@ -1006,7 +1006,7 @@ void pio_clear_instruction_memory(PIO pio);
* \param sm State machine index (0..3)
* \param initial_pc the initial program memory offset to run from
* \param config the configuration to apply (or NULL to apply defaults)
- * \return PICO_OK, or < 0 for an error (see \enum pico_error_codes)
+ * \return PICO_OK, or < 0 for an error (see \ref pico_error_codes)
*/
int pio_sm_init(PIO pio, uint sm, uint initial_pc, const pio_sm_config *config);
@@ -1029,7 +1029,7 @@ static inline void pio_sm_set_enabled(PIO pio, uint sm, bool enabled) {
* Note that this method just sets the enabled state of the state machine;
* if now enabled they continue exactly from where they left off.
*
- * \see pio_enable_sm_mask_in_sync() if you wish to enable multiple state machines
+ * See pio_enable_sm_mask_in_sync() if you wish to enable multiple state machines
* and ensure their clock dividers are in sync.
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
@@ -1049,7 +1049,7 @@ static inline void pio_set_sm_mask_enabled(PIO pio, uint32_t mask, bool enabled)
* Note that this method just sets the enabled state of the state machine;
* if now enabled they continue exactly from where they left off.
*
- * \see pio_enable_sm_mask_in_sync() if you wish to enable multiple state machines
+ * See pio_enable_sm_mask_in_sync() if you wish to enable multiple state machines
* and ensure their clock dividers are in sync.
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
@@ -1419,7 +1419,7 @@ static inline uint8_t pio_sm_get_pc(PIO pio, uint sm) {
*
* This instruction is executed instead of the next instruction in the normal control flow on the state machine.
* Subsequent calls to this method replace the previous executed
- * instruction if it is still running. \see pio_sm_is_exec_stalled() to see if an executed instruction
+ * instruction if it is still running. See pio_sm_is_exec_stalled() to see if an executed instruction
* is still running (i.e. it is stalled on some condition)
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
@@ -1450,7 +1450,7 @@ static inline bool pio_sm_is_exec_stalled(PIO pio, uint sm) {
*
* This instruction is executed instead of the next instruction in the normal control flow on the state machine.
* Subsequent calls to this method replace the previous executed
- * instruction if it is still running. \see pio_sm_is_exec_stalled() to see if an executed instruction
+ * instruction if it is still running. See pio_sm_is_exec_stalled() to see if an executed instruction
* is still running (i.e. it is stalled on some condition)
*
* \param pio The PIO instance; e.g. \ref pio0 or \ref pio1
@@ -1982,7 +1982,7 @@ bool pio_sm_is_claimed(PIO pio, uint sm);
* \param sm Returns the index of the PIO state machine that was claimed
* \param offset Returns the instruction memory offset of the start of the program
* \return true on success, false otherwise
- * \see pio_remove_program_unclaim_sm
+ * \see pio_remove_program_and_unclaim_sm
*/
bool pio_claim_free_sm_and_add_program(const pio_program_t *program, PIO *pio, uint *sm, uint *offset);
@@ -1994,7 +1994,7 @@ bool pio_claim_free_sm_and_add_program(const pio_program_t *program, PIO *pio, u
* PIO instance can interact with both pins 0->15 or 32->47 at the same time.
*
* This method takes additional information about the GPIO pins needed (via gpio_base and gpio_count),
- * and optionally will set the GPIO base (\see pio_set_gpio_base) of an unused PIO instance if necessary
+ * and optionally will set the GPIO base (see \ref pio_set_gpio_base) of an unused PIO instance if necessary
*
* \param program PIO program to add
* \param pio Returns the PIO hardware instance or NULL if no PIO is available
@@ -2006,7 +2006,7 @@ bool pio_claim_free_sm_and_add_program(const pio_program_t *program, PIO *pio, u
* instance, then that PIO will be reconfigured so that this method can succeed
*
* \return true on success, false otherwise
- * \see pio_remove_program_unclaim_sm
+ * \see pio_remove_program_and_unclaim_sm
*/
bool pio_claim_free_sm_and_add_program_for_gpio_range(const pio_program_t *program, PIO *pio, uint *sm, uint *offset, uint gpio_base, uint gpio_count, bool set_gpio_base);
diff --git a/src/rp2_common/hardware_rcp/BUILD.bazel b/src/rp2_common/hardware_rcp/BUILD.bazel
index 750ae819..6f8be1be 100644
--- a/src/rp2_common/hardware_rcp/BUILD.bazel
+++ b/src/rp2_common/hardware_rcp/BUILD.bazel
@@ -2,6 +2,19 @@ load("//bazel:defs.bzl", "compatible_with_rp2")
package(default_visibility = ["//visibility:public"])
+# Picotool needs this (transitively through
+# //src/rp2_common/pico_bootrom:pico_bootrom_headers), so we can't strictly
+# constrain compatibility.
+cc_library(
+ name = "hardware_rcp_headers",
+ hdrs = ["include/hardware/rcp.h"],
+ includes = ["include"],
+ visibility = ["//src/rp2_common/pico_bootrom:__pkg__"],
+ deps = [
+ "//src:pico_platform_internal",
+ ],
+)
+
cc_library(
name = "hardware_rcp",
hdrs = ["include/hardware/rcp.h"],
diff --git a/src/rp2_common/hardware_rcp/include/hardware/rcp.h b/src/rp2_common/hardware_rcp/include/hardware/rcp.h
index b75f182d..64c88c5a 100644
--- a/src/rp2_common/hardware_rcp/include/hardware/rcp.h
+++ b/src/rp2_common/hardware_rcp/include/hardware/rcp.h
@@ -15,13 +15,15 @@
*/
// ----------------------------------------------------------------------------
-// RCP instructions (this header is Arm-only)
-#if defined(PICO_RP2350) && !defined(__riscv)
+// RCP masks
+#if !PICO_RP2040
#define RCP_MASK_TRUE _u(0xa500a500)
#define RCP_MASK_FALSE _u(0x00c300c3)
#define RCP_MASK_INTXOR _u(0x96009600)
+// RCP instructions (these instructions are Arm-only)
+#if HAS_REDUNDANCY_COPROCESSOR
// ----------------------------------------------------------------------------
// Macros and inline functions for use in C files
#ifndef __ASSEMBLER__
@@ -994,7 +996,8 @@ rcp_switch_u8_to_ch_cl rcp_canary_check_nodelay_impl \tag, \x
cdp p7, #0, c0, c0, c0, #1
.endm
-#endif // !__riscv
+#endif // HAS_REDUNDANCY_COPROCESSOR
+#endif // !PICO_RP2040
#endif // __ASSEMBLER__
// ----------------------------------------------------------------------------
diff --git a/src/rp2_common/hardware_resets/include/hardware/resets.h b/src/rp2_common/hardware_resets/include/hardware/resets.h
index 8baef728..f7577571 100644
--- a/src/rp2_common/hardware_resets/include/hardware/resets.h
+++ b/src/rp2_common/hardware_resets/include/hardware/resets.h
@@ -23,6 +23,8 @@
*
* Multiple blocks are referred to using a bitmask as follows:
*
+ * \if rp2040_specific
+ * For RP2040:
* Block to reset | Bit
* ---------------|----
* USB | 24
@@ -41,15 +43,51 @@
* PIO 1 | 11
* PIO 0 | 10
* Pads - QSPI | 9
- * Pads - bank 0 | 8
+ * Pads - Bank 0 | 8
* JTAG | 7
- * IO Bank 1 | 6
+ * IO QSPI | 6
* IO Bank 0 | 5
* I2C 1 | 4
* I2C 0 | 3
* DMA | 2
* Bus Control | 1
* ADC 0 | 0
+ * \endif
+ *
+ * \if rp2350_specific
+ * For RP2350:
+ * Block to reset | Bit
+ * ---------------|----
+ * USB | 28
+ * UART 1 | 27
+ * UART 0 | 26
+ * TRNG | 25
+ * Timer 1 | 24
+ * Timer 0 | 23
+ * TB Manager | 22
+ * SysInfo | 21
+ * System Config | 20
+ * SPI 1 | 19
+ * SPI 0 | 18
+ * SHA256 | 17
+ * PWM | 16
+ * PLL USB | 15
+ * PLL System | 14
+ * PIO 2 | 13
+ * PIO 1 | 12
+ * PIO 0 | 11
+ * Pads - QSPI | 10
+ * Pads - Bank 0 | 9
+ * JTAG | 8
+ * IO QSPI | 7
+ * IO Bank 0 | 6
+ * I2C 1 | 5
+ * I2C 0 | 4
+ * HSTX | 3
+ * DMA | 2
+ * Bus Control | 1
+ * ADC 0 | 0
+ * \endif
*
* \subsection reset_example Example
* \addtogroup hardware_resets
diff --git a/src/rp2_common/hardware_sha256/include/hardware/sha256.h b/src/rp2_common/hardware_sha256/include/hardware/sha256.h
index db8fca6f..dcbf1043 100644
--- a/src/rp2_common/hardware_sha256/include/hardware/sha256.h
+++ b/src/rp2_common/hardware_sha256/include/hardware/sha256.h
@@ -122,7 +122,7 @@ static inline bool sha256_is_sum_valid(void) {
* \ingroup hardware_sha256
*
* After writing 64 bytes of data to the hardware, it will be unable to accept more data for a time.
- * Call this to check if the hardware is ready for more data to be written. \see sha256_err_not_ready
+ * Call this to check if the hardware is ready for more data to be written. See \ref sha256_err_not_ready
*
* \return True if the hardware is ready to receive more data
*/
diff --git a/src/rp2_common/hardware_spi/include/hardware/spi.h b/src/rp2_common/hardware_spi/include/hardware/spi.h
index cf79645d..bd83770c 100644
--- a/src/rp2_common/hardware_spi/include/hardware/spi.h
+++ b/src/rp2_common/hardware_spi/include/hardware/spi.h
@@ -202,7 +202,7 @@ uint spi_set_baudrate(spi_inst_t *spi, uint baudrate);
/*! \brief Get SPI baudrate
* \ingroup hardware_spi
*
- * Get SPI baudrate which was set by \see spi_set_baudrate
+ * Get SPI baudrate which was set by \ref spi_set_baudrate
*
* \param spi SPI instance specifier, either \ref spi0 or \ref spi1
* \return The actual baudrate set
diff --git a/src/rp2_common/hardware_timer/include/hardware/timer.h b/src/rp2_common/hardware_timer/include/hardware/timer.h
index 289a28a3..b2696408 100644
--- a/src/rp2_common/hardware_timer/include/hardware/timer.h
+++ b/src/rp2_common/hardware_timer/include/hardware/timer.h
@@ -351,7 +351,7 @@ typedef void (*hardware_alarm_callback_t)(uint alarm_num);
* \param timer the timer instance
* \param alarm_num the hardware alarm to claim
* \sa hardware_alarm_claim
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
void timer_hardware_alarm_claim(timer_hw_t *timer, uint alarm_num);
@@ -362,7 +362,7 @@ void timer_hardware_alarm_claim(timer_hw_t *timer, uint alarm_num);
*
* \param alarm_num the hardware alarm to claim
* \sa timer_hardware_alarm_claim
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
void hardware_alarm_claim(uint alarm_num);
@@ -375,7 +375,7 @@ void hardware_alarm_claim(uint alarm_num);
* \param required if true the function will panic if none are available
* \return alarm_num the hardware alarm claimed or -1 if required was false, and none are available
* \sa hardware_alarm_claim_unused
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
int timer_hardware_alarm_claim_unused(timer_hw_t *timer, bool required);
@@ -387,7 +387,7 @@ int timer_hardware_alarm_claim_unused(timer_hw_t *timer, bool required);
* \param required if true the function will panic if none are available
* \return alarm_num the hardware alarm claimed or -1 if required was false, and none are available
* \sa timer_hardware_alarm_claim_unused
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
int hardware_alarm_claim_unused(bool required);
@@ -397,7 +397,7 @@ int hardware_alarm_claim_unused(bool required);
* \param timer the timer instance
* \param alarm_num the hardware alarm to unclaim
* \sa hardware_alarm_unclaim
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
void timer_hardware_alarm_unclaim(timer_hw_t *timer, uint alarm_num);
@@ -406,7 +406,7 @@ void timer_hardware_alarm_unclaim(timer_hw_t *timer, uint alarm_num);
*
* \param alarm_num the hardware alarm to unclaim
* \sa timer_hardware_alarm_unclaim
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
void hardware_alarm_unclaim(uint alarm_num);
diff --git a/src/rp2_common/pico_async_context/include/pico/async_context.h b/src/rp2_common/pico_async_context/include/pico/async_context.h
index 6f7c4f0d..8a19b9ca 100644
--- a/src/rp2_common/pico_async_context/include/pico/async_context.h
+++ b/src/rp2_common/pico_async_context/include/pico/async_context.h
@@ -84,8 +84,8 @@ typedef struct async_context async_context_t;
* A "timeout" represents some future action that must be taken at a specific time.
* Its methods are called from the async_context under lock at the given time
*
- * \see async_context_add_worker_at
- * \see async_context_add_worker_in_ms
+ * \see async_context_add_at_time_worker_at
+ * \see async_context_add_at_time_worker_in_ms
*/
typedef struct async_work_on_timeout {
/*!
@@ -119,8 +119,8 @@ typedef struct async_work_on_timeout {
* to some external stimulus (usually an IRQ).
* Its methods are called from the async_context under lock at the given time
*
- * \see async_context_add_worker_at
- * \see async_context_add_worker_in_ms
+ * \see async_context_add_at_time_worker_at
+ * \see async_context_add_at_time_worker_in_ms
*/
typedef struct async_when_pending_worker {
/*!
diff --git a/src/rp2_common/pico_bootrom/BUILD.bazel b/src/rp2_common/pico_bootrom/BUILD.bazel
index 53a24b10..1463216d 100644
--- a/src/rp2_common/pico_bootrom/BUILD.bazel
+++ b/src/rp2_common/pico_bootrom/BUILD.bazel
@@ -18,6 +18,7 @@ cc_library(
"//src/rp2_common/boot_bootrom_headers",
"//src/rp2_common/hardware_boot_lock:hardware_boot_lock_headers",
"//src/rp2_common/pico_flash:pico_flash_headers",
+ "//src/rp2_common/hardware_rcp:hardware_rcp_headers",
] + select({
"//bazel/constraint:host": ["//src/host/hardware_sync"],
"//conditions:default": ["//src/rp2_common/hardware_sync"],
diff --git a/src/rp2_common/pico_bootrom/bootrom.c b/src/rp2_common/pico_bootrom/bootrom.c
index 1120f006..cedc27fc 100644
--- a/src/rp2_common/pico_bootrom/bootrom.c
+++ b/src/rp2_common/pico_bootrom/bootrom.c
@@ -7,6 +7,9 @@
#include "pico/bootrom.h"
#include "boot/picoboot.h"
#include "boot/picobin.h"
+#if !PICO_RP2040
+#include "hardware/rcp.h"
+#endif
/// \tag::table_lookup[]
@@ -108,4 +111,89 @@ int rom_add_flash_runtime_partition(uint32_t start_offset, uint32_t size, uint32
}
return PICO_ERROR_INSUFFICIENT_RESOURCES;
}
+
+int rom_pick_ab_update_partition(uint32_t *workarea_base, uint32_t workarea_size, uint partition_a_num) {
+#if PICO_RP2350
+ // Generated from adding the following code into the bootrom
+ // scan_workarea_t* scan_workarea = (scan_workarea_t*)workarea;
+ // printf("VERSION_DOWNGRADE_ERASE_ADDR %08x\n", &(always->zero_init.version_downgrade_erase_flash_addr));
+ // printf("TBYB_FLAG_ADDR %08x\n", &(always->zero_init.tbyb_flag_flash_addr));
+ // printf("IMAGE_DEF_VERIFIED %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.verified) - (uint32_t)scan_workarea);
+ // printf("IMAGE_DEF_TBYB_FLAGGED %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.tbyb_flagged) - (uint32_t)scan_workarea);
+ // printf("IMAGE_DEF_BASE %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.enclosing_window.base) - (uint32_t)scan_workarea);
+ // printf("IMAGE_DEF_REL_BLOCK_OFFSET %08x\n", (uint32_t)&(scan_workarea->parsed_block_loops[0].image_def.core.window_rel_block_offset) - (uint32_t)scan_workarea);
+ #define VERSION_DOWNGRADE_ERASE_ADDR *(uint32_t*)0x400e0338
+ #define TBYB_FLAG_ADDR *(uint32_t*)0x400e0348
+ #define IMAGE_DEF_VERIFIED(scan_workarea) *(uint32_t*)(0x64 + (uint32_t)scan_workarea)
+ #define IMAGE_DEF_TBYB_FLAGGED(scan_workarea) *(bool*)(0x4c + (uint32_t)scan_workarea)
+ #define IMAGE_DEF_BASE(scan_workarea) *(uint32_t*)(0x54 + (uint32_t)scan_workarea)
+ #define IMAGE_DEF_REL_BLOCK_OFFSET(scan_workarea) *(uint32_t*)(0x5c + (uint32_t)scan_workarea)
+#else
+ // Prevent linting errors
+ #define VERSION_DOWNGRADE_ERASE_ADDR *(uint32_t*)NULL
+ #define TBYB_FLAG_ADDR *(uint32_t*)NULL
+ #define IMAGE_DEF_VERIFIED(scan_workarea) *(uint32_t*)(NULL + (uint32_t)scan_workarea)
+ #define IMAGE_DEF_TBYB_FLAGGED(scan_workarea) *(bool*)(NULL + (uint32_t)scan_workarea)
+ #define IMAGE_DEF_BASE(scan_workarea) *(uint32_t*)(NULL + (uint32_t)scan_workarea)
+ #define IMAGE_DEF_REL_BLOCK_OFFSET(scan_workarea) *(uint32_t*)(NULL + (uint32_t)scan_workarea)
+
+ panic_unsupported();
+#endif
+
+ uint32_t flash_update_base = 0;
+ bool tbyb_boot = false;
+ uint32_t saved_erase_addr = 0;
+ if (rom_get_last_boot_type() == BOOT_TYPE_FLASH_UPDATE) {
+ // For a flash update boot, get the flash update base
+ boot_info_t boot_info = {};
+ int ret = rom_get_boot_info(&boot_info);
+ if (ret) {
+ flash_update_base = boot_info.reboot_params[0];
+ if (boot_info.tbyb_and_update_info & BOOT_TBYB_AND_UPDATE_FLAG_BUY_PENDING) {
+ // A buy is pending, so the main software has not been bought
+ tbyb_boot = true;
+ // Save the erase address, as this will be overwritten by rom_pick_ab_partition
+ saved_erase_addr = VERSION_DOWNGRADE_ERASE_ADDR;
+ }
+ }
+ }
+
+ int rc = rom_pick_ab_partition((uint8_t*)workarea_base, workarea_size, partition_a_num, flash_update_base);
+
+ if (IMAGE_DEF_VERIFIED(workarea_base) != RCP_MASK_TRUE) {
+ // Chosen partition failed verification
+ return BOOTROM_ERROR_NOT_FOUND;
+ }
+
+ if (IMAGE_DEF_TBYB_FLAGGED(workarea_base)) {
+ // The chosen partition is TBYB
+ if (tbyb_boot) {
+ // The boot partition is also TBYB - cannot update both, so prioritise boot partition
+ // Restore the erase address saved earlier
+ VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr;
+ return BOOTROM_ERROR_NOT_PERMITTED;
+ } else {
+ // Update the tbyb flash address, so that explicit_buy will clear the flag for the chosen partition
+ TBYB_FLAG_ADDR =
+ IMAGE_DEF_BASE(workarea_base)
+ + IMAGE_DEF_REL_BLOCK_OFFSET(workarea_base) + 4;
+ }
+ } else {
+ // The chosen partition is not TBYB
+ if (tbyb_boot && saved_erase_addr) {
+ // The boot partition was TBYB, and requires an erase
+ if (VERSION_DOWNGRADE_ERASE_ADDR) {
+ // But both the chosen partition requires an erase too
+ // As before, prioritise the boot partition, and restore it's saved erase_address
+ VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr;
+ return BOOTROM_ERROR_NOT_PERMITTED;
+ } else {
+ // The chosen partition doesn't require an erase, so we're fine
+ VERSION_DOWNGRADE_ERASE_ADDR = saved_erase_addr;
+ }
+ }
+ }
+
+ return rc;
+}
#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_bootrom/include/pico/bootrom.h b/src/rp2_common/pico_bootrom/include/pico/bootrom.h
index bb5b8ba2..db2f23d2 100644
--- a/src/rp2_common/pico_bootrom/include/pico/bootrom.h
+++ b/src/rp2_common/pico_bootrom/include/pico/bootrom.h
@@ -749,6 +749,9 @@ static inline int rom_load_partition_table(uint8_t *workarea_base, uint32_t work
*
* NOTE: This method does not look at owner partitions, only the A partition passed and it's corresponding B partition.
*
+ * NOTE: You should not call this method directly when performing a Flash Update Boot before calling `explicit_buy`, as it may prevent
+ * any version downgrade from occuring - instead see \ref rom_pick_ab_update_partition() which wraps this function.
+ *
* \param workarea_base base address of work area
* \param workarea_size size of work area
* \param partition_a_num the A partition of the pair
@@ -1091,6 +1094,30 @@ static inline int rom_get_last_boot_type(void) {
*/
int rom_add_flash_runtime_partition(uint32_t start_offset, uint32_t size, uint32_t permissions);
+/*! \brief Pick A/B partition without disturbing any in progress update or TBYB boot
+ * \ingroup pico_bootrom
+ *
+ * This will call `rom_pick_ab_partition` using the `flash_update_boot_window_base` from the current boot, while performing extra checks to prevent disrupting
+ * a main image TBYB boot. It requires the same minimum workarea size as `rom_pick_ab_partition`.
+ * \see rom_pick_ab_partition()
+ *
+ * For example, if an `explicit_buy` is pending then calling `pick_ab_partition` would normally clear the saved flash erase address for the version downgrade,
+ * so the required erase of the other partition would not occur when `explicit_buy` is called - this function saves and restores that address to prevent this
+ * issue, and returns `BOOTROM_ERROR_NOT_PERMITTED` if the partition chosen by `pick_ab_partition` also requires a flash erase version downgrade (as you can't
+ * erase 2 partitions with one `explicit_buy` call).
+ *
+ * It also checks that the chosen partition contained a valid image (e.g. a signed image when using secure boot), and returns `BOOTROM_ERROR_NOT_FOUND`
+ * if it does not.
+ *
+ * \param workarea_base base address of work area
+ * \param workarea_size size of work area
+ * \param partition_a_num the A partition of the pair
+ * \return >= 0 the partition number picked
+ * BOOTROM_ERROR_NOT_PERMITTED if not possible to do an update correctly, e.g. if both main image and data image are TBYB
+ * BOOTROM_ERROR_NOT_FOUND if the chosen partition failed verification
+ */
+int rom_pick_ab_update_partition(uint32_t *workarea_base, uint32_t workarea_size, uint partition_a_num);
+
#endif
#ifdef __cplusplus
diff --git a/src/rp2_common/pico_btstack/CMakeLists.txt b/src/rp2_common/pico_btstack/CMakeLists.txt
index 010cc9e3..dcfcad4f 100644
--- a/src/rp2_common/pico_btstack/CMakeLists.txt
+++ b/src/rp2_common/pico_btstack/CMakeLists.txt
@@ -308,6 +308,9 @@ if (EXISTS ${PICO_BTSTACK_PATH}/${BTSTACK_TEST_PATH})
find_package (Python3 REQUIRED COMPONENTS Interpreter)
get_filename_component(GATT_NAME "${GATT_FILE}" NAME_WE)
get_filename_component(GATT_PATH "${GATT_FILE}" PATH)
+ if (NOT GATT_PATH)
+ set(GATT_PATH "${CMAKE_CURRENT_LIST_DIR}")
+ endif()
set(TARGET_GATT "${TARGET_LIB}_gatt_header")
set(GATT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated/${TARGET_GATT}")
set(GATT_HEADER "${GATT_BINARY_DIR}/${GATT_NAME}.h")
diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S
index e408b7de..eb477bd1 100644
--- a/src/rp2_common/pico_crt0/crt0.S
+++ b/src/rp2_common/pico_crt0/crt0.S
@@ -23,14 +23,23 @@
pico_default_asm_setup
+#ifdef PICO_NO_STORED_VECTOR_TABLE
+#warning PICO_NO_STORED_VECTOR_TABLE is no longer used. PICO_MINIMAL_STORED_VECTOR_TABLE is not identical but usually serves the same purpose
+#endif
+
.section .vectors, "ax"
.align 2
-.global __vectors, __VECTOR_TABLE
+.global __vectors, __VECTOR_TABLE, __vectors_end
__VECTOR_TABLE:
__vectors:
.word __StackTop
.word _reset_handler
+
+#if PICO_MINIMAL_STORED_VECTOR_TABLE
+.word isr_invalid // NMI
+.word isr_invalid // HardFault
+#else
.word isr_nmi
.word isr_hardfault
.word isr_invalid // Reserved, should never fire
@@ -45,15 +54,9 @@ __vectors:
.word isr_invalid // Reserved, should never fire
.word isr_pendsv
.word isr_systick
-#if PICO_NO_STORED_VECTOR_TABLE && !PICO_NO_FLASH // note in no flash binary, we only have the single RAM vector table anyway
-#if PICO_NO_RAM_VECTOR_TABLE
-#error Can't specify PICO_NO_STORED_VECTOR_TABLE and PICO_NO_RAM_VECTOR_TABLE
-#endif
-// we don't include any IRQ vectors; we will initialize them during runtime_init in the RAM vector table
-#else
.macro if_irq_word num func
-.if \num < NUM_IRQS
+.if \num < PICO_NUM_VTABLE_IRQS
.word \func
.endif
.endm
@@ -142,10 +145,11 @@ if_irq_word 76 isr_irq76
if_irq_word 77 isr_irq77
if_irq_word 78 isr_irq78
if_irq_word 79 isr_irq79
-#if NUM_IRQS > 80
+#if PICO_NUM_VTABLE_IRQS > 80
#error more IRQ entries required
#endif
-#endif
+#endif // #if !PICO_MINIMAL_STORED_VECTOR_TABLE
+__vectors_end:
// all default exception handlers do nothing, and we can check for them being set to our
// default values by seeing if they point to somewhere between __defaults_isrs_start and __default_isrs_end
@@ -164,24 +168,14 @@ __default_isrs_start:
bkpt #0
.endm
-// these are separated out for clarity
-decl_isr_bkpt isr_invalid
-decl_isr_bkpt isr_nmi
-decl_isr_bkpt isr_hardfault
-decl_isr_bkpt isr_svcall
-decl_isr_bkpt isr_pendsv
-decl_isr_bkpt isr_systick
-
-.global __default_isrs_end
-__default_isrs_end:
-
.altmacro
.macro decl_isr name
-#if !PICO_NO_STORED_VECTOR_TABLE | PICO_NO_FLASH
+#if !PICO_MINIMAL_STORED_VECTOR_TABLE | PICO_NO_FLASH
// We declare a weak label, so user can override
.weak \name
#else
-// We declare a strong label, so user can't override (their version would not automatically be used)
+// We declare a strong global label, so user can't override (their version would not automatically be used)
+.global \name
#endif
.type \name,%function
.thumb_func
@@ -189,8 +183,14 @@ __default_isrs_end:
.endm
.macro if_irq_decl num func
-.if \num < NUM_IRQS
+.if \num < PICO_NUM_VTABLE_IRQS
decl_isr \func
+.elseif \num < NUM_IRQS
+// We declare a strong global label, so user can't override (their version would not automatically be used)
+.global \func
+.type \func,%function
+.thumb_func
+\func:
.endif
.endm
@@ -274,7 +274,7 @@ if_irq_decl 76 isr_irq76
if_irq_decl 77 isr_irq77
if_irq_decl 78 isr_irq78
if_irq_decl 79 isr_irq79
-#if NUM_IRQS > 80
+#if PICO_NUM_VTABLE_IRQS > 80
#error more IRQ entries required
#endif
@@ -282,12 +282,30 @@ if_irq_decl 79 isr_irq79
.global __unhandled_user_irq
.thumb_func
__unhandled_user_irq:
+// if we include the implementation if there could be a valid IRQ hanler in the vtable that uses it
+#if !(PICO_NO_RAM_VECTOR_TABLE && PICO_MINIMAL_STORED_VECTOR_TABLE)
mrs r0, ipsr
subs r0, #16
.global unhandled_user_irq_num_in_r0
unhandled_user_irq_num_in_r0:
+#endif
+ // note the next instruction is a breakpoint too, however we have a 2 byte alignment hole
+ // and it is preferrable to have distinct labels, to inform the user what has happened in the debugger.
bkpt #0
+decl_isr_bkpt isr_invalid
+#if !PICO_MINIMAL_STORED_VECTOR_TABLE
+// these are separated out for clarity
+decl_isr_bkpt isr_nmi
+decl_isr_bkpt isr_hardfault
+decl_isr_bkpt isr_svcall
+decl_isr_bkpt isr_pendsv
+decl_isr_bkpt isr_systick
+#endif
+
+.global __default_isrs_end
+__default_isrs_end:
+
// ----------------------------------------------------------------------------
.section .binary_info_header, "a"
diff --git a/src/rp2_common/pico_crt0/crt0_riscv.S b/src/rp2_common/pico_crt0/crt0_riscv.S
index 0e89ab15..e9fc7d94 100644
--- a/src/rp2_common/pico_crt0/crt0_riscv.S
+++ b/src/rp2_common/pico_crt0/crt0_riscv.S
@@ -160,64 +160,22 @@ check_irq_before_exit:
addi sp, sp, 80
mret
+
// Default software vector table for system interrupts, routed through
// mip.meip. Note this is assumed in e.g. hardware_irq to begin exactly 0x34
// words after the hardware vector table indicated by mtvec (defined above).
.p2align 4
.global __soft_vector_table
__soft_vector_table:
-.word isr_irq0
-.word isr_irq1
-.word isr_irq2
-.word isr_irq3
-.word isr_irq4
-.word isr_irq5
-.word isr_irq6
-.word isr_irq7
-.word isr_irq8
-.word isr_irq9
-.word isr_irq10
-.word isr_irq11
-.word isr_irq12
-.word isr_irq13
-.word isr_irq14
-.word isr_irq15
-.word isr_irq16
-.word isr_irq17
-.word isr_irq18
-.word isr_irq19
-.word isr_irq20
-.word isr_irq21
-.word isr_irq22
-.word isr_irq23
-.word isr_irq24
-.word isr_irq25
-.word isr_irq26
-.word isr_irq27
-.word isr_irq28
-.word isr_irq29
-.word isr_irq30
-.word isr_irq31
-.word isr_irq32
-.word isr_irq33
-.word isr_irq34
-.word isr_irq35
-.word isr_irq36
-.word isr_irq37
-.word isr_irq38
-.word isr_irq39
-.word isr_irq40
-.word isr_irq41
-.word isr_irq42
-.word isr_irq43
-.word isr_irq44
-.word isr_irq45
-.word isr_irq46
-.word isr_irq47
-.word isr_irq48
-.word isr_irq49
-.word isr_irq50
-.word isr_irq51
+.macro vtable_irq_n n
+.word isr_irq\n
+.endm
+
+.set IRQN, 0
+.rept PICO_NUM_VTABLE_IRQS
+vtable_irq_n IRQN
+.set IRQN, IRQN + 1
+.endr
// all default trap handlers do nothing, and we can check for them being set to our
// default values by seeing if they point to somewhere between __defaults_isrs_start and __default_isrs_end
@@ -252,58 +210,23 @@ decl_isr isr_riscv_machine_exception
decl_isr_bkpt isr_riscv_machine_timer
decl_isr_bkpt isr_riscv_machine_soft_irq
-decl_isr isr_irq0
-decl_isr isr_irq1
-decl_isr isr_irq2
-decl_isr isr_irq3
-decl_isr isr_irq4
-decl_isr isr_irq5
-decl_isr isr_irq6
-decl_isr isr_irq7
-decl_isr isr_irq8
-decl_isr isr_irq9
-decl_isr isr_irq10
-decl_isr isr_irq11
-decl_isr isr_irq12
-decl_isr isr_irq13
-decl_isr isr_irq14
-decl_isr isr_irq15
-decl_isr isr_irq16
-decl_isr isr_irq17
-decl_isr isr_irq18
-decl_isr isr_irq19
-decl_isr isr_irq20
-decl_isr isr_irq21
-decl_isr isr_irq22
-decl_isr isr_irq23
-decl_isr isr_irq24
-decl_isr isr_irq25
-decl_isr isr_irq26
-decl_isr isr_irq27
-decl_isr isr_irq28
-decl_isr isr_irq29
-decl_isr isr_irq30
-decl_isr isr_irq31
-decl_isr isr_irq32
-decl_isr isr_irq33
-decl_isr isr_irq34
-decl_isr isr_irq35
-decl_isr isr_irq36
-decl_isr isr_irq37
-decl_isr isr_irq38
-decl_isr isr_irq39
-decl_isr isr_irq40
-decl_isr isr_irq41
-decl_isr isr_irq42
-decl_isr isr_irq43
-decl_isr isr_irq44
-decl_isr isr_irq45
-decl_isr isr_irq46
-decl_isr isr_irq47
-decl_isr isr_irq48
-decl_isr isr_irq49
-decl_isr isr_irq50
-decl_isr isr_irq51
+// Declare all the ISR labels
+.macro decl_isr_n n
+.if \n < PICO_NUM_VTABLE_IRQS
+ decl_isr isr_irq\n
+.elseif \n < NUM_IRQS
+ // We declare a strong label, so user can't override, since there is no vtable entry
+ .type isr_irq\n,%function
+ .thumb_func
+ isr_irq\n:
+.endif
+.endm
+
+.set IRQN, 0
+.rept PICO_NUM_VTABLE_IRQS
+decl_isr_n IRQN
+.set IRQN, IRQN + 1
+.endr
// fall through
// All unhandled USER IRQs fall through to here. Note there is no way to get
diff --git a/src/rp2_common/pico_crt0/embedded_start_block.inc.S b/src/rp2_common/pico_crt0/embedded_start_block.inc.S
index 8f1b622d..e4632255 100644
--- a/src/rp2_common/pico_crt0/embedded_start_block.inc.S
+++ b/src/rp2_common/pico_crt0/embedded_start_block.inc.S
@@ -41,7 +41,7 @@ embedded_block:
PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(RISCV) | \
PICOBIN_IMAGE_TYPE_EXE_CHIP_AS_BITS(RP2350) | \
CRT0_TBYB_FLAG
-#elif defined(PICO_RP2040)
+#elif PICO_RP2040
.hword PICOBIN_IMAGE_TYPE_IMAGE_TYPE_AS_BITS(EXE) | \
PICOBIN_IMAGE_TYPE_EXE_SECURITY_AS_BITS(NS) | \
PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(ARM) | \
@@ -84,7 +84,7 @@ embedded_block:
.word SRAM_END // stack pointer
#endif
-#ifndef PICO_RP2040
+#if !PICO_RP2040
#if PICO_NO_FLASH
// If no_flash bin, then include a vector table item
.byte PICOBIN_BLOCK_ITEM_1BS_VECTOR_TABLE
diff --git a/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h
index 46aa0989..5eb43d1b 100644
--- a/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h
+++ b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h
@@ -59,7 +59,7 @@ extern "C" {
*
* As of right now, lwIP is the only supported TCP/IP stack, however the use of \c pico_cyw43_arch is intended to be independent of
* the particular TCP/IP stack used (and possibly Bluetooth stack used) in the future. For this reason, the integration of lwIP
- * is handled in the base (\c pico_cyw43_arch) library based on the #define \ref CYW43_LWIP used by the \c cyw43_driver.
+ * is handled in the base (\c pico_cyw43_arch) library based on the \#define \ref CYW43_LWIP used by the \c cyw43_driver.
*
* \note As of version 1.5.0 of the Raspberry Pi Pico SDK, the \c pico_cyw43_arch library no longer directly implements
* the distinct behavioral abstractions. This is now handled by the more general \ref pico_async_context library. The
@@ -169,7 +169,7 @@ extern "C" {
* \ref cyw43_arch_init_default_async_context, however the user can specify use of their own async_context
* by calling \ref cyw43_arch_set_async_context() before calling this method
*
- * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ * \return 0 if the initialization is successful, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_init(void);
@@ -186,7 +186,7 @@ int cyw43_arch_init(void);
* by calling \ref cyw43_arch_set_async_context() before calling this method
*
* \param country the country code to use (see \ref CYW43_COUNTRY_)
- * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ * \return 0 if the initialization is successful, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_init_with_country(uint32_t country);
@@ -399,7 +399,7 @@ void cyw43_arch_disable_ap_mode(void);
* \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
* \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
*
- * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ * \return 0 if the initialization is successful, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_wifi_connect_blocking(const char *ssid, const char *pw, uint32_t auth);
@@ -413,7 +413,7 @@ int cyw43_arch_wifi_connect_blocking(const char *ssid, const char *pw, uint32_t
* \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
* \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
*
- * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ * \return 0 if the initialization is successful, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_wifi_connect_bssid_blocking(const char *ssid, const uint8_t *bssid, const char *pw, uint32_t auth);
@@ -427,7 +427,7 @@ int cyw43_arch_wifi_connect_bssid_blocking(const char *ssid, const uint8_t *bssi
* \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
* \param timeout how long to wait in milliseconds for a connection to succeed before giving up
*
- * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ * \return 0 if the initialization is successful, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout);
@@ -442,7 +442,7 @@ int cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_
* \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
* \param timeout how long to wait in milliseconds for a connection to succeed before giving up
*
- * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ * \return 0 if the initialization is successful, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_wifi_connect_bssid_timeout_ms(const char *ssid, const uint8_t *bssid, const char *pw, uint32_t auth, uint32_t timeout);
@@ -458,7 +458,7 @@ int cyw43_arch_wifi_connect_bssid_timeout_ms(const char *ssid, const uint8_t *bs
* \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
* \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
*
- * \return 0 if the scan was started successfully, an error code otherwise \see pico_error_codes
+ * \return 0 if the scan was started successfully, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_wifi_connect_async(const char *ssid, const char *pw, uint32_t auth);
@@ -475,7 +475,7 @@ int cyw43_arch_wifi_connect_async(const char *ssid, const char *pw, uint32_t aut
* \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
* \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
*
- * \return 0 if the scan was started successfully, an error code otherwise \see pico_error_codes
+ * \return 0 if the scan was started successfully, an error code otherwise see \ref pico_error_codes
*/
int cyw43_arch_wifi_connect_bssid_async(const char *ssid, const uint8_t *bssid, const char *pw, uint32_t auth);
diff --git a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
index 787eeff5..30b18473 100644
--- a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
+++ b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c
@@ -451,13 +451,6 @@ static inline int _cyw43_write_reg(cyw43_int_t *self, uint32_t fn, uint32_t reg,
uint32_t buf[2];
buf[0] = make_cmd(true, true, fn, reg, size);
buf[1] = val;
- if (fn == BACKPLANE_FUNCTION) {
- // In case of f1 overflow
- self->last_size = 8;
- self->last_header[0] = buf[0];
- self->last_header[1] = buf[1];
- self->last_backplane_window = self->cur_backplane_window;
- }
if (fn == BACKPLANE_FUNCTION) {
logic_debug_set(pin_BACKPLANE_WRITE, 1);
diff --git a/src/rp2_common/pico_divider/divider_hardware.S b/src/rp2_common/pico_divider/divider_hardware.S
index cb3f5416..049c6f75 100644
--- a/src/rp2_common/pico_divider/divider_hardware.S
+++ b/src/rp2_common/pico_divider/divider_hardware.S
@@ -12,21 +12,27 @@
#warning "Building divider_hardware.S on a platform with no SIO divider hardware"
#endif
-// PICO_CONFIG: PICO_DIVIDER_DISABLE_INTERRUPTS, Disable interrupts around division such that divider state need not be saved/restored in exception handlers, default=0, group=pico_divider
+// PICO_CONFIG: PICO_DIVIDER_DISABLE_INTERRUPTS, Disable interrupts around division such that divider state need not be saved/restored in exception handlers, default=0, type=bool, group=pico_divider
+#if 0 // make tooling checks happy
+#define PICO_DIVIDER_DISABLE_INTERRUPTS 0
+#endif
-// PICO_CONFIG: PICO_DIVIDER_CALL_IDIV0, Whether 32 bit division by zero should call __aeabi_idiv0, default=1, group=pico_divider
+// PICO_CONFIG: PICO_DIVIDER_CALL_IDIV0, Whether 32 bit division by zero should call __aeabi_idiv0, default=1, type=bool, group=pico_divider
#ifndef PICO_DIVIDER_CALL_IDIV0
#define PICO_DIVIDER_CALL_IDIV0 1
#endif
-// PICO_CONFIG: PICO_DIVIDER_CALL_IDIV0, Whether 64 bit division by zero should call __aeabi_ldiv0, default=1, group=pico_divider
+// PICO_CONFIG: PICO_DIVIDER_CALL_LDIV0, Whether 64 bit division by zero should call __aeabi_ldiv0, default=1, type=bool, group=pico_divider
#ifndef PICO_DIVIDER_CALL_LDIV0
#define PICO_DIVIDER_CALL_LDIV0 1
#endif
pico_default_asm_setup
-// PICO_CONFIG: PICO_DIVIDER_IN_RAM, Whether divider functions should be placed in RAM, default=0, group=pico_divider
+// PICO_CONFIG: PICO_DIVIDER_IN_RAM, Whether divider functions should be placed in RAM, default=0, type=bool, group=pico_divider
+#if 0 // make tooling checks happy
+#define PICO_DIVIDER_IN_RAM 0
+#endif
.macro div_section name
#if PICO_DIVIDER_IN_RAM
.section RAM_SECTION_NAME(\name), "ax"
diff --git a/src/rp2_common/pico_lwip/CMakeLists.txt b/src/rp2_common/pico_lwip/CMakeLists.txt
index 1a523b78..e412f372 100644
--- a/src/rp2_common/pico_lwip/CMakeLists.txt
+++ b/src/rp2_common/pico_lwip/CMakeLists.txt
@@ -299,8 +299,7 @@ if (EXISTS ${PICO_LWIP_PATH}/${LWIP_TEST_PATH})
pico_mirrored_target_link_libraries(pico_lwip_freertos INTERFACE
pico_async_context_base
pico_lwip
- pico_lwip_contrib_freertos
- pico_rand)
+ pico_lwip_contrib_freertos)
pico_add_subdirectory(tools)
pico_promote_common_scope_vars()
diff --git a/src/rp2_common/pico_multicore/include/pico/multicore.h b/src/rp2_common/pico_multicore/include/pico/multicore.h
index 5eb49ddc..9b4622a9 100644
--- a/src/rp2_common/pico_multicore/include/pico/multicore.h
+++ b/src/rp2_common/pico_multicore/include/pico/multicore.h
@@ -151,7 +151,7 @@ static inline bool multicore_fifo_rvalid(void) {
*
* See the note in the \ref multicore_fifo section for considerations regarding use of the inter-core FIFOs
*
- * @return true if the FIFO has room for more data, false otherwise
+ * \return true if the FIFO has room for more data, false otherwise
*/
static inline bool multicore_fifo_wready(void) {
return sio_hw->fifo_st & SIO_FIFO_ST_RDY_BITS;
@@ -316,7 +316,7 @@ static inline void check_doorbell_num_param(__unused uint doorbell_num) {
*
* \param doorbell_num the doorbell number to claim
* \param core_mask 0b01: core 0, 0b10: core 1, 0b11 both core 0 and core 1
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
void multicore_doorbell_claim(uint doorbell_num, uint core_mask);
@@ -328,7 +328,7 @@ void multicore_doorbell_claim(uint doorbell_num, uint core_mask);
* \param core_mask 0b01: core 0, 0b10: core 1, 0b11 both core 0 and core 1
* \param required if true the function will panic if none are available
* \return the doorbell number claimed or -1 if required was false, and none are available
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
int multicore_doorbell_claim_unused(uint core_mask, bool required);
@@ -337,7 +337,7 @@ int multicore_doorbell_claim_unused(uint core_mask, bool required);
*
* \param doorbell_num the doorbell number to unclaim
* \param core_mask 0b01: core 0, 0b10: core 1, 0b11 both core 0 and core 1
- * \sa hardware_claiming
+ * \sa hardware_claim
*/
void multicore_doorbell_unclaim(uint doorbell_num, uint core_mask);
diff --git a/src/rp2_common/pico_platform_common/BUILD.bazel b/src/rp2_common/pico_platform_common/BUILD.bazel
new file mode 100644
index 00000000..18a373a5
--- /dev/null
+++ b/src/rp2_common/pico_platform_common/BUILD.bazel
@@ -0,0 +1,25 @@
+load("//bazel:defs.bzl", "compatible_with_rp2")
+
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "pico_platform_common_headers",
+ hdrs = ["include/pico/platform/common.h"],
+ includes = ["include"],
+ visibility = [
+ "//src/rp2040/pico_platform:__pkg__",
+ "//src/rp2350/pico_platform:__pkg__",
+ ],
+)
+
+cc_library(
+ name = "pico_platform_common",
+ srcs = ["common.c"],
+ target_compatible_with = compatible_with_rp2(),
+ deps = [
+ ":pico_platform_common_headers",
+ "//src/rp2_common:platform_defs",
+ "//src/rp2_common/hardware_base",
+ "//src/common/pico_base_headers",
+ ],
+)
diff --git a/src/rp2_common/pico_platform_common/CMakeLists.txt b/src/rp2_common/pico_platform_common/CMakeLists.txt
new file mode 100644
index 00000000..8e6da4e1
--- /dev/null
+++ b/src/rp2_common/pico_platform_common/CMakeLists.txt
@@ -0,0 +1,8 @@
+if (NOT TARGET pico_platform_common)
+ pico_add_library(pico_platform_common)
+ target_sources(pico_platform_common INTERFACE ${CMAKE_CURRENT_LIST_DIR}/common.c)
+
+ target_include_directories(pico_platform_common_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
+
+ target_link_libraries(pico_platform_common_headers INTERFACE hardware_regs)
+endif()
diff --git a/src/rp2_common/pico_platform_common/common.c b/src/rp2_common/pico_platform_common/common.c
new file mode 100644
index 00000000..af5bf183
--- /dev/null
+++ b/src/rp2_common/pico_platform_common/common.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico.h"
+#include "hardware/address_mapped.h"
+#include "hardware/regs/tbman.h"
+
+// Note we leave the FPGA check in by default so that we can run bug repro
+// binaries coming in from the wild on the FPGA platform. It takes up around
+// 48 bytes if you include all the calls, so you can pass PICO_NO_FPGA_CHECK=1
+// to remove it. The FPGA check is used to skip initialisation of hardware
+// (mainly clock generators and oscillators) that aren't present on FPGA.
+
+#if !PICO_NO_FPGA_CHECK
+// Inline stub provided in header if this code is unused (so folding can be
+// done in each TU instead of relying on LTO)
+bool __attribute__((weak)) running_on_fpga(void) {
+ return (*(io_ro_32 *)TBMAN_BASE) & TBMAN_PLATFORM_FPGA_BITS;
+}
+#endif
+
+#if !PICO_NO_SIM_CHECK
+bool __attribute__((weak)) running_in_sim(void) {
+ return (*(io_ro_32 *)TBMAN_BASE) & TBMAN_PLATFORM_HDLSIM_BITS;
+}
+#endif
+
diff --git a/src/rp2_common/pico_platform_common/include/pico/platform/common.h b/src/rp2_common/pico_platform_common/include/pico/platform/common.h
new file mode 100644
index 00000000..c4645d6e
--- /dev/null
+++ b/src/rp2_common/pico_platform_common/include/pico/platform/common.h
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2025 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PICO_PLATFORM_COMMON_H
+#define _PICO_PLATFORM_COMMON_H
+
+/** \file pico/platform/common.h
+ * \ingroup pico_platform
+ *
+ * \brief Macros and definitions common to all rp2 platforms but not specific to any library
+ *
+ * This header may be included by assembly code
+ *
+ * Note certain library specific defines are defined here when they are interdpedent across libraries,
+ * but making an explicit library dependency does not make sense.
+ */
+
+// PICO_CONFIG: PICO_MINIMAL_STORED_VECTOR_TABLE, Only store a very minimal vector table in the binary on Arm, type=bool, default=0, advanced=true, group=pico_crt0
+#ifndef PICO_MINIMAL_STORED_VECTOR_TABLE
+#define PICO_MINIMAL_STORED_VECTOR_TABLE 0
+#endif
+
+#if PICO_MINIMAL_STORED_VECTOR_TABLE && (PICO_NO_FLASH && !defined(__riscv))
+#if PICO_NUM_VTABLE_IRQS
+#warning PICO_NUM_VTABLE_IRQS is specied with PICO_MINIMAL_STORED_VECTOR_TABLE for NO_FLASH Arm binary; ignored
+#undef PICO_NUM_VTABLE_IRQS
+#endif
+#define PICO_NUM_VTABLE_IRQS 0
+#else
+// PICO_CONFIG: PICO_NUM_VTABLE_IRQS, Number of IRQ handlers in the vector table - can be lowered to save space if you aren't using some higher IRQs, type=int, default=NUM_IRQS, group=hardware_irq
+#ifndef PICO_NUM_VTABLE_IRQS
+#define PICO_NUM_VTABLE_IRQS NUM_IRQS
+#endif
+#endif
+
+#ifndef __ASSEMBLER__
+
+// PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
+#ifndef PICO_NO_FPGA_CHECK
+#define PICO_NO_FPGA_CHECK 1
+#endif
+
+// PICO_CONFIG: PICO_NO_SIM_CHECK, Remove the SIM platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
+#ifndef PICO_NO_SIM_CHECK
+#define PICO_NO_SIM_CHECK 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if PICO_NO_FPGA_CHECK
+static inline bool running_on_fpga(void) {return false;}
+#else
+bool running_on_fpga(void);
+#endif
+
+#if PICO_NO_SIM_CHECK
+static inline bool running_in_sim(void) {return false;}
+#else
+bool running_in_sim(void);
+#endif
+
+/*! \brief No-op function for the body of tight loops
+ * \ingroup pico_platform
+ *
+ * No-op function intended to be called by any tight hardware polling loop. Using this ubiquitously
+ * makes it much easier to find tight loops, but also in the future \#ifdef-ed support for lockup
+ * debugging might be added
+ */
+static __force_inline void tight_loop_contents(void) {}
+
+#define host_safe_hw_ptr(x) ((uintptr_t)(x))
+#define native_safe_hw_ptr(x) host_safe_hw_ptr(x)
+
+#ifdef __cplusplus
+}
+#endif
+#endif // __ASSEMBLER__
+
+
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h b/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h
index 486758be..7f24008a 100644
--- a/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h
+++ b/src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h
@@ -7,8 +7,8 @@
#ifndef _PICO_PLATFORM_COMPILER_H
#define _PICO_PLATFORM_COMPILER_H
-/** \file platform_compiler.h
- * \defgroup pico_platform pico_platform
+/** \file pico/platform/compiler.h
+ * \ingroup pico_platform
*
* \brief Macros and definitions (and functions when included by non assembly code) to adapt for different compilers
*
diff --git a/src/rp2_common/pico_rand/include/pico/rand.h b/src/rp2_common/pico_rand/include/pico/rand.h
index b0a337f2..e3bbe2df 100644
--- a/src/rp2_common/pico_rand/include/pico/rand.h
+++ b/src/rp2_common/pico_rand/include/pico/rand.h
@@ -25,7 +25,7 @@ extern "C" {
* The random numbers (32 to 128 bit) to be supplied are read from the PRNG which is used
* to help provide a large number space.
*
- * The following (multiple) sources of entropy are available (of varying quality), each enabled by a #define:
+ * The following (multiple) sources of entropy are available (of varying quality), each enabled by a \#define:
*
* - The Ring Oscillator (ROSC) (\ref PICO_RAND_ENTROPY_SRC_ROSC == 1):
* \ref PICO_RAND_ROSC_BIT_SAMPLE_COUNT bits are gathered from the ring oscillator "random bit" and mixed in each
@@ -47,7 +47,7 @@ extern "C" {
* - Time (\ref PICO_RAND_SEED_ENTROPY_SRC_TIME == 1): The 64-bit microsecond timer is mixed into the seed.
* - Board Identifier (PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID == 1): The board id via \ref pico_get_unique_board_id
* is mixed into the seed.
- * - RAM hash (\ref PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH (\ref PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH): The hashed contents of a
+ * - RAM hash (\ref PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH): The hashed contents of a
* subset of RAM are mixed in. Initial RAM contents are undefined on power up, so provide a reasonable source of entropy.
* By default the last 1K of RAM (which usually contains the core 0 stack) is hashed, which may also provide for differences
* after each warm reset.
diff --git a/src/rp2_common/pico_runtime_init/runtime_init.c b/src/rp2_common/pico_runtime_init/runtime_init.c
index 2b69c806..2e1ce89f 100644
--- a/src/rp2_common/pico_runtime_init/runtime_init.c
+++ b/src/rp2_common/pico_runtime_init/runtime_init.c
@@ -195,23 +195,32 @@ PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_spin_locks_reset, PICO_RUNTIME_INIT_
// RISC-V to have an initial flash-resident vector table at a well-known
// location, unlike Cortex-M which can take an NMI on cycle 0.
#ifndef __riscv
+#include "hardware/structs/scb.h"
+#include "hardware/irq.h"
#if !PICO_RUNTIME_NO_INIT_INSTALL_RAM_VECTOR_TABLE
-uint32_t __attribute__((section(".ram_vector_table"))) ram_vector_table[PICO_RAM_VECTOR_TABLE_SIZE];
-
-#include "hardware/structs/scb.h"
-void runtime_init_install_ram_vector_table(void) {
- // Note on RISC-V the RAM vector table is initialised during crt0
-#if !(PICO_NO_RAM_VECTOR_TABLE || PICO_NO_FLASH) && !defined(__riscv)
-#if !PICO_NO_STORED_VECTOR_TABLE
- __builtin_memcpy(ram_vector_table, (uint32_t *) scb_hw->vtor, sizeof(ram_vector_table));
-#else
- __builtin_memcpy(ram_vector_table, (uint32_t *) scb_hw->vtor, MIN(VTABLE_FIRST_IRQ, sizeof(ram_vector_table)));
- for(uint i = VTABLE_FIRST_IRQ; ivtor = (uintptr_t) ram_vector_table;
#endif
}
diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt
index a428eb69..53eaa84f 100644
--- a/src/rp2_common/pico_standard_link/CMakeLists.txt
+++ b/src/rp2_common/pico_standard_link/CMakeLists.txt
@@ -30,6 +30,7 @@ if (NOT TARGET pico_standard_link)
set_target_properties(${TARGET} PROPERTIES PICO_TARGET_BINARY_TYPE ${TYPE})
endfunction()
+ # slightly messy as we support both the preferred PICO_DEFAULT_BINARY_TYPE and the individual variables
if (NOT PICO_DEFAULT_BINARY_TYPE)
if (PICO_NO_FLASH)
set(PICO_DEFAULT_BINARY_TYPE no_flash)
@@ -40,6 +41,23 @@ if (NOT TARGET pico_standard_link)
else()
set(PICO_DEFAULT_BINARY_TYPE default)
endif()
+ else()
+ # we must set the individual variables here, as they are used in generator expressions,
+ # but also for our checks below
+ if (PICO_DEFAULT_BINARY_TYPE STREQUAL no_flash)
+ set(PICO_NO_FLASH 1)
+ endif()
+ if (PICO_DEFAULT_BINARY_TYPE STREQUAL blocked_ram)
+ set(PICO_USE_BLOCKED_RAM 1)
+ endif()
+ if (PICO_DEFAULT_BINARY_TYPE STREQUAL copy_to_ram)
+ set(PICO_COPY_TO_RAM 1)
+ endif()
+ endif()
+ if ((PICO_NO_FLASH AND PICO_USE_BLOCKED_RAM) OR
+ (PICO_USE_BLOCKED_RAM AND PICO_COPY_TO_RAM) OR
+ (PICO_COPY_TO_RAM AND PICO_NO_FLASH))
+ message(FATAL_ERROR "Conflicting binary types specified amongst PICO_DEFAULT_BINARY_TYPE, PICO_NO_FLASH, PICO_USE_BLOCKED_RAM and PICO_COPY_TO_RAM")
endif()
# todo only needed if not using a custom linker script
diff --git a/src/rp2_common/pico_stdio_usb/BUILD.bazel b/src/rp2_common/pico_stdio_usb/BUILD.bazel
index be950655..1e881714 100644
--- a/src/rp2_common/pico_stdio_usb/BUILD.bazel
+++ b/src/rp2_common/pico_stdio_usb/BUILD.bazel
@@ -24,6 +24,9 @@ cc_library(
hdrs = ["include/tusb_config.h"],
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
+ deps = [
+ ":pico_stdio_usb_headers",
+ ],
)
pico_sdk_define(
@@ -43,10 +46,6 @@ cc_library(
hdrs = ["include/pico/stdio_usb.h"],
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
- visibility = [
- ":__pkg__",
- "//src/rp2_common/tinyusb:__pkg__",
- ],
deps = [
":LIB_PICO_STDIO_USB",
":PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS",
diff --git a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
index b1cb0354..9e6575a3 100644
--- a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
+++ b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
@@ -44,10 +44,30 @@
// this variable is no longer set by default (one is claimed dynamically), but will be respected if specified
#endif
+// PICO_CONFIG: PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK, Enable/disable the use of a background task to call tud_task(), type=bool, default=1 if the application is not using tinyUSB directly, group=pico_stdio_usb
+#ifndef PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK
+#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE
+#define PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK 1
+#else
+#define PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK 0
+#endif
+#endif
+
+// PICO_CONFIG: PICO_STDIO_USB_ENABLE_TINYUSB_INIT, Enable/disable calling tinyUSB tusb_init() during initialization, type=bool, default=1 if the application is not using tinyUSB directly, group=pico_stdio_usb
+#ifndef PICO_STDIO_USB_ENABLE_TINYUSB_INIT
+#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE
+#define PICO_STDIO_USB_ENABLE_TINYUSB_INIT 1
+#else
+#define PICO_STDIO_USB_ENABLE_TINYUSB_INIT 0
+#endif
+#endif
+
// PICO_CONFIG: PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE, Enable/disable resetting into BOOTSEL mode if the host sets the baud rate to a magic value (PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE), type=bool, default=1 if application is not using TinyUSB directly, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE
-#if !defined(LIB_TINYUSB_HOST) && !defined(LIB_TINYUSB_DEVICE)
+#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE
#define PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE 1
+#else
+#define PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE 0
#endif
#endif
@@ -91,8 +111,10 @@
// PICO_CONFIG: PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE, Enable/disable resetting into BOOTSEL mode via an additional VENDOR USB interface - enables picotool based reset, type=bool, default=1 if application is not using TinyUSB directly, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE
-#if !defined(LIB_TINYUSB_HOST) && !defined(LIB_TINYUSB_DEVICE)
+#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE
#define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE 1
+#else
+#define PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE 0
#endif
#endif
@@ -116,6 +138,15 @@
#define PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS 100
#endif
+// PICO_CONFIG: PICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS, Defines the default USB descriptors needed for USB communication, type=bool, default=1 if the application is not using tinyUSB directly, group=pico_stdio_usb
+#ifndef PICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS
+#if !LIB_TINYUSB_HOST && !LIB_TINYUSB_DEVICE
+#define PICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS 1
+#else
+#define PICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS 0
+#endif
+#endif
+
// PICO_CONFIG: PICO_STDIO_USB_CONNECTION_WITHOUT_DTR, Disable use of DTR for connection checking meaning connection is assumed to be valid, type=bool, default=0, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_CONNECTION_WITHOUT_DTR
#define PICO_STDIO_USB_CONNECTION_WITHOUT_DTR 0
@@ -161,6 +192,19 @@ bool stdio_usb_deinit(void);
* \return true if stdio is connected over CDC
*/
bool stdio_usb_connected(void);
+
+#if PICO_STDIO_USB_SUPPORT_CHARS_AVAILABLE_CALLBACK
+/*! \brief Explicitly calls the registered USB stdio chars_available_callback
+ * \ingroup pico_stdio_usb
+ *
+ * This method is normally called by the internal USB stdio background thread when there is new USB CDC
+ * data available to read. However, if the internal background thread is disabled (e.g. when the user
+ * directly links tinyUSB), the user will need to implement their own background thread and call this
+ * method directly.
+ */
+void stdio_usb_call_chars_available_callback(void);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/rp2_common/pico_stdio_usb/stdio_usb.c b/src/rp2_common/pico_stdio_usb/stdio_usb.c
index 0f9e3188..61aa7089 100644
--- a/src/rp2_common/pico_stdio_usb/stdio_usb.c
+++ b/src/rp2_common/pico_stdio_usb/stdio_usb.c
@@ -26,8 +26,7 @@ static void (*chars_available_callback)(void*);
static void *chars_available_param;
#endif
-// when tinyusb_device is explicitly linked we do no background tud processing
-#if !LIB_TINYUSB_DEVICE
+#if PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK
// if this crit_sec is initialized, we are not in periodic timer mode, and must make sure
// we don't either create multiple one shot timers, or miss creating one. this crit_sec
// is used to protect the one_shot_timer_pending flag
@@ -171,6 +170,12 @@ void stdio_usb_set_chars_available_callback(void (*fn)(void*), void *param) {
chars_available_callback = fn;
chars_available_param = param;
}
+
+void stdio_usb_call_chars_available_callback(void) {
+ if (chars_available_callback) {
+ chars_available_callback(chars_available_param);
+ }
+}
#endif
stdio_driver_t stdio_usb = {
@@ -197,8 +202,8 @@ bool stdio_usb_init(void) {
bi_decl_if_func_used(bi_program_feature("USB stdin / stdout"));
#endif
-#if !defined(LIB_TINYUSB_DEVICE)
- // initialize TinyUSB, as user hasn't explicitly linked it
+#if PICO_STDIO_USB_ENABLE_TINYUSB_INIT
+ // initialize TinyUSB
tusb_init();
#else
assert(tud_inited()); // we expect the caller to have initialized if they are using TinyUSB
@@ -206,7 +211,7 @@ bool stdio_usb_init(void) {
if (!mutex_is_initialized(&stdio_usb_mutex)) mutex_init(&stdio_usb_mutex);
bool rc = true;
-#if !LIB_TINYUSB_DEVICE
+#if PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK
#ifdef PICO_STDIO_USB_LOW_PRIORITY_IRQ
user_irq_claim(PICO_STDIO_USB_LOW_PRIORITY_IRQ);
#else
@@ -265,7 +270,7 @@ bool stdio_usb_deinit(void) {
sleep_ms(PICO_STDIO_USB_DEINIT_DELAY_MS);
#endif
-#if !LIB_TINYUSB_DEVICE
+#if PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK
if (irq_has_shared_handler(USBCTRL_IRQ)) {
spin_lock_unclaim(spin_lock_get_num(one_shot_timer_crit_sec.spin_lock));
critical_section_deinit(&one_shot_timer_crit_sec);
diff --git a/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c b/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c
index 2f6e7587..b805e8fb 100644
--- a/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c
+++ b/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c
@@ -26,11 +26,12 @@
* THE SOFTWARE.
*/
-#if !defined(LIB_TINYUSB_HOST) && !defined(LIB_TINYUSB_DEVICE)
-
-#include "tusb.h"
+#include "pico/stdio_usb.h"
#include "pico/stdio_usb/reset_interface.h"
#include "pico/unique_id.h"
+#include "tusb.h"
+
+#if PICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS
#ifndef USBD_VID
#define USBD_VID (0x2E8A) // Raspberry Pi
diff --git a/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h b/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h
index 639e9149..9392fe77 100644
--- a/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h
+++ b/src/rp2_common/pico_time_adapter/include/pico/time_adapter.h
@@ -80,7 +80,7 @@ static inline void ta_disable_irq_handler(alarm_pool_timer_t *timer, uint alarm_
hw_clear_bits(&timer_hw_from_timer(timer)->inte, 1u << alarm_num);
irq_set_enabled(irq_num, true);
irq_remove_handler(irq_num, irq_handler);
- hardware_alarm_unclaim(alarm_num);
+ timer_hardware_alarm_unclaim(timer, alarm_num);
}
static inline void ta_hardware_alarm_claim(alarm_pool_timer_t *timer, uint hardware_alaram_num) {
diff --git a/src/rp2_common/pico_unique_id/include/pico/unique_id.h b/src/rp2_common/pico_unique_id/include/pico/unique_id.h
index 367d32bf..9f91733d 100644
--- a/src/rp2_common/pico_unique_id/include/pico/unique_id.h
+++ b/src/rp2_common/pico_unique_id/include/pico/unique_id.h
@@ -41,6 +41,28 @@ extern "C" {
#define PICO_UNIQUE_BOARD_ID_SIZE_BYTES 8
+/**
+ * \brief Static initialization order
+ * \ingroup pico_unique_id
+ *
+ * This defines the init_priority of the pico_unique_id. By default, it is 1000. The valid range is
+ * from 101-65535. Set it to -1 to set the priority to none, thus putting it after 65535. Changing
+ * this value will initialize the unique_id earlier or later in the static initialization order.
+ * This is most useful for C++ consumers of the pico-sdk.
+ *
+ * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-constructor-function-attribute
+ * and https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-init_005fpriority-variable-attribute
+ *
+ * Here is an example of C++ static initializers that will run before, and then after, pico_unique_id is loaded:
+ *
+ * [[gnu::init_priority(500)]] my_class before_instance;
+ * [[gnu::init_priority(2000)]] my_class after_instance;
+ *
+ */
+#ifndef PICO_UNIQUE_BOARD_ID_INIT_PRIORITY
+#define PICO_UNIQUE_BOARD_ID_INIT_PRIORITY 1000
+#endif
+
/**
* \brief Unique board identifier
* \ingroup pico_unique_id
diff --git a/src/rp2_common/pico_unique_id/unique_id.c b/src/rp2_common/pico_unique_id/unique_id.c
index c027bf27..28204eda 100644
--- a/src/rp2_common/pico_unique_id/unique_id.c
+++ b/src/rp2_common/pico_unique_id/unique_id.c
@@ -12,7 +12,13 @@ static_assert(PICO_UNIQUE_BOARD_ID_SIZE_BYTES <= FLASH_UNIQUE_ID_SIZE_BYTES, "Bo
static pico_unique_board_id_t retrieved_id;
-static void __attribute__((constructor)) _retrieve_unique_id_on_boot(void) {
+#if PICO_UNIQUE_BOARD_ID_INIT_PRIORITY == -1
+#define PICO_UNIQUE_BOARD_ID_INIT_ATTRIBUTES constructor
+#else
+#define PICO_UNIQUE_BOARD_ID_INIT_ATTRIBUTES constructor(PICO_UNIQUE_BOARD_ID_INIT_PRIORITY)
+#endif
+
+static void __attribute__((PICO_UNIQUE_BOARD_ID_INIT_ATTRIBUTES)) _retrieve_unique_id_on_boot(void) {
#if PICO_RP2040
#if PICO_NO_FLASH
// The hardware_flash call will panic() if called directly on a NO_FLASH
diff --git a/src/rp2_common/tinyusb/BUILD.bazel b/src/rp2_common/tinyusb/BUILD.bazel
index 4accbb5e..fcc0405a 100644
--- a/src/rp2_common/tinyusb/BUILD.bazel
+++ b/src/rp2_common/tinyusb/BUILD.bazel
@@ -15,6 +15,7 @@ cc_library(
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
+ "//bazel/config:PICO_TINYUSB_CONFIG",
"//src/common/pico_binary_info",
"//src/common/pico_stdlib_headers",
"//src/common/pico_sync",
@@ -30,7 +31,6 @@ cc_library(
"//src/rp2_common/pico_stdio_semihosting",
"//src/rp2_common/pico_stdio_uart",
"//src/rp2_common/pico_stdio_usb:pico_stdio_usb_headers",
- "//src/rp2_common/pico_stdio_usb:tusb_config",
"//src/rp2_common/pico_unique_id",
],
)
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index c2fbe328..7d68c910 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -153,6 +153,28 @@ function(picotool_check_configurable TARGET)
endif()
endfunction()
+# Compare 2 key files, used by picotool_check_default_keys
+function(picotool_compare_keys TARGET KEY DEFAULT TYPE)
+ if (KEY)
+ execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files "${KEY}" "${PICO_SDK_PATH}/tools/example_keys/${DEFAULT}"
+ RESULT_VARIABLE compare_result
+ )
+ if(compare_result EQUAL 0)
+ message(WARNING "${TARGET} is using a default ${TYPE} key - this must be changed before production")
+ endif()
+ endif()
+endfunction()
+
+# Check if default signing/encryption keys are being used
+function(picotool_check_default_keys TARGET)
+ get_target_property(picotool_sigfile ${TARGET} PICOTOOL_SIGFILE)
+ picotool_compare_keys(${TARGET} ${picotool_sigfile} private.pem "signing")
+ get_target_property(picotool_aesfile ${TARGET} PICOTOOL_AESFILE)
+ picotool_compare_keys(${TARGET} ${picotool_aesfile} privateaes.bin "encryption")
+ get_target_property(picotool_enc_sigfile ${TARGET} PICOTOOL_ENC_SIGFILE)
+ picotool_compare_keys(${TARGET} ${picotool_enc_sigfile} private.pem "encrypted signing")
+endfunction()
+
# Generate pio header and include it in the build
# PICO_CMAKE_CONFIG: PICO_DEFAULT_PIOASM_OUTPUT_FORMAT, Default output format used by pioasm when using pico_generate_pio_header, type=string, default=c-sdk, group=build
function(pico_generate_pio_header TARGET)
@@ -449,6 +471,12 @@ function(picotool_postprocess_binary TARGET)
set_target_properties(${TARGET} PROPERTIES
PICOTOOL_PROCESSING_CONFIGURED true
)
+
+ # PICO_CMAKE_CONFIG: PICO_ALLOW_EXAMPLE_KEYS, Don't raise a warning when using default signing/encryption keys, type=bool, default=0, group=build
+ if (NOT PICO_ALLOW_EXAMPLE_KEYS)
+ picotool_check_default_keys(${TARGET})
+ endif()
+
# Read target properties
get_target_property(picotool_sign_output ${TARGET} PICOTOOL_SIGN_OUTPUT)
if (picotool_sign_output)
diff --git a/tools/build_all_headers.py b/tools/build_all_headers.py
index fc047d99..a3e4f04b 100755
--- a/tools/build_all_headers.py
+++ b/tools/build_all_headers.py
@@ -24,11 +24,15 @@ IGNORE_DIRS.add('common/pico_usb_reset_interface')
IGNORE_DIRS.add('rp2_common/cmsis')
IGNORE_DIRS.add('rp2_common/pico_async_context')
IGNORE_DIRS.add('rp2_common/pico_btstack')
-IGNORE_DIRS.add('rp2_common/pico_cyw43_arch')
+#IGNORE_DIRS.add('rp2_common/pico_cyw43_arch')
IGNORE_DIRS.add('rp2_common/pico_cyw43_driver')
IGNORE_DIRS.add('rp2_common/pico_lwip')
IGNORE_DIRS.add('rp2_common/pico_stdio_semihosting')
IGNORE_DIRS.add('rp2_common/pico_stdio_usb')
+IGNORE_DIRS.add('rp2_common/pico_clib_interface')
+IGNORE_DIRS.add('rp2_common/pico_mbedtls')
+
+SORT_HEADERS_BY_DIRECTORY = True # if False, sort by filename
if len(sys.argv) != 3:
print("Usage: {} top_dir output_header".format(os.path.basename(sys.argv[0])))
@@ -54,7 +58,12 @@ for root, dirs, files in os.walk(top_dir):
include_dirs.add(os.path.join(root, 'include'))
dirs.remove('include')
-include_files = list()
+include_files_by_chip = {
+ 'none': list(),
+ 'rp2040': list(),
+ 'rp2350': list(),
+}
+all_include_files = set()
include_locations = dict()
for d in sorted(include_dirs):
for root, dirs, files in os.walk(d):
@@ -62,13 +71,30 @@ for d in sorted(include_dirs):
if f.endswith('.h'):
include_file = os.path.relpath(os.path.join(root, f), d)
include_path = os.path.relpath(d, top_dir)
- if include_file in include_files:
- raise Exception("Duplicate include file '{}' (found in both {} and {})".format(include_file, include_locations[include_file], include_path))
- include_files.append(include_file)
+ if 'rp2040/' in include_path:
+ include_files_by_chip['rp2040'].append(include_file)
+ elif 'rp2350/' in include_path:
+ include_files_by_chip['rp2350'].append(include_file)
+ else:
+ if include_file in include_files_by_chip['none']:
+ raise Exception("Duplicate include file '{}' (found in both {} and {})".format(include_file, include_locations[include_file], include_path))
+ include_files_by_chip['none'].append(include_file)
include_locations[include_file] = include_path
+ all_include_files.add(include_file)
-with open(output_header, 'w') as fh:
- fh.write('''/*
+# figure out which includes are applicable to both chips
+include_files_by_chip['both'] = []
+for f in include_files_by_chip['rp2040']:
+ if f in include_files_by_chip['rp2350']:
+ include_files_by_chip['both'].append(f)
+ include_locations[f] = include_locations[f].replace('rp2350/', 'rp2xxx/')
+for f in include_files_by_chip['both']:
+ include_files_by_chip['rp2040'].remove(f)
+ include_files_by_chip['rp2350'].remove(f)
+
+if SORT_HEADERS_BY_DIRECTORY:
+ with open(output_header, 'w') as fh:
+ fh.write('''/*
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -77,11 +103,61 @@ with open(output_header, 'w') as fh:
// This file is autogenerated, do not edit by hand
''')
- last_location = ''
- for f in include_files:
- if include_locations[f] != last_location:
- fh.write('\n// {}\n'.format(include_locations[f]))
- fh.write('#include "{}"\n'.format(f))
- last_location = include_locations[f]
- fh.write('\n')
+ last_location = ''
+ for f in include_files_by_chip['none']:
+ if include_locations[f] != last_location:
+ fh.write('\n// {}\n'.format(include_locations[f]))
+ fh.write('#include "{}"\n'.format(f))
+ last_location = include_locations[f]
+ for f in include_files_by_chip['both']:
+ if include_locations[f] != last_location:
+ fh.write('\n// {}\n'.format(include_locations[f]))
+ fh.write('#include "{}"\n'.format(f))
+ last_location = include_locations[f]
+ if include_files_by_chip['rp2040']:
+ fh.write('\n#if PICO_RP2040\n')
+ for f in include_files_by_chip['rp2040']:
+ if include_locations[f] != last_location:
+ fh.write('\n// {}\n'.format(include_locations[f]))
+ fh.write('#include "{}"\n'.format(f))
+ last_location = include_locations[f]
+ fh.write('\n#endif\n')
+ if include_files_by_chip['rp2350']:
+ fh.write('\n#if PICO_RP2350\n')
+ for f in include_files_by_chip['rp2350']:
+ if include_locations[f] != last_location:
+ fh.write('\n// {}\n'.format(include_locations[f]))
+ fh.write('#include "{}"\n'.format(f))
+ last_location = include_locations[f]
+ fh.write('\n#endif\n')
+ fh.write('\n')
+else:
+ with open(output_header, 'w') as fh:
+ fh.write('''/*
+ * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// This file is autogenerated, do not edit by hand
+
+''')
+ last_define = None
+ for f in sorted(all_include_files, key=lambda x: os.path.split(x)):
+ if f in include_files_by_chip['rp2040']:
+ define = 'PICO_RP2040'
+ elif f in include_files_by_chip['rp2350']:
+ define = 'PICO_RP2350'
+ else:
+ define = None
+ if define != last_define:
+ if last_define is not None:
+ fh.write('#endif\n')
+ if define is not None:
+ fh.write('#if {}\n'.format(define))
+ fh.write('#include "{}"\n'.format(f))
+ last_define = define
+ if last_define is not None:
+ fh.write('#endif\n')
+ fh.write('\n')
diff --git a/tools/check_board_header.py b/tools/check_board_header.py
index c259c813..3bfce1c5 100755
--- a/tools/check_board_header.py
+++ b/tools/check_board_header.py
@@ -196,6 +196,7 @@ def read_defines_from(header_file, defines_dict):
if board_header_basename == "amethyst_fpga.h":
defines['PICO_RP2350'] = DefineType('PICO_RP2350', 1, 1, -1)
+ defines['PICO_RP2350A'] = DefineType('PICO_RP2350A', 0, 0, -1)
with open(board_header) as header_fh:
last_ifndef = None
@@ -347,7 +348,7 @@ with open(board_header) as header_fh:
raise Exception("{}:{} Include-guard #define {} is missing an #ifndef".format(board_header, lineno, name))
if value:
raise Exception("{}:{} Include-guard #define {} shouldn't have a value".format(board_header, lineno, name))
- if len(defines) and not (len(defines) == 1 and defines[list(defines.keys())[0]].lineno < 0):
+ if any(defines[d].lineno >= 0 for d in defines):
raise Exception("{}:{} Include-guard #define {} should be the first define".format(board_header, lineno, name))
if name == expected_include_guard:
has_include_guard = True
@@ -387,10 +388,15 @@ else:
other_chip = 'RP2350'
elif cmake_settings['PICO_PLATFORM'].value == "rp2350":
other_chip = 'RP2040'
- if 'PICO_RP2350A' in defines and defines['PICO_RP2350A'].resolved_value == 1:
- chip = 'RP2350A'
+ if 'PICO_RP2350B' in defines:
+ raise Exception("{} sets #define {} {} (should probably be #define {} {})".format(board_header, 'PICO_RP2350B', defines['PICO_RP2350B'].resolved_value, 'PICO_RP2350A', 1 - defines['PICO_RP2350B'].resolved_value))
+ if 'PICO_RP2350A' not in defines:
+ raise Exception("{} has no #define for {} (set to 1 for RP2350A, or 0 for RP2350B)".format(board_header, 'PICO_RP2350A'))
else:
- chip = 'RP2350B'
+ if defines['PICO_RP2350A'].resolved_value == 1:
+ chip = 'RP2350A'
+ else:
+ chip = 'RP2350B'
if not board_header.endswith("amethyst_fpga.h"):
if 'PICO_RP2350_A2_SUPPORTED' not in cmake_default_settings:
raise Exception("{} uses chip {} but is missing a pico_cmake_set_default {} comment".format(board_header, chip, 'PICO_RP2350_A2_SUPPORTED'))
diff --git a/tools/example_keys/private.pem b/tools/example_keys/private.pem
new file mode 100644
index 00000000..bf777d89
--- /dev/null
+++ b/tools/example_keys/private.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BgUrgQQACg==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHQCAQEEIAXAdiilH8wT07TESUzWPt+BY9+NcchvYU3xbnpK+CBNoAcGBSuBBAAK
+oUQDQgAEYYJtMQFGW4AB94tU3u/Qir5sRcYjBYMqCa+8gxsYd9OwMS3dqWKsnVBz
+dyy7bFWdJzXDMb9o20xRRd57Q9xSYw==
+-----END EC PRIVATE KEY-----
diff --git a/tools/example_keys/privateaes.bin b/tools/example_keys/privateaes.bin
new file mode 100644
index 00000000..21a47756
Binary files /dev/null and b/tools/example_keys/privateaes.bin differ
diff --git a/tools/extract_configs.py b/tools/extract_configs.py
index 30705d5c..00ff3437 100755
--- a/tools/extract_configs.py
+++ b/tools/extract_configs.py
@@ -133,12 +133,12 @@ def ValidateAttrs(config_name, config_attrs, file_path, linenum):
-# Scan all .c and .h files in the specific path, recursively.
+# Scan all .c and .h and .S files in the specific path, recursively.
for dirpath, dirnames, filenames in os.walk(scandir):
for filename in filenames:
file_ext = os.path.splitext(filename)[1]
- if file_ext in ('.c', '.h'):
+ if file_ext in ('.c', '.h', '.S'):
file_path = os.path.join(dirpath, filename)
applicable = "all"
for chip in (*CHIP_NAMES, "host"):
@@ -241,6 +241,7 @@ for applicable, all_defines in chips_all_defines.items():
for applicable, all_configs in chips_all_configs.items():
all_defines = chips_all_defines[applicable]
+ resolved_defines = chips_resolved_defines[applicable]
for config_name, config_obj in all_configs.items():
file_path = os.path.join(scandir, config_obj['filename'])
linenum = config_obj['line_number']
diff --git a/tools/pioasm/c_sdk_output.cpp b/tools/pioasm/c_sdk_output.cpp
index c1730db4..d62d47c3 100644
--- a/tools/pioasm/c_sdk_output.cpp
+++ b/tools/pioasm/c_sdk_output.cpp
@@ -139,7 +139,7 @@ struct c_sdk_output : public output_format {
const char *types[] = {
"STATUS_TX_LESSTHAN",
"STATUS_RX_LESSTHAN",
- "STATUS_IRQ_INDEX",
+ "STATUS_IRQ_SET",
};
if (program.mov_status_type < 0 || program.mov_status_type >= 3) {
throw std::runtime_error("unknown mov_status type");