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/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/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/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_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_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 f2504685..9006b5d7 100644 --- a/src/rp2_common/hardware_irq/irq.c +++ b/src/rp2_common/hardware_irq/irq.c @@ -57,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? @@ -82,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); @@ -135,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, ""); @@ -215,9 +208,17 @@ bool irq_has_shared_handler(uint 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 @@ -237,6 +238,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 } @@ -258,7 +260,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 @@ -368,6 +370,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); @@ -461,7 +465,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; @@ -586,6 +590,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 } @@ -626,7 +632,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) { @@ -670,7 +676,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 @@ -678,7 +684,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/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_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_runtime_init/runtime_init.c b/src/rp2_common/pico_runtime_init/runtime_init.c index 2b69c806..e028a513 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 }