This lesson has one job: get every fuse value to its consumer before that consumer's first use. The array read is slow and sequenced, the PLL needs trim before lock, the wrappers need repair before the first test or access, and the ROM reads boot configuration in its opening steps. A consumer released before its fuse value arrives starts life on a safe default at best and on garbage at worst.
Read-out runs inside the reset sequence, in one window: it starts when the oscillator is ready (cycle 1024 of clk_per) and runs during the PLL start-up and lock window (260 clk_per, 10.833 microseconds, which starts at cycle 1026). The fuse controller walks the array, shifts each field into its shadow register near the consumer, and raises a done flag that gates the downstream releases. Shadow registers are ordinary flops, so timing analysis treats them like any other path, and the array itself powers down after the read to save leakage. The shadow registers live in PD_AON, the always-on domain: SLEEP removes power from PD_SW, but the shadows keep their values and drive the repair pins of the SRAM wrappers across the domain boundary (always-on to switchable wires need no isolation clamp; the clamps cover the other direction). That is why the 14.073 microsecond wake sequence has no fuse re-read in it. If the shadows were in PD_SW, wake would have to re-read the array and the 14.073 microseconds would grow by the read time. The ordering constraint is absolute: trim before lock, repair before the SRAM wrappers leave reset, boot configuration and secrets before the CPU's first fetch, and the version field before the first authentication. With an illustrative 256-bit array read at 8 bits per peripheral clock, the whole read costs 32 clocks or about 1.333 microseconds and ends at cycle 1056, long before the PLL locks at cycle 1286, so it never extends the boot.
The script uses the boot ledger's reset times in units of clk_per cycles: the oscillator is ready at cycle 1024, the PLL window ends with lock at cycle 1286, the system reset is released at about cycle 1292.5 (step 6) and the CPU reset at about cycle 1294.75 (step 7). It reads the array at three assumed widths and checks every consumer. The slowest case must fail.
array_bits = 256
osc_ready = 1024
pll_lock = 1024 + 2 + 260
rst_sys = pll_lock + 2 + 4.5
rst_cpu = rst_sys + 2.25
consumers = {"trim (before PLL lock)": pll_lock, "repair (before SRAM wrappers leave reset)": rst_sys, "boot config and secrets (before CPU fetch)": rst_cpu}
def check(clocks_per_bit_group, bits_per_group):
cycles = array_bits // bits_per_group * clocks_per_bit_group
done = osc_ready + cycles
late = [name for name, need in consumers.items() if done > need]
return cycles, done, late
cycles, done, late = check(1, 8)
assert cycles == 32 and done == 1056 and not late, (cycles, done, late)
assert abs(cycles / 24e6 * 1e6 - 1.333) < 0.002
print(f"8 bits per clock: {cycles} cycles, done at cycle {done}, ends before lock at {pll_lock}")
cycles, done, late = check(1, 1)
assert cycles == 256 and not late
print(f"1 bit per clock: {cycles} cycles, done at cycle {done}: still early enough")
cycles, done, late = check(2, 1)
assert cycles == 512 and late and "trim (before PLL lock)" in late, late
print(f"1 bit per 2 clocks: {cycles} cycles, done at cycle {done}: LATE for {late}")
print("PASS: the 32-cycle read beats every consumer; the 512-cycle read is caught missing the PLL lock")The reset sequence diagram shows the fuse read with its start (oscillator ready), its end inside the PLL window, its done flag and every release the flag gates.
Each shadow register names its fuse field and its consumer; unconnected shadows are a review finding.
Safe defaults are documented per consumer for the window before read-out completes.
Simulate reset with the fuse model delaying done past each consumer's release in turn and confirm the release waits: a consumer that starts early has its gate wired to the wrong flag. Then corrupt one shadow register after read-out and confirm only its consumer misbehaves, proving distribution fans out without cross-talk.
Because it runs inside the 260-clock PLL start-up and lock window that the reset sequence already pays: it starts at cycle 1024, ends at cycle 1056 and the PLL does not lock until cycle 1286. Work inside an existing wait is free; only work on the critical path costs.