Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b9c20d4
Separate linker scripts out into include files
will-v-pi Dec 1, 2025
d7896b8
Add customisable heap location, with pico_set_linker_script_var function
will-v-pi Dec 1, 2025
6dd16d4
Add kitchen sink test of custom linker scripts
will-v-pi Dec 1, 2025
1e86595
Separate out rp2_common and platform-specific linker script sections
will-v-pi Dec 2, 2025
f6789f8
More de-duplication
will-v-pi Dec 2, 2025
c6cac63
Make overriding ram locations simpler
will-v-pi Dec 2, 2025
d89c2d8
Make it possible to reference default locations in pico_set_linker_sc…
will-v-pi Dec 4, 2025
cad6167
Initial non-secure support
will-v-pi Oct 2, 2025
249b422
Add nonsecure PIO support
will-v-pi Oct 7, 2025
25e2edd
Add pads_bank0 helper functions for E3
will-v-pi Oct 7, 2025
52c22c7
Add pico_secure library with non-bootrom-related secure setup code
will-v-pi Oct 7, 2025
021b00f
Add secure hardfault handler function
will-v-pi Oct 7, 2025
3d47f3e
Add rom_get_owned_partition and rom_roll_qmi_to_partition functions
will-v-pi Oct 7, 2025
326e945
Tidy up runtime init
will-v-pi Oct 7, 2025
4c3543e
Add nonsecure USB support
will-v-pi Oct 7, 2025
3326a5f
Add CMake function docs
will-v-pi Oct 8, 2025
c606caf
Fix libraries
will-v-pi Oct 8, 2025
6ef5d37
Improve secure call defines
will-v-pi Nov 12, 2025
0f8d15c
Add pico_set_security_ram_split for simple split configuration
will-v-pi Dec 4, 2025
362f83e
Make that work correctly
will-v-pi Dec 4, 2025
cd11286
Add user callbacks to rom_secure_call
will-v-pi Dec 4, 2025
044071b
Add scratch_each and secure_scratch splits, and secure_launch_nonsecu…
will-v-pi Dec 4, 2025
8455e64
Add NO_FLASH option to split, to run NonSecure from ram
will-v-pi Dec 4, 2025
bd8af3f
hw_set_bits doesn't work on SAU
will-v-pi Dec 5, 2025
9f7afbd
Enable sys_info NS API
will-v-pi Dec 5, 2025
26e397a
Only take mask for secure call reset functions
will-v-pi Dec 5, 2025
2c4e1f6
Add buffer validation for nonsecure stdio
will-v-pi Dec 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/cmake/rp2_common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ if (NOT PICO_BARE_METAL)

if (PICO_COMBINED_DOCS OR NOT PICO_RP2040)
pico_add_subdirectory(rp2_common/pico_sha256)
pico_add_subdirectory(rp2_common/pico_secure)
endif()

pico_add_subdirectory(rp2_common/pico_stdio_semihosting)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,4 +341,42 @@ typedef struct cflash_flags {
#define CFLASH_OP_VALUE_READ _u(2)
#define CFLASH_OP_MAX _u(2)

#ifndef __riscv
/*! \brief Return a well known secure call code based on four ASCII characters
* \ingroup pico_bootrom
*
* These codes are used to call well known secure functions from non-secure code.
*
* NOTE: ASCII characters are all < 0x80, so will always start with `0b0xxx`, as required by the rom_secure_call() documentation.
*
* \param c1 the first character
* \param c2 the second character
* \param c3 the third character
* \param c4 the fourth character
* \return the 'code' to use in rom_secure_call(), and handled by rom_default_callback()
*/
#define SECURE_CALL_WELL_KNOWN_CODE(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))

#define SECURE_CALL_stdio_out_chars SECURE_CALL_WELL_KNOWN_CODE('I', 'O', 'O', 'C')

#define SECURE_CALL_get_rand_64 SECURE_CALL_WELL_KNOWN_CODE('R', 'D', '6', '4')

#define SECURE_CALL_dma_allocate_unused_channel_for_nonsecure SECURE_CALL_WELL_KNOWN_CODE('D', 'A', 'C', 'H')

#define SECURE_CALL_user_irq_claim_unused_for_nonsecure SECURE_CALL_WELL_KNOWN_CODE('U', 'I', 'R', 'Q')

#define SECURE_CALL_clock_get_hz SECURE_CALL_WELL_KNOWN_CODE('C', 'K', 'G', 'H')

#define SECURE_CALL_pio_claim_unused_pio_for_nonsecure SECURE_CALL_WELL_KNOWN_CODE('P', 'I', 'O', 'C')

#define SECURE_CALL_pads_bank0_set_bits SECURE_CALL_WELL_KNOWN_CODE('P', '0', 'S', 'B')
#define SECURE_CALL_pads_bank0_clear_bits SECURE_CALL_WELL_KNOWN_CODE('P', '0', 'C', 'B')
#define SECURE_CALL_pads_bank0_write_masked SECURE_CALL_WELL_KNOWN_CODE('P', '0', 'W', 'M')
#define SECURE_CALL_pads_bank0_read SECURE_CALL_WELL_KNOWN_CODE('P', '0', 'R', 'D')

#define SECURE_CALL_reset_block_mask SECURE_CALL_WELL_KNOWN_CODE('R', 'T', 'R', 'M')
#define SECURE_CALL_unreset_block_mask SECURE_CALL_WELL_KNOWN_CODE('R', 'T', 'U', 'M')
#define SECURE_CALL_unreset_block_mask_wait_blocking SECURE_CALL_WELL_KNOWN_CODE('R', 'T', 'U', 'W')
#endif

#endif
9 changes: 6 additions & 3 deletions src/rp2_common/hardware_flash/include/hardware/flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_FLASH 0
#endif
#endif
#define FLASH_PAGE_SIZE (1u << 8)
#define FLASH_SECTOR_SIZE (1u << 12)
#define FLASH_BLOCK_SIZE (1u << 16)
#define FLASH_PAGE_SHIFT 8u
#define FLASH_PAGE_SIZE (1u << FLASH_PAGE_SHIFT)
#define FLASH_SECTOR_SHIFT 12u
#define FLASH_SECTOR_SIZE (1u << FLASH_SECTOR_SHIFT)
#define FLASH_BLOCK_SHIFT 16u
#define FLASH_BLOCK_SIZE (1u << FLASH_BLOCK_SHIFT)

#ifndef FLASH_UNIQUE_ID_SIZE_BYTES
#define FLASH_UNIQUE_ID_SIZE_BYTES 8
Expand Down
6 changes: 5 additions & 1 deletion src/rp2_common/hardware_gpio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
pico_simple_hardware_target(gpio)
pico_mirrored_target_link_libraries(hardware_gpio INTERFACE hardware_irq)
pico_mirrored_target_link_libraries(hardware_gpio INTERFACE hardware_irq)

if (PICO_RP2350)
pico_mirrored_target_link_libraries(hardware_gpio INTERFACE pico_bootrom)
endif()
44 changes: 22 additions & 22 deletions src/rp2_common/hardware_gpio/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static raw_irq_mask_type_t raw_irq_mask[NUM_CORES];
// Get the raw value from the pin, bypassing any muxing or overrides.
int gpio_get_pad(uint gpio) {
check_gpio_param(gpio);
hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
pads_bank0_set_bits(gpio, PADS_BANK0_GPIO0_IE_BITS);
return (io_bank0_hw->io[gpio].status & IO_BANK0_GPIO0_STATUS_INFROMPAD_BITS)
>> IO_BANK0_GPIO0_STATUS_INFROMPAD_LSB;
}
Expand All @@ -39,7 +39,7 @@ void gpio_set_function(uint gpio, gpio_function_t fn) {
check_gpio_param(gpio);
invalid_params_if(HARDWARE_GPIO, ((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS);
// Set input enable on, output disable off
hw_write_masked(&pads_bank0_hw->io[gpio],
pads_bank0_write_masked(gpio,
PADS_BANK0_GPIO0_IE_BITS,
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS
);
Expand All @@ -48,7 +48,7 @@ void gpio_set_function(uint gpio, gpio_function_t fn) {
io_bank0_hw->io[gpio].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
#if HAS_PADS_BANK0_ISOLATION
// Remove pad isolation now that the correct peripheral is in control of the pad
hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_ISO_BITS);
pads_bank0_clear_bits(gpio, PADS_BANK0_GPIO0_ISO_BITS);
#endif
}
/// \end::gpio_set_function[]
Expand All @@ -62,8 +62,8 @@ gpio_function_t gpio_get_function(uint gpio) {
// i.e. weak pull to whatever is current high/low state of GPIO.
void gpio_set_pulls(uint gpio, bool up, bool down) {
check_gpio_param(gpio);
hw_write_masked(
&pads_bank0_hw->io[gpio],
pads_bank0_write_masked(
gpio,
(bool_to_bit(up) << PADS_BANK0_GPIO0_PUE_LSB) | (bool_to_bit(down) << PADS_BANK0_GPIO0_PDE_LSB),
PADS_BANK0_GPIO0_PUE_BITS | PADS_BANK0_GPIO0_PDE_BITS
);
Expand Down Expand Up @@ -106,28 +106,28 @@ void gpio_set_oeover(uint gpio, uint value) {
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled) {
check_gpio_param(gpio);
if (enabled)
hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
pads_bank0_set_bits(gpio, PADS_BANK0_GPIO0_SCHMITT_BITS);
else
hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
pads_bank0_clear_bits(gpio, PADS_BANK0_GPIO0_SCHMITT_BITS);
}


bool gpio_is_input_hysteresis_enabled(uint gpio) {
check_gpio_param(gpio);
return (pads_bank0_hw->io[gpio] & PADS_BANK0_GPIO0_SCHMITT_BITS) != 0;
return (pads_bank0_read(gpio) & PADS_BANK0_GPIO0_SCHMITT_BITS) != 0;
}

void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew) {
check_gpio_param(gpio);
hw_write_masked(&pads_bank0_hw->io[gpio],
pads_bank0_write_masked(gpio,
(uint)slew << PADS_BANK0_GPIO0_SLEWFAST_LSB,
PADS_BANK0_GPIO0_SLEWFAST_BITS
);
}

enum gpio_slew_rate gpio_get_slew_rate(uint gpio) {
check_gpio_param(gpio);
return (enum gpio_slew_rate)((pads_bank0_hw->io[gpio]
return (enum gpio_slew_rate)((pads_bank0_read(gpio)
& PADS_BANK0_GPIO0_SLEWFAST_BITS)
>> PADS_BANK0_GPIO0_SLEWFAST_LSB);
}
Expand All @@ -137,15 +137,15 @@ enum gpio_slew_rate gpio_get_slew_rate(uint gpio) {
static_assert(PADS_BANK0_GPIO0_DRIVE_VALUE_8MA == GPIO_DRIVE_STRENGTH_8MA, "");
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive) {
check_gpio_param(gpio);
hw_write_masked(&pads_bank0_hw->io[gpio],
pads_bank0_write_masked(gpio,
(uint)drive << PADS_BANK0_GPIO0_DRIVE_LSB,
PADS_BANK0_GPIO0_DRIVE_BITS
);
}

enum gpio_drive_strength gpio_get_drive_strength(uint gpio) {
check_gpio_param(gpio);
return (enum gpio_drive_strength)((pads_bank0_hw->io[gpio]
return (enum gpio_drive_strength)((pads_bank0_read(gpio)
& PADS_BANK0_GPIO0_DRIVE_BITS)
>> PADS_BANK0_GPIO0_DRIVE_LSB);
}
Expand Down Expand Up @@ -186,7 +186,7 @@ static void _gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled, io_b
void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled) {
// either this call disables the interrupt or callback should already be set.
// this protects against enabling the interrupt without callback set
assert(!enabled || irq_has_handler(IO_IRQ_BANK0));
assert(!enabled || irq_has_handler(DEFAULT_IO_IRQ_BANK0));

// Separate mask/force/status per-core, so check which core called, and
// set the relevant IRQ controls.
Expand All @@ -201,32 +201,32 @@ void gpio_set_irq_enabled_with_callback(uint gpio, uint32_t events, bool enabled
if (enabled) gpio_set_irq_callback(callback);
gpio_set_irq_enabled(gpio, events, enabled);
if (!enabled) gpio_set_irq_callback(callback);
if (enabled) irq_set_enabled(IO_IRQ_BANK0, true);
if (enabled) irq_set_enabled(DEFAULT_IO_IRQ_BANK0, true);
}

void gpio_set_irq_callback(gpio_irq_callback_t callback) {
uint core = get_core_num();
if (callbacks[core]) {
if (!callback) {
irq_remove_handler(IO_IRQ_BANK0, gpio_default_irq_handler);
irq_remove_handler(DEFAULT_IO_IRQ_BANK0, gpio_default_irq_handler);
}
callbacks[core] = callback;
} else if (callback) {
callbacks[core] = callback;
irq_add_shared_handler(IO_IRQ_BANK0, gpio_default_irq_handler, GPIO_IRQ_CALLBACK_ORDER_PRIORITY);
irq_add_shared_handler(DEFAULT_IO_IRQ_BANK0, gpio_default_irq_handler, GPIO_IRQ_CALLBACK_ORDER_PRIORITY);
}
}

void gpio_add_raw_irq_handler_with_order_priority_masked(uint32_t gpio_mask, irq_handler_t handler, uint8_t order_priority) {
hard_assert(!(raw_irq_mask[get_core_num()] & gpio_mask)); // should not add multiple handlers for the same event
raw_irq_mask[get_core_num()] |= gpio_mask;
irq_add_shared_handler(IO_IRQ_BANK0, handler, order_priority);
irq_add_shared_handler(DEFAULT_IO_IRQ_BANK0, handler, order_priority);
}

void gpio_add_raw_irq_handler_with_order_priority_masked64(uint64_t gpio_mask, irq_handler_t handler, uint8_t order_priority) {
hard_assert(!(raw_irq_mask[get_core_num()] & gpio_mask)); // should not add multiple handlers for the same event
raw_irq_mask[get_core_num()] |= (raw_irq_mask_type_t) gpio_mask;
irq_add_shared_handler(IO_IRQ_BANK0, handler, order_priority);
irq_add_shared_handler(DEFAULT_IO_IRQ_BANK0, handler, order_priority);
}

void gpio_add_raw_irq_handler_masked(uint32_t gpio_mask, irq_handler_t handler) {
Expand All @@ -239,13 +239,13 @@ void gpio_add_raw_irq_handler_masked64(uint64_t gpio_mask, irq_handler_t handler

void gpio_remove_raw_irq_handler_masked(uint32_t gpio_mask, irq_handler_t handler) {
assert(raw_irq_mask[get_core_num()] & gpio_mask); // should not remove handlers that are not added
irq_remove_handler(IO_IRQ_BANK0, handler);
irq_remove_handler(DEFAULT_IO_IRQ_BANK0, handler);
raw_irq_mask[get_core_num()] &= ~gpio_mask;
}

void gpio_remove_raw_irq_handler_masked64(uint64_t gpio_mask, irq_handler_t handler) {
assert(raw_irq_mask[get_core_num()] & gpio_mask); // should not remove handlers that are not added
irq_remove_handler(IO_IRQ_BANK0, handler);
irq_remove_handler(DEFAULT_IO_IRQ_BANK0, handler);
raw_irq_mask[get_core_num()] &= (raw_irq_mask_type_t)~gpio_mask;
}

Expand All @@ -267,9 +267,9 @@ void gpio_debug_pins_init(void) {
void gpio_set_input_enabled(uint gpio, bool enabled) {
check_gpio_param(gpio);
if (enabled)
hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
pads_bank0_set_bits(gpio, PADS_BANK0_GPIO0_IE_BITS);
else
hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
pads_bank0_clear_bits(gpio, PADS_BANK0_GPIO0_IE_BITS);
}

void gpio_init(uint gpio) {
Expand Down
21 changes: 19 additions & 2 deletions src/rp2_common/hardware_gpio/include/hardware/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,27 @@
#define PICO_USE_GPIO_COPROCESSOR 1
#endif


#if PICO_NONSECURE
#define DEFAULT_IO_IRQ_BANK0 IO_IRQ_BANK0_NS
#else
#define DEFAULT_IO_IRQ_BANK0 IO_IRQ_BANK0
#endif


#if PICO_USE_GPIO_COPROCESSOR
#include "hardware/gpio_coproc.h"
#endif

#if PICO_SECURE || PICO_NONSECURE
#include "pico/bootrom.h" // uses helper functions due to Errata RP2350-E3
#else
#define pads_bank0_set_bits(gpio, bits) hw_set_bits(&pads_bank0_hw->io[gpio], bits)
#define pads_bank0_clear_bits(gpio, bits) hw_clear_bits(&pads_bank0_hw->io[gpio], bits)
#define pads_bank0_write_masked(gpio, bits, mask) hw_write_masked(&pads_bank0_hw->io[gpio], bits, mask)
#define pads_bank0_read(gpio) pads_bank0_hw->io[gpio]
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -312,7 +329,7 @@ static inline void gpio_pull_up(uint gpio) {
* \return true if the GPIO is pulled up
*/
static inline bool gpio_is_pulled_up(uint gpio) {
return (pads_bank0_hw->io[gpio] & PADS_BANK0_GPIO0_PUE_BITS) != 0;
return (pads_bank0_read(gpio) & PADS_BANK0_GPIO0_PUE_BITS) != 0;
}

/*! \brief Set specified GPIO to be pulled down.
Expand All @@ -331,7 +348,7 @@ static inline void gpio_pull_down(uint gpio) {
* \return true if the GPIO is pulled down
*/
static inline bool gpio_is_pulled_down(uint gpio) {
return (pads_bank0_hw->io[gpio] & PADS_BANK0_GPIO0_PDE_BITS) != 0;
return (pads_bank0_read(gpio) & PADS_BANK0_GPIO0_PDE_BITS) != 0;
}

/*! \brief Disable pulls on specified GPIO
Expand Down
4 changes: 4 additions & 0 deletions src/rp2_common/hardware_resets/include/hardware/resets.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@
extern "C" {
#endif

#if PICO_NONSECURE
#include "pico/bootrom.h"
#else
static __force_inline void reset_block_reg_mask(io_rw_32 *reset, uint32_t mask) {
hw_set_bits(reset, mask);
}
Expand All @@ -119,6 +122,7 @@ static __force_inline void unreset_block_reg_mask_wait_blocking(io_rw_32 *reset,
while (~*reset_done & mask)
tight_loop_contents();
}
#endif

/// \tag::reset_funcs[]

Expand Down
4 changes: 2 additions & 2 deletions src/rp2_common/pico_bootrom/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ target_sources(pico_bootrom INTERFACE
)

target_link_libraries(pico_bootrom_headers INTERFACE boot_picoboot_headers boot_bootrom_headers)
pico_mirrored_target_link_libraries(pico_bootrom INTERFACE pico_base hardware_boot_lock pico_flash)
pico_mirrored_target_link_libraries(pico_bootrom INTERFACE pico_base hardware_boot_lock pico_flash hardware_flash pico_rand hardware_dma hardware_irq pico_stdio hardware_pio)

# bootrom.c includes boot/picobin.h
# bootrom_lock.c includes pico/runtime_init.h
target_link_libraries(pico_bootrom INTERFACE boot_picobin_headers pico_runtime_init_headers)
target_link_libraries(pico_bootrom INTERFACE boot_picobin_headers pico_runtime_init_headers)
Loading
Loading