3.3.1 Change Register Bit Field Configurations Using Group and Group Configuration Masks

When updating only a bit field in a register, a Read-Modify-Write operation must be used. Therefore, to change the configuration of a register bit field, it is recommended to first clear the old configuration and then set a new one.

It is recommended using a bit group configuration mask to set a configuration in a bit field.

One way to change a bit field to a new configuration is presented in the code listing below. To be sure that the desired configuration is obtained, the user must clear the old configuration first, using the group mask.

/* Changing a bit group configuration */
USART0.CTRLB &= (~USART_RXMODE_gm); /* Clear the old configuration */
/* Set the new configuration using the group configuration mask */
USART0.CTRLB |= USART_RXMODE_GENAUTO_gc; 
Note: The first line will put the USART0 RXMODE, for a short time, into a specific state: 0x00.

A group mask macro is defined in the header file, as presented below.

#define USART_RXMODE_gm 0x06 /* Receiver mode group mask */

The USART_RXMODE_enum enumeration contains the group configuration mask presented below.

USART_RXMODE_GENAUTO_gc = (0x02<<1), /* Generic Auto-Baud mode */
CAUTION: Even though it may seem easier to split the code into two separate code lines, one to clear the register and another one to set the desired configuration, it is recommended to use a single line to do this, as presented in the code listing below.
/* Changing a bit group configuration */
USART0.CTRLB = (USART0.CTRLB & ~USART_RXMODE_gm) | USART_RXMODE_GENAUTO_gc;

These steps must be implemented in a single line to avoid putting the microcontroller in an unintended state.

The CTRLB register is declared this way:

register8_t CTRLB;

The register8_t data type is a volatile defined data type.

typedef volatile uint8_t register8_t;

Since the register is defined as volatile, two different code lines will trigger the reading and writing in the CTRLB register twice instead of once. In addition to making the code inefficient, this can also put the peripheral in an unintended state. The reason is that when an interrupt is triggered between the two lines of code, the context will be changed, and the register can remain in an undefined state.