7#ifndef _HARDWARE_SYNC_SPIN_LOCK_H
8#define _HARDWARE_SYNC_SPIN_LOCK_H
14#ifndef PICO_USE_SW_SPIN_LOCKS
16#define PICO_USE_SW_SPIN_LOCKS (!PICO_XIP_RAM)
33#ifndef PICO_SPINLOCK_ID_IRQ
34#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
35#define PICO_SPINLOCK_ID_IRQ 5
37#define PICO_SPINLOCK_ID_IRQ 9
42#ifndef PICO_SPINLOCK_ID_TIMER
43#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
44#define PICO_SPINLOCK_ID_TIMER 6
46#define PICO_SPINLOCK_ID_TIMER 10
51#ifndef PICO_SPINLOCK_ID_HARDWARE_CLAIM
52#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
53#define PICO_SPINLOCK_ID_HARDWARE_CLAIM 7
55#define PICO_SPINLOCK_ID_HARDWARE_CLAIM 11
60#ifndef PICO_SPINLOCK_ID_RAND
61#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
62#define PICO_SPINLOCK_ID_RAND 10
64#define PICO_SPINLOCK_ID_RAND 12
69#ifndef PICO_SPINLOCK_ID_ATOMIC
70#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
71#define PICO_SPINLOCK_ID_ATOMIC 11
73#define PICO_SPINLOCK_ID_ATOMIC 13
78#ifndef PICO_SPINLOCK_ID_OS1
79#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
80#define PICO_SPINLOCK_ID_OS1 18
82#define PICO_SPINLOCK_ID_OS1 14
87#ifndef PICO_SPINLOCK_ID_OS2
88#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
89#define PICO_SPINLOCK_ID_OS2 19
91#define PICO_SPINLOCK_ID_OS2 15
96#ifndef PICO_SPINLOCK_ID_STRIPED_FIRST
97#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
98#define PICO_SPINLOCK_ID_STRIPED_FIRST 20
100#define PICO_SPINLOCK_ID_STRIPED_FIRST 16
105#ifndef PICO_SPINLOCK_ID_STRIPED_LAST
106#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
107#define PICO_SPINLOCK_ID_STRIPED_LAST 25
109#define PICO_SPINLOCK_ID_STRIPED_LAST 23
114#ifndef PICO_SPINLOCK_ID_CLAIM_FREE_FIRST
115#if PICO_RP2350 && !PICO_USE_SW_SPIN_LOCKS
116#define PICO_SPINLOCK_ID_CLAIM_FREE_FIRST 26
118#define PICO_SPINLOCK_ID_CLAIM_FREE_FIRST 24
122#ifdef PICO_SPINLOCK_ID_CLAIM_FREE_END
123#warning PICO_SPINLOCK_ID_CLAIM_FREE_END has been renamed to PICO_SPINLOCK_ID_CLAIM_FREE_LAST
127#ifndef PICO_SPINLOCK_ID_CLAIM_FREE_LAST
128#define PICO_SPINLOCK_ID_CLAIM_FREE_LAST 31
134#if !PICO_USE_SW_SPIN_LOCKS
136typedef io_rw_32 spin_lock_t;
138#ifndef SW_SPIN_LOCK_TYPE
140#define SW_SPIN_LOCK_TYPE volatile uint8_t
145#if PICO_USE_SW_SPIN_LOCKS
147#ifndef SW_SPIN_LOCK_INSTANCE
148#define SW_SPIN_LOCK_INSTANCE(lock_num) ({ \
149 extern spin_lock_t _sw_spin_locks[NUM_SPIN_LOCKS]; \
150 &_sw_spin_locks[lock_num]; \
154#ifndef SW_SPIN_LOCK_NUM
155#define SW_SPIN_LOCK_NUM(lock) ({ \
156 extern spin_lock_t _sw_spin_locks[NUM_SPIN_LOCKS]; \
157 (lock) - _sw_spin_locks; \
161#ifndef SW_SPIN_LOCK_IS_LOCKED
162#define SW_SPIN_LOCK_IS_LOCKED(lock) ((bool) *(lock))
165#ifndef SW_SPIN_LOCK_LOCK
166#if __ARM_ARCH_8M_MAIN__
167#define SW_SPIN_LOCK_LOCK(lock) ({ \
168 uint32_t _tmp0, _tmp1; \
169 pico_default_asm_volatile ( \
171 "ldaexb %1, [%2]\n" \
177 "strexb %1, %0, [%2]\n" \
181 : "=&r" (_tmp0), "=&r" (_tmp1) : "r" (lock) \
183 __mem_fence_acquire(); \
185#elif __riscv && (defined(__riscv_a) || defined(__riscv_zaamo))
186#define SW_SPIN_LOCK_LOCK(lock) ({ \
187 uint32_t _tmp0, _tmp1; \
188 pico_default_asm_volatile ( \
192 "bset %1, zero, %1\n" \
193 "andi %0, %0, -4\n" \
197 "amoor.w.aq %2, %1, (%0)\n" \
200 : "+r" (lock), "=r" (_tmp0), "=r" (_tmp1) \
202 __mem_fence_acquire(); \
205#error no SW_SPIN_LOCK_LOCK available for PICO_USE_SW_SPIN_LOCK on this platform
209#ifndef SW_SPIN_TRY_LOCK
210#if __ARM_ARCH_8M_MAIN__
211#define SW_SPIN_TRY_LOCK(lock) ({ \
212 uint32_t _tmp0, _tmp1; \
213 pico_default_asm_volatile ( \
214 "ldaexb %1, [%2]\n" \
220 "strexb %1, %0, [%2]\n" \
222 : "=&r" (_tmp0), "=&r" (_tmp1) : "r" (lock) \
224 __mem_fence_acquire(); \
227#elif __riscv && (defined(__riscv_a) || defined(__riscv_zaamo))
228#define SW_SPIN_TRY_LOCK(lock) ({ \
230 pico_default_asm_volatile ( \
234 "bset %1, zero, %1\n" \
235 "andi %0, %0, -4\n" \
238 "amoor.w.aq %0, %1, (%0)\n" \
240 : "+r" (lock), "=r" (_tmp0) \
242 __mem_fence_acquire(); \
246#error no SW_SPIN_TRY_LOCK available for PICO_USE_SW_SPIN_LOCK on this platform
250#ifndef SW_SPIN_LOCK_UNLOCK
251#if __ARM_ARCH_8M_MAIN__
252#define SW_SPIN_LOCK_UNLOCK(lock) ({ \
255 pico_default_asm_volatile( \
257 : : "r" (zero), "r" (lock) \
261#define SW_SPIN_LOCK_UNLOCK(lock) ({ \
262 __mem_fence_release(); \
266#error no SW_SPIN_LOCK_UNLOCK available for PICO_USE_SW_SPIN_LOCK on this platform
279 invalid_params_if(HARDWARE_SYNC, lock_num >= NUM_SPIN_LOCKS);
280#if PICO_USE_SW_SPIN_LOCKS
281 return SW_SPIN_LOCK_INSTANCE(lock_num);
283 return (spin_lock_t *) (SIO_BASE + SIO_SPINLOCK0_OFFSET + lock_num * 4);
294#if PICO_USE_SW_SPIN_LOCKS
295 uint lock_num = SW_SPIN_LOCK_NUM(lock);
296 invalid_params_if(HARDWARE_SYNC, lock_num >= (uint)NUM_SPIN_LOCKS);
299 invalid_params_if(HARDWARE_SYNC, (uint) lock < SIO_BASE + SIO_SPINLOCK0_OFFSET ||
300 (uint) lock >= NUM_SPIN_LOCKS *
sizeof(spin_lock_t) + SIO_BASE + SIO_SPINLOCK0_OFFSET ||
301 ((uint) lock - SIO_BASE + SIO_SPINLOCK0_OFFSET) %
sizeof(spin_lock_t) != 0);
302 return (uint) (lock - (spin_lock_t *) (SIO_BASE + SIO_SPINLOCK0_OFFSET));
315#if PICO_USE_SW_SPIN_LOCKS
316 SW_SPIN_LOCK_LOCK(lock);
318 while (__builtin_expect(!*lock, 0)) {
325__force_inline static bool spin_try_lock_unsafe(spin_lock_t *lock) {
326#if PICO_USE_SW_SPIN_LOCKS
327 return SW_SPIN_TRY_LOCK(lock);
338#if PICO_USE_SW_SPIN_LOCKS
339 SW_SPIN_LOCK_UNLOCK(lock);
366#if PICO_USE_SW_SPIN_LOCKS
367 return SW_SPIN_LOCK_IS_LOCKED(lock);
369 check_hw_size(spin_lock_t, 4);
371 return 0 != (*(io_ro_32 *) (SIO_BASE + SIO_SPINLOCK_ST_OFFSET) & (1u << lock_num));
static __force_inline uint32_t spin_lock_blocking(spin_lock_t *lock)
Acquire a spin lock safely.
Definition spin_lock.h:354
static __force_inline uint32_t save_and_disable_interrupts(void)
Disable interrupts on the calling core, returning the previous interrupt state.
Definition sync.h:252
static __force_inline void __mem_fence_release(void)
Release a memory fence.
Definition sync.h:204
static __force_inline void spin_unlock_unsafe(spin_lock_t *lock)
Release a spin lock without re-enabling interrupts.
Definition spin_lock.h:337
static __force_inline void spin_unlock(spin_lock_t *lock, uint32_t saved_irq)
Release a spin lock safely.
Definition spin_lock.h:385
static __force_inline void restore_interrupts_from_disabled(uint32_t status)
Restore interrupts to a specified state on the calling core with restricted transitions.
Definition sync.h:295
void spin_locks_reset(void)
Release all spin locks.
Definition sync_spin_lock.c:8
static __force_inline spin_lock_t * spin_lock_instance(uint lock_num)
Get HW Spinlock instance from number.
Definition spin_lock.h:278
static __force_inline void __mem_fence_acquire(void)
Acquire a memory fence.
Definition sync.h:188
static __force_inline void spin_lock_unsafe_blocking(spin_lock_t *lock)
Acquire a spin lock without disabling interrupts (hence unsafe).
Definition spin_lock.h:311
spin_lock_t * spin_lock_init(uint lock_num)
Initialise a spin lock.
Definition sync_spin_lock.c:14
static __force_inline uint spin_lock_get_num(spin_lock_t *lock)
Get HW Spinlock number from instance.
Definition spin_lock.h:293
static bool is_spin_locked(spin_lock_t *lock)
Check to see if a spinlock is currently acquired elsewhere.
Definition spin_lock.h:365
#define SW_SPIN_LOCK_TYPE
A spin lock identifier.
Definition spin_lock.h:140