|
typedef volatile uint32_t | spin_lock_t |
| A spin lock identifier.
|
|
Low level hardware spin locks, barrier and processor event APIs
Spin Locks
The RP2040 provides 32 hardware spin locks, which can be used to manage mutually-exclusive access to shared software and hardware resources.
Generally each spin lock itself is a shared resource, i.e. the same hardware spin lock can be used by multiple higher level primitives (as long as the spin locks are neither held for long periods, nor held concurrently with other spin locks by the same core - which could lead to deadlock). A hardware spin lock that is exclusively owned can be used individually without more flexibility and without regard to other software. Note that no hardware spin lock may be acquired re-entrantly (i.e. hardware spin locks are not on their own safe for use by both thread code and IRQs) however the default spinlock related methods here (e.g. spin_lock_blocking) always disable interrupts while the lock is held as use by IRQ handlers and user code is common/desirable, and spin locks are only expected to be held for brief periods.
The SDK uses the following default spin lock assignments, classifying which spin locks are reserved for exclusive/special purposes vs those suitable for more general shared use:
Number (ID) | Description |
0-13 | Currently reserved for exclusive use by the SDK and other libraries. If you use these spin locks, you risk breaking SDK or other library functionality. Each reserved spin lock used individually has its own PICO_SPINLOCK_ID so you can search for those. |
14,15 | (PICO_SPINLOCK_ID_OS1 and PICO_SPINLOCK_ID_OS2). Currently reserved for exclusive use by an operating system (or other system level software) co-existing with the SDK. |
16-23 | (PICO_SPINLOCK_ID_STRIPED_FIRST - PICO_SPINLOCK_ID_STRIPED_LAST). Spin locks from this range are assigned in a round-robin fashion via next_striped_spin_lock_num(). These spin locks are shared, but assigning numbers from a range reduces the probability that two higher level locking primitives using striped spin locks will actually be using the same spin lock. |
24-31 | (PICO_SPINLOCK_ID_CLAIM_FREE_FIRST - PICO_SPINLOCK_ID_CLAIM_FREE_LAST). These are reserved for exclusive use and are allocated on a first come first served basis at runtime via spin_lock_claim_unused() |
◆ __dmb()
Insert a DMB instruction in to the code path.
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.
◆ __dsb()
Insert a DSB instruction in to the code path.
The DSB (data synchronization barrier) acts as a special kind of data memory barrier (DMB). The DSB operation completes when all explicit memory accesses before this instruction complete.
◆ __isb()
Insert a ISB instruction in to the code path.
ISB acts as an instruction synchronization barrier. It flushes the pipeline of the processor, so that all instructions following the ISB are fetched from cache or memory again, after the ISB instruction has been completed.
◆ __sev()
Insert a SEV instruction in to the code path.
The SEV (send event) instruction sends an event to both cores.
◆ __wfe()
Insert a WFE instruction in to the code path.
The WFE (wait for event) instruction waits until one of a number of events occurs, including events signalled by the SEV instruction on either core.
◆ __wfi()
Insert a WFI instruction in to the code path.
The WFI (wait for interrupt) instruction waits for a interrupt to wake up the core.
◆ is_spin_locked()
Check to see if a spinlock is currently acquired elsewhere.
- Parameters
-
◆ next_striped_spin_lock_num()
uint next_striped_spin_lock_num |
( |
void |
| ) |
|
Return a spin lock number from the striped range.
Returns a spin lock number in the range PICO_SPINLOCK_ID_STRIPED_FIRST to PICO_SPINLOCK_ID_STRIPED_LAST in a round robin fashion. This does not grant the caller exclusive access to the spin lock, so the caller must:
- Abide (with other callers) by the contract of only holding this spin lock briefly (and with IRQs disabled - the default via spin_lock_blocking()), and not whilst holding other spin locks.
- Be OK with any contention caused by the - brief due to the above requirement - contention with other possible users of the spin lock.
- Returns
- lock_num a spin lock number the caller may use (non exclusively)
- See also
- PICO_SPINLOCK_ID_STRIPED_FIRST
-
PICO_SPINLOCK_ID_STRIPED_LAST
◆ restore_interrupts()
Restore interrupts to a specified state.
- Parameters
-
◆ save_and_disable_interrupts()
Save and disable interrupts.
- Returns
- The prior interrupt enable status for restoration later via restore_interrupts()
◆ spin_lock_blocking()
Acquire a spin lock safely.
This function will disable interrupts prior to acquiring the spinlock
- Parameters
-
- Returns
- interrupt status to be used when unlocking, to restore to original state
◆ spin_lock_claim()
void spin_lock_claim |
( |
uint |
lock_num | ) |
|
Mark a spin lock as used.
Method for cooperative claiming of hardware. Will cause a panic if the spin lock is already claimed. Use of this method by libraries detects accidental configurations that would fail in unpredictable ways.
- Parameters
-
lock_num | the spin lock number |
◆ spin_lock_claim_mask()
void spin_lock_claim_mask |
( |
uint32_t |
lock_num_mask | ) |
|
Mark multiple spin locks as used.
Method for cooperative claiming of hardware. Will cause a panic if any of the spin locks are already claimed. Use of this method by libraries detects accidental configurations that would fail in unpredictable ways.
- Parameters
-
lock_num_mask | Bitfield of all required spin locks to claim (bit 0 == spin lock 0, bit 1 == spin lock 1 etc) |
◆ spin_lock_claim_unused()
int spin_lock_claim_unused |
( |
bool |
required | ) |
|
Claim a free spin lock.
- Parameters
-
required | if true the function will panic if none are available |
- Returns
- the spin lock number or -1 if required was false, and none were free
◆ spin_lock_get_num()
Get HW Spinlock number from instance.
- Parameters
-
lock | The Spinlock instance |
- Returns
- The Spinlock ID
◆ spin_lock_init()
Initialise a spin lock.
The spin lock is initially unlocked
- Parameters
-
lock_num | The spin lock number |
- Returns
- The spin lock instance
◆ spin_lock_instance()
Get HW Spinlock instance from number.
- Parameters
-
- Returns
- The spinlock instance
◆ spin_lock_is_claimed()
bool spin_lock_is_claimed |
( |
uint |
lock_num | ) |
|
◆ spin_lock_unclaim()
void spin_lock_unclaim |
( |
uint |
lock_num | ) |
|
Mark a spin lock as no longer used.
Method for cooperative claiming of hardware.
- Parameters
-
lock_num | the spin lock number to release |
◆ spin_lock_unsafe_blocking()
Acquire a spin lock without disabling interrupts (hence unsafe)
- Parameters
-
◆ spin_unlock()
Release a spin lock safely.
This function will re-enable interrupts according to the parameters.
- Parameters
-
- See also
- spin_lock_blocking()
◆ spin_unlock_unsafe()
Release a spin lock without re-enabling interrupts.
- Parameters
-