Functions | |
static __force_inline void | hw_set_bits (io_rw_32 *addr, uint32_t mask) |
Atomically set the specified bits to 1 in a HW register. More... | |
static __force_inline void | hw_clear_bits (io_rw_32 *addr, uint32_t mask) |
Atomically clear the specified bits to 0 in a HW register. More... | |
static __force_inline void | hw_xor_bits (io_rw_32 *addr, uint32_t mask) |
Atomically flip the specified bits in a HW register. More... | |
static __force_inline void | hw_write_masked (io_rw_32 *addr, uint32_t values, uint32_t write_mask) |
Set new values for a sub-set of the bits in a HW register. More... | |
Low-level types and (atomic) accessors for memory-mapped hardware registers
hardware_base
defines the low level types and access functions for memory mapped hardware registers. It is included by default by all other hardware libraries.
The following register access typedefs codify the access type (read/write) and the bus size (8/16/32) of the hardware register. The register type names are formed by concatenating one from each of the 3 parts A, B, C
A | B | C | Meaning |
---|---|---|---|
io_ | A Memory mapped IO register | ||
ro_ | read-only access | ||
rw_ | read-write access | ||
wo_ | write-only access (can't actually be enforced via C API) | ||
8 | 8-bit wide access | ||
16 | 16-bit wide access | ||
32 | 32-bit wide access |
When dealing with these types, you will always use a pointer, i.e. io_rw_32 *some_reg
is a pointer to a read/write 32 bit register that you can write with *some_reg = value
, or read with value = *some_reg
.
RP2040 hardware is also aliased to provide atomic setting, clear or flipping of a subset of the bits within a hardware register so that concurrent access by two cores is always consistent with one atomic operation being performed first, followed by the second.
See hw_set_bits(), hw_clear_bits() and hw_xor_bits() provide for atomic access via a pointer to a 32 bit register
Additionally given a pointer to a structure representing a piece of hardware (e.g. dma_hw_t *dma_hw
for the DMA controller), you can get an alias to the entire structure such that writing any member (register) within the structure is equivalent to an atomic operation via hw_set_alias(), hw_clear_alias() or hw_xor_alias()...
For example hw_set_alias(dma_hw)->inte1 = 0x80;
will set bit 7 of the INTE1 register of the DMA controller, leaving the other bits unchanged.
|
static |
Atomically clear the specified bits to 0 in a HW register.
addr | Address of writable register |
mask | Bit-mask specifying bits to clear |
|
static |
Atomically set the specified bits to 1 in a HW register.
addr | Address of writable register |
mask | Bit-mask specifying bits to set |
|
static |
Set new values for a sub-set of the bits in a HW register.
Sets destination bits to values specified in values
, if and only if corresponding bit in write_mask
is set
Note: this method allows safe concurrent modification of different bits of a register, but multiple concurrent access to the same bits is still unsafe.
addr | Address of writable register |
values | Bits values |
write_mask | Mask of bits to change |
|
static |
Atomically flip the specified bits in a HW register.
addr | Address of writable register |
mask | Bit-mask specifying bits to invert |