soc_esp32::reg
Read-modify-write on a memory-mapped register, spelled once.
Sixteen sites across six files open-coded
r.write_volatile(r.read_volatile() | bits);r.write_volatile(r.read_volatile() & !bits);Individually trivial. Together they are the pattern in this codebase most
likely to be mistyped, and the typo is nasty: & bits where & !bits was
meant clears every other bit in the register. On a config register that
presents as a peripheral that stopped working, several layers away from the
line that did it, and the compiler has no opinion.
Not for DPORT
Section titled “Not for DPORT”[crate::dport] has its own [crate::dport::modify], and these must not be
used in its place. A DPORT read needs the erratum workaround — an APB
pre-read with interrupts masked — and the cross-core lock. Plain volatile
access to that block is the bug #56 was about.
Not a hal trait
Section titled “Not a hal trait”A trait would drag hal into pointer arithmetic it has no reason to know
about, and every chip’s registers are its own. Free functions in the SoC
crate keep this where the chip already is.
Functions
Section titled “Functions”const fn at(base: u32, offset: u32) -> *mut u32The address of offset within a peripheral’s register block.
unsafe fn clear(r: *mut u32, bits: u32)Clear bits, leaving the rest alone.
Safety
Section titled “Safety”As [set].
modify
Section titled “modify”unsafe fn modify(r: *mut u32, mask: u32, value: u32)Clear mask, then set value — a field update in one read-modify-write.
value is used as given, so it must already be shifted into the field.
Clearing first is what makes this idempotent: | alone can only ever add
bits, so a field would accumulate every value it had ever held.
Safety
Section titled “Safety”As [set].
unsafe fn read(r: *mut u32) -> u32Read a register.
Safety
Section titled “Safety”r must be a valid, aligned, memory-mapped register.
unsafe fn set(r: *mut u32, bits: u32)Set bits, leaving the rest alone.
Safety
Section titled “Safety”r must be a valid, aligned, memory-mapped register.
unsafe fn write(r: *mut u32, val: u32)Write a register.
Safety
Section titled “Safety”As [read].