Beetwise

The pitfalls of register code

Register code fails in a small number of ways, over and over.

Most of the failures look like a dead peripheral rather than a wrong value.

Each one has a symptom you can recognise and a fix of one line.

Try register pitfalls in the bit editor

The safe idiom: clear the field, then set it. Edit the expression or select a bit to flip it.

7
6
5
4
3
2
1
0
0xB3
hex · 8 bits
binary
0b10110011
value
179
Bit width
Shift

Register pitfalls step by step

Change the low four bits of 0xB6 to 3 and keep the rest:

  1. The mask for the field is 0x0F.
  2. Clear the field first: 0xB6 & ~0x0F gives 0xB0.
  3. Set the new value: 0xB0 | 0x03 gives 0xB3.
  4. An OR alone gives 0xBF, because the old bits stay.

Ten register mistakes, with the symptom and the fix

Ten register mistakes, with the symptom and the fix
MistakeWhat you seeFix
reg = valueOther bits of the register go to 0reg |= value
OR without a clearAn old field value stays behindreg &= ~mask first
Bit n for a 2-bit fieldThe wrong pin changesUse 2n for the position
1 << 31Undefined behaviour on a signed intWrite 1u << 31
Shift by the widthUndefined behaviour, not 0Guard the shift amount
No volatileThe compiler drops the readDeclare the pointer volatile
Read, change, writeAn interrupt loses a changeUse a W1TS register or a lock
x & mask == 0The test always failsWrite (x & mask) == 0
Signed right shiftA negative value keeps its signShift an unsigned type
A full write to MODERThe debug port stopsKeep the bits of the debug pins

Where register pitfalls is used

A dead peripheral after a register write is almost always one of these ten.

A code generator and a language model both produce field offsets that look right and are not.

A value that reads back wrong is faster to check against the bits than against the datasheet.

Register pitfalls: points to note

  • A wrong bit position gives a program that runs with a dead pin, which hides the cause.
  • A clobbered field often works until a second peripheral needs the bits you cleared.
  • A read, change and write sequence fails once in a thousand runs, which reads as random.
  • Paste the value you wrote into the editor above and compare it against the field you meant.

The full bit editor

The full editor holds many values, evaluates expressions across them, and reads live values from a serial port.

Open this value in the full editor

Questions about register pitfalls

Why did my other pins go dead?
An assignment writes every bit. Use |= to set bits and &= ~mask to clear them.
Why does the pin next to mine change?
A field of two bits sits at the position 2n, so pin 5 uses bit 10 and not bit 5.
Why does my register read back as 0?
A pointer without volatile lets the compiler drop the read. Declare it volatile.