Most of the 32-bit address space on NanoSoC is nothing: four holes cover nearly everything outside the ROM, the SRAMs and the peripheral window. Nothing is not one thing, though. Three of the holes answer with one kind of error and the fourth with another, and the DMA answers at sixteen addresses where the map shows one slot. Bring-up software that probes around to see what is there discovers this the confusing way. This lesson walks every empty space so the error lesson later can build on it.
Holes H1, H2 and H4 sit where no decoder claims the address: between the ROM and SRAM0, between SRAM1 and the peripheral window, and above the peripheral window to the top of the address space. The interconnect default slave answers all three with DECERR, starting one clock after the address handshake and then one beat per clock while the master is ready. Hole H3 is different: it sits inside the peripheral window at slots 7 to 15, so the APB slot decoder does claim it and its own default slave answers with PSLVERR, which the bridge turns into SLVERR. Same emptiness, different responder, different response code; the error lesson turns this into a diagnosis table.
Alias A1 is born inside the DMA slot. The slot is 4 KB wide with 12 offset bits, but the DMA block only has an 8-bit address port, and the wrapper passes through apb_paddr bits 7 down to 0 while dropping bits 11 down to 8. The 256-byte register window therefore repeats sixteen times across 0x4000_0000 to 0x4000_0FFF: offset 0x100 reads the same register as offset 0x000. Every other offset inside each image is genuinely unmapped and answers PSLVERR, because the DMA decodes all eight bits and implements only offsets 0x00, 0x04, 0x08, 0x0C and 0x10. Software uses only the first image, 0x4000_0000 to 0x4000_00FF, and a lint rule plus a connectivity test check that no slave input depends on apb_paddr bits 11 down to 8.
Empty space | Addresses | Who answers | Response | Software rule |
|---|---|---|---|---|
H1 | 0x0000_4000 to 0x1FFF_FFFF | Interconnect default slave | DECERR | Never probe; a fetch here is a linker-script bug. |
H2 | 0x2002_0000 to 0x3FFF_FFFF | Interconnect default slave | DECERR | Never probe. |
H3 | 0x4000_7000 to 0x4000_FFFF | APB default slave via bridge | PSLVERR, seen as SLVERR | Reserved for later peripherals; do not use yet. |
H4 | 0x4001_0000 to 0xFFFF_FFFF | Interconnect default slave | DECERR | Never probe. |
A1 alias images | 0x4000_0000 to 0x4000_00FF, repeated at 0x4000_0100, 0x4000_0200 ... 0x4000_0F00 | The DMA itself | Normal response | Use only the first image; the rest are an accident of wiring. |
Reserved means three things on NanoSoC. First, the 1 KB stranded in each peripheral slot stays empty so a register block can grow without moving its base. Second, hole H3 stays empty so a future peripheral takes a free slot instead of shifting the map. Third, production software never probes any of it: not to detect peripherals, not to size memories, not out of curiosity. Probing belongs to the test environment, with a timeout on every access. Probing is how a benign reserved region turns into a bus error in the field, or worse, into a dependence on an alias that a later revision removes.
Aliases are harmless until software or verification depends on one. A driver that reads DMA STATUS from 0x4000_0104 works perfectly, and keeps working until a cost-reduced device wires the slot fully and the same address becomes a different register or an error. A connectivity test that only touches aliased addresses passes while the true base path is broken. The standing rule is cheap to state and to check: every address in headers, tests and linker scripts must lie in the canonical first image, and the checker that proves it is a one-line range test per address.
Every hole has a named responder and a response code, matching the error lesson's table exactly.
The alias images are drawn on the map as aliases, not as free space, with the canonical range marked.
No header, linker script or test in the tree references an alias image or a reserved slot.
In the test environment, never from production software, sweep the map with a timeout on every access, one word per region plus one per hole, and confirm each answers as the table says: data from the mapped, DECERR from H1, H2 and H4, SLVERR from H3. Read the DMA CTRL register from 0x4000_0000 and from 0x4000_0100 and confirm both read the same value; that is the alias made visible. If a hole answers differently, the decoder changed without the map changing, which means the generation flow is broken, not the map.
It reaches DMA STATUS: the slot base 0x4000_0000 plus image offset 0x200 plus register offset 0x04. It works, but it is not legal by the project rule, which allows only the first image at 0x4000_0004.