Hardware Register Interface (HRI)

The layer closest to the hardware is named HRI. This layer is a simple interface with very little logic that do register data content manipulation with a set of defined functions calls. The data manipulation operations can be performed on a bit, bit field, and complete register level.

Figure 1. HRI Example Data Manipulation of Bit and Bit Field Contents

This layer also abstracts special register access properties like data synchronization between clock domains. It also ensures that data integrity is kept within an interruptible system by inserting critical sections when it is not possible to do data manipulation atomically.

Using the HRI interfaces as access interface to the peripheral registers helps the compiler optimize the code towards targets like low code size or faster code. When targeting fast code, the compiler can choose to inline the function to be able to optimize the code in context and avoid call conventions. For low code size, the compiler can avoid in-lining the function and reuse the same copy of the function multiple times.

All functions in the HRI are defined as static inline. This gives the compiler the possibility to optimize the code within the context of where it is used. Using functions instead of pre-processor macros keeps the possibility to use the compiler for type checking and makes the code a bit safer compared to pre-processor macros.

There are three main categories of access functions; single-bit access functions (accesses one bit at the time), bit field access functions (accesses multiple bits with a common purpose), and register access functions (access the content of a full register).

Different operation types available for the access functions

Note: If shadow registers are detected for set, toggle, and clear they will be used instead of normal access.

These operations are available for single bit access

Note: Access to some registers, such as status and INTFLAG registers, only have get and clear access functions.

These operations are available for bit field access

These operations are available for register access

These operations are available for write-only register access

Note: The bit and bitfield operations are not available for write-only register since they are based on the latest value in the register.

These operations are available for read-only register access

Shadow register access

The shadow registers are grouped registers that share data of named or virtual register value. They offer some atomic way to change this shared data value. As an example, in SAM D20 there is a register group of OUT, OUTCLR, OUTSET, and OUTTGL in PORT peripheral for port outputs. Writing to OUTCLR, OUTSET, and OUTTGL actually modifies the value in OUT register. In SAM V71, there is a similar register group of ODSR, CODR, and SODR in PIO peripheral for I/O outputs, where writing to CODR and SODR causes changes in ODSR and applies to the actual output pin levels.

Shadow registers have all possible operations for register, bit, and bit field access. The operations target the actual named or virtual register: There is register, bit, and bit field operations to access OUT register, but no operation to access OUTCLR, OUTSET, and OUTTGL.

Naming scheme

Single bit access

hri_[module name]_[function]_[REGISTER NAME]_[BIT NAME]
eg. adc_set_CTRLA_ENABLE(hw);

Bit field access

hri_[module name]_[function]_[REGISTER NAME]__[BIT FIELD NAME]
eg. adc_set_AVGCTRL_SAMPLENUM(hw, mask);

Register access

hri_[module name]_[function]_[REGISTER NAME]
eg. adc_set_CTRLA(hw, mask);
Note: Special naming rule for single bit access to an interrupt flag register. This applies only to interrupt status registers, not interrupt related registers for enabling, disabling, clearing, etc.
[module name]_[function]_interrupt_[BIT NAME]