Teams optimise the reset sequence to save a microsecond while the SPI load burns eleven milliseconds unexamined. The NanoSoC boot budget exists so that no such argument happens twice: every step is priced, the shares are computed, and the one step worth optimising is named. This lesson reads that budget the way an integrator defends it.
Hardware reset is 53.948 µs, 0.43 percent of boot. The UART banner at 115,384.6 baud costs 1,386.667 µs, 11.0 percent, for sixteen characters. The 8 KB image load over 6 Mb/s SPI costs 10,928 µs, 86.9 percent, and dominates everything. The DMA self-test, the checksum pass and the register setup together cost barely 2 percent. The script below recomputes the shares from the NanoSoC boot table: anyone proposing to speed up boot must beat the SPI link, compress the image, or boot from a faster source, because nothing else moves the total.
# Boot budget shares, NanoSoC teaching values (NanoSoC boot table, microseconds).
steps = {"hardware_reset": 53.948, "first_fetch": 0.125, "stack_clear": 10.667,
"rstcause_rd": 0.28125, "uart_init": 0.84375, "banner": 1386.667,
"dma_selftest": 8.385, "spi_load": 10928.0, "checksum": 192.0}
total = sum(steps.values())
assert abs(total - 12580.917) < 0.001, total # 12.581 ms
assert abs(steps["spi_load"] / total - 0.869) < 0.002
assert abs(steps["banner"] / total - 0.110) < 0.002
rest = total - steps["spi_load"] - steps["banner"]
assert abs(rest / total - 0.021) < 0.002
assert steps["hardware_reset"] / total < 0.005
# Target: halve the boot time. Image halved (4096 bytes + 4 command bytes);
# the checksum covers half as many words.
spi_half = (4096 + 4) * 8 / 6.0 # us at 6 Mb/s
sum_half = steps["checksum"] / 2
image_only = total - steps["spi_load"] + spi_half - steps["checksum"] + sum_half
assert image_only / total > 0.5 # halving the image alone MISSES the target
assert abs(1 - image_only / total - 0.442) < 0.002
# Banner at an illustrative 4x baud rate: 160 bit times at 4 x 115,384.6 baud.
banner_fast = steps["banner"] / 4
both = image_only - steps["banner"] + banner_fast
assert both / total < 0.5 # image plus baud meets it
assert abs(both / total - 0.476) < 0.002
print("PASS: boot 12.581 ms; SPI 86.9%, banner 11.0%; image alone cuts 44.2%, image + baud 52.4%")The boot budget table is versioned with the map and the clock table, because any of the three moves its numbers.
The dominant step is named with its share and its physical cause: SPI bit rate times image bytes.
Any boot-time requirement is traced to a step that can actually move it; requirements against the hardware 0.43 percent are sent back.
Measure boot with a timer from POR release to the jump, then compare each step against the table: the SPI load is the canary, and a slowdown there means the SPI clock divider or the board, not the ROM. If the banner prints garbage, the UART baud divisor was computed for the wrong peripheral clock; 24 MHz over 16 times 13 is the combination NanoSoC uses to get 115,384.6 baud.
Halving the image alone saves about 5,557 µs (the SPI load and the checksum both shrink), a 44 percent cut, not 50. The 16-character banner, 11.0 percent of boot, is the next largest term and does not shrink with the image: raise the baud rate (illustratively four times) and its 1,386.7 µs falls to 346.7 µs. Together the total drops to about 5,984 µs, 47.6 percent of the original, which meets the target. Then check that any decompression time still fits; the reset sequence cannot help by more than half a percent.