P31 keeps the P30 platform and changes the software shape again. The reset
entry is still assembly, but it now clears .bss, installs mtvec, and calls
a freestanding C main().
Status: RTL pass. The compiled C runtime test passes, and the scoped ACT4/Sail
rv32i/Ibatch still passes withPASS=39 FAIL=0 NOT RUN=0. Hardening and official privileged tests are NOT RUN for this rung.
The Result
Run it:
make -C projects/31_rv32i_c_runtime_probe/test
Result: PASS
| check | result |
|---|---|
| Build linked C runtime ELF | PASS |
| UART-load compiled image | PASS |
Clear .bss before main() | PASS |
Call C main() from reset assembly | PASS |
| Exercise C function calls and globals | PASS |
MMIO UART writes C, T, E | PASS |
| MMIO timer interrupt visible to C | PASS |
| External interrupt visible to C | PASS |
Halt with x5 = 1 | PASS |
ACT4/Sail rv32i/I: PASS=39 FAIL=0 NOT RUN=0
Harden status: NOT RUN
Runtime Shape
| piece | behavior |
|---|---|
runtime/link.ld | places text, data, and BSS in low external RAM |
runtime/start.S | reset entry, BSS clear, trap glue, call into C |
runtime/main.c | freestanding C platform probe |
runtime/build/c_runtime.elf | generated linked ELF |
runtime/build/c_runtime.memh | generated byte image for the UART loader |
The runtime targets rv32i_zicsr: base integer plus CSR instructions. The C
file itself is normal freestanding C, but the startup/trap glue still needs
machine CSR access.
What Changed
P30 stopped hand-encoding the program. P31 stops keeping the program entirely in assembly.
P31 adds:
- a C
main()reached through the assembly reset path; - C-visible BSS globals used by the trap handler;
- volatile MMIO access from C;
- simple stack/function-call behavior from compiler output;
- a linker map artifact for inspecting placement;
- a no-RWX-segment linker layout so the bare-metal build is quiet.
The generated C runtime binary is small: 540 bytes in the current build. That is intentionally modest. This rung is about proving the path, not writing a firmware library.
What This Proves
The compiled runtime:
- boots from address zero after the UART loader releases the CPU;
- clears
.bssbeforemain(); - uses C globals and volatile scratch storage in external RAM;
- writes
Cto the MMIO UART; - programs the MMIO timer from C;
- takes a machine timer interrupt and returns through
mret; - observes the timer flag from C, writes
T, then enables external IRQ; - observes the external IRQ flag from C and writes
E; - returns
1, which the assembly glue copies intox5before halting.
The scoped ACT4/Sail run still matters because the RTL shell is the same
base-integer core lineage. The base integer batch still passes:
PASS=39 FAIL=0 NOT RUN=0.
Scope
Still unsupported: libc, heap allocation, constructors, broad ABI stress,
supervisor mode, vectored mtvec, delegation CSRs, satp, an MMU, and
official privileged architecture tests.
So the honest label is narrow: PASS for the compiled C-runtime RTL test,
PASS for scoped ACT4/Sail rv32i/I, NOT RUN for hardening, and NOT RUN
for privileged compliance.