Register Bit Operations

Set, clear, toggle and test individual bits, and read or write multi-bit fields — the everyday operations of driver code.

A 32-bit peripheral register packs many settings into one word: an enable bit here, a 2-bit mode field there, a status flag elsewhere. Changing one setting without disturbing the others is a read-modify-write: read the register, change only the bits you mean to, write it back.

Why not C bit-fields for registers?

REG |= (mode << 8); // update a 2-bit field REG = (REG & ~(3UL << 8)) | ((mode & 3UL) << 8);

OR alone cannot turn a 1 back into 0, so the old field value leaks into the new one. Clear the field first.

REG &= ~1 << 5;

REG &= ~(1UL << 5);

~ binds tighter than <<, so ~1 << 5 is (~1) << 5 — it clears bits 0–4 too. Always parenthesise the shifted mask.

Write the expression that tests whether bit 7 of status is set.

(status & (1UL << 7)) != 0 — or ((status >> 7) & 1u).

Why is GPIOx->BSRR preferred over ODR |= for setting a pin from both main and an ISR?

BSRR sets or resets pins in a single write, with no read-modify-write, so an interrupt between steps cannot lose an update.

REG = 0xABCD1234. What does ((REG >> 8) & 0xF) return?

0x2 — shifting right by 8 brings bits [11:8] (the hex digit '2' in ...12 34) to the bottom, and & 0xF keeps those 4 bits. The program above prints exactly this.