// lesson: bits-and-masks

Bits, Masks, and Read-Modify-Write

A register is rarely one value โ€” it is 32 independent switches packed into a word. GPIO_OUT bit 25 is the Pico's LED; bit 16 might be your I2C bus. Driving hardware means changing your bits without disturbing anyone else's, which is done with masks:

reg |=  mask;   /* set   every bit that is 1 in mask */
reg &= ~mask;   /* clear every bit that is 1 in mask */
reg ^=  mask;   /* flip  every bit that is 1 in mask */

A mask for a single pin is built by shifting: 1u << pin. Note the u โ€” shifting a plain (signed) int left into bit 31 is undefined behavior. The RP2040's GPIO pins only go up to 29, so GPIO_OUT never actually needs bit 31, but plenty of other 32-bit registers use every bit: the SIO has 32 hardware spinlocks, and SIO_SPINLOCK_ST reports all of them as a bitmap, one bit per spinlock, straight through to bit 31. Use 1u, not 1, and which register you're shifting into stops mattering.

Each of those compound assignments is really three steps: read the register, modify the copy, write it back. Keep that shape in mind โ€” it works, but the next lesson shows why on the RP2040 you often want the hardware to do the modify step for you.

โ€บ Set, Clear, Toggle

10 pts

Implement the three classic read-modify-write helpers. Each takes a pointer to a register and a mask, and must leave every bit outside the mask exactly as it found it.

Log in to submit a solution and earn points.