diff --git a/src/host/hardware_sync/include/hardware/sync.h b/src/host/hardware_sync/include/hardware/sync.h index ae3865ae2..065cb3e52 100644 --- a/src/host/hardware_sync/include/hardware/sync.h +++ b/src/host/hardware_sync/include/hardware/sync.h @@ -109,8 +109,6 @@ extern "C" { void __sev(); -void __wev(); - void __wfi(); void __wfe(); diff --git a/src/host/hardware_sync/sync_core0_only.c b/src/host/hardware_sync/sync_core0_only.c index 70964c4b0..2578f0413 100644 --- a/src/host/hardware_sync/sync_core0_only.c +++ b/src/host/hardware_sync/sync_core0_only.c @@ -93,23 +93,44 @@ void PICO_WEAK_FUNCTION_IMPL_NAME(spin_unlock)(spin_lock_t *lock, uint32_t saved spin_unlock_unsafe(lock); } -PICO_WEAK_FUNCTION_DEF(__sev) +// These are defined on ARM hosts, but don't do what we want for the host +// since this is a simulated build. + +#if PICO_C_COMPILER_IS_GNU || !__has_builtin(__sev) +#define __sev_c __sev +#else +#pragma redefine_extname __sev_c __sev +#endif + +#if PICO_C_COMPILER_IS_GNU || !__has_builtin(__wfi) +#define __wfi_c __wfi +#else +#pragma redefine_extname __wfi_c __wfi +#endif + +#if PICO_C_COMPILER_IS_GNU || !__has_builtin(__wfe) +#define __wfe_c __wfe +#else +#pragma redefine_extname __wfe_c __wfe +#endif + +PICO_WEAK_FUNCTION_DEF(__sev_c) volatile bool event_fired; -void PICO_WEAK_FUNCTION_IMPL_NAME(__sev)() { +void PICO_WEAK_FUNCTION_IMPL_NAME(__sev_c)() { event_fired = true; } -PICO_WEAK_FUNCTION_DEF(__wfi) +PICO_WEAK_FUNCTION_DEF(__wfi_c) -void PICO_WEAK_FUNCTION_IMPL_NAME(__wfi)() { +void PICO_WEAK_FUNCTION_IMPL_NAME(__wfi_c)() { panic("Can't wait on irq for host core0 only implementation"); } -PICO_WEAK_FUNCTION_DEF(__wfe) +PICO_WEAK_FUNCTION_DEF(__wfe_c) -void PICO_WEAK_FUNCTION_IMPL_NAME(__wfe)() { +void PICO_WEAK_FUNCTION_IMPL_NAME(__wfe_c)() { while (!event_fired) tight_loop_contents(); } @@ -146,4 +167,4 @@ int PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_claim_unused)(bool required) { PICO_WEAK_FUNCTION_DEF(spin_lock_num) uint PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_num)(spin_lock_t *lock) { return 0; -} \ 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 52a5b64c0..7cb7cc464 100644 --- a/src/rp2_common/hardware_exception/exception.c +++ b/src/rp2_common/hardware_exception/exception.c @@ -35,7 +35,7 @@ static inline exception_handler_t *get_exception_table(void) { 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(); + __DMB(); restore_interrupts_from_disabled(save); } #endif @@ -108,4 +108,4 @@ uint exception_get_priority(uint num) { } return PICO_LOWEST_EXCEPTION_PRIORITY; } -#endif \ No newline at end of file +#endif diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c index fdcbb00fb..4260f8d9b 100644 --- a/src/rp2_common/hardware_irq/irq.c +++ b/src/rp2_common/hardware_irq/irq.c @@ -132,7 +132,7 @@ void irq_set_pending(uint num) { 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(); + __DMB(); spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_IRQ), save); } #endif @@ -498,7 +498,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) { // Note that a irq handler chain is local to our own core, so we don't need to worry about the other core bool was_enabled = irq_is_enabled(num); irq_set_enabled(num, false); - __dmb(); + __DMB(); // It is possible we are being called while an IRQ for this chain is already in progress. // The issue we have here is that we must not free a slot that is currently being executed, because diff --git a/src/rp2_common/hardware_sync/include/hardware/sync.h b/src/rp2_common/hardware_sync/include/hardware/sync.h index 69b3e69a0..49aa30972 100644 --- a/src/rp2_common/hardware_sync/include/hardware/sync.h +++ b/src/rp2_common/hardware_sync/include/hardware/sync.h @@ -62,12 +62,19 @@ extern "C" { #endif #endif +#if (__ARM_ACLE >= 200) +// If the compiler offers arm_acle.h, don't try to re-define symbols from +// the header. +#include +#else + /*! \brief Insert a NOP instruction in to the code path. * \ingroup hardware_sync * * NOP does nothing for one cycle. On RP2350 Arm binaries this is forced to be * a 32-bit instruction to avoid dual-issue of NOPs. */ +#if !__has_builtin(__nop) __force_inline static void __nop(void) { #if !__ARM_ARCH_6M__ #ifdef __riscv @@ -79,6 +86,7 @@ __force_inline static void __nop(void) { __asm volatile ("nop"); #endif } +#endif /*! \brief Insert a SEV instruction in to the code path. @@ -129,13 +137,15 @@ __force_inline static void __wfi(void) { * The DMB (data memory barrier) acts as a memory barrier, all memory accesses prior to this * instruction will be observed before any explicit access after the instruction. */ -__force_inline static void __dmb(void) { +#if !__has_builtin(__dmb) +__force_inline static void __dmb(unsigned int) { #ifdef __riscv __asm volatile ("fence rw, rw" : : : "memory"); #else pico_default_asm_volatile ("dmb" : : : "memory"); #endif } +#endif /*! \brief Insert a DSB instruction in to the code path. * \ingroup hardware_sync @@ -144,13 +154,15 @@ __force_inline static void __dmb(void) { * memory barrier (DMB). The DSB operation completes when all explicit memory * accesses before this instruction complete. */ -__force_inline static void __dsb(void) { +#if !__has_builtin(__dsb) +__force_inline static void __dsb(unsigned int) { #ifdef __riscv __asm volatile ("fence rw, rw" : : : "memory"); #else pico_default_asm_volatile ("dsb" : : : "memory"); #endif } +#endif /*! \brief Insert a ISB instruction in to the code path. * \ingroup hardware_sync @@ -159,13 +171,29 @@ __force_inline static void __dsb(void) { * so that all instructions following the ISB are fetched from cache or memory again, after * the ISB instruction has been completed. */ -__force_inline static void __isb(void) { +#if !__has_builtin(__isb) +__force_inline static void __isb(unsigned int) { #ifdef __riscv __asm volatile ("fence.i" : : : "memory"); #else pico_default_asm_volatile("isb" ::: "memory"); #endif } +#endif + +#endif /* (__ARM_ACLE >= 200) */ + +#ifndef __DMB +#define __DMB() __dmb(0xf) +#endif + +#ifndef __DSB +#define __DSB() __dsb(0xf) +#endif + +#ifndef __ISB +#define __ISB() __isb(0xf) +#endif /*! \brief Acquire a memory fence * \ingroup hardware_sync @@ -174,7 +202,7 @@ __force_inline static void __mem_fence_acquire(void) { // the original code below makes it hard for us to be included from C++ via a header // which itself is in an extern "C", so just use __dmb instead, which is what // is required on Cortex M0+ - __dmb(); + __DMB(); //#ifndef __cplusplus // atomic_thread_fence(memory_order_acquire); //#else @@ -190,7 +218,7 @@ __force_inline static void __mem_fence_release(void) { // the original code below makes it hard for us to be included from C++ via a header // which itself is in an extern "C", so just use __dmb instead, which is what // is required on Cortex M0+ - __dmb(); + __DMB(); //#ifndef __cplusplus // atomic_thread_fence(memory_order_release); //#else diff --git a/src/rp2_common/hardware_xip_cache/xip_cache.c b/src/rp2_common/hardware_xip_cache/xip_cache.c index 5a78ec0f4..48083fdc9 100644 --- a/src/rp2_common/hardware_xip_cache/xip_cache.c +++ b/src/rp2_common/hardware_xip_cache/xip_cache.c @@ -18,7 +18,7 @@ typedef enum { #endif // Used to ensure subsequent accesses observe the new state of the maintained cache lines -#define __post_maintenance_barrier() do {__dsb(); __isb();} while (0) +#define __post_maintenance_barrier() do {__DSB(); __ISB();} while (0) // All functions in this file are marked non-flash, even though they themselves may be executed // safely from flash, because they are likely to be called during a flash programming operation