hardware_base

Low-level types and (atomic) accessors for memory-mapped hardware registers. More...

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...
 

Detailed Description

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.

Function Documentation

◆ hw_clear_bits()

static __force_inline void hw_clear_bits ( io_rw_32 *  addr,
uint32_t  mask 
)
static

Atomically clear the specified bits to 0 in a HW register.

Parameters
addrAddress of writable register
maskBit-mask specifying bits to clear

◆ hw_set_bits()

static __force_inline void hw_set_bits ( io_rw_32 *  addr,
uint32_t  mask 
)
static

Atomically set the specified bits to 1 in a HW register.

Parameters
addrAddress of writable register
maskBit-mask specifying bits to set

◆ hw_write_masked()

static __force_inline void hw_write_masked ( io_rw_32 *  addr,
uint32_t  values,
uint32_t  write_mask 
)
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.

Parameters
addrAddress of writable register
valuesBits values
write_maskMask of bits to change

◆ hw_xor_bits()

static __force_inline void hw_xor_bits ( io_rw_32 *  addr,
uint32_t  mask 
)
static

Atomically flip the specified bits in a HW register.

Parameters
addrAddress of writable register
maskBit-mask specifying bits to invert