Repository navigation
Build experimental original ESP32 execution, memory and I/O foundations - #115
Merged
Merged
Conversation
…ots ESP-IDF Two LX6 cores (core/mcu/xtensa/lx6.c, lx6fp.c) as core-isa.h configures the ESP32: windowed registers, loops, XEA2 exceptions, seven interrupt levels, CCOUNT/CCOMPARE timers, MAC16, booleans, single-precision FPU, region protection, the debug option; backend "xtensa" in build.c. The ESP32 description (catalog/mcus/espressif/esp32): the memory map, the ROM image built from Espressif's esp32_rev300_rom.elf (equal to QEMU's esp32-v3-rom.bin), the register file from esp32.svd, and models for DPORT (APP_CPU control, caches and flash MMU, interrupt matrix, the APP_CPU's own ROM view), RTC_CNTL, eFuse, APB_CTRL clocks, GPIO/IO_MUX with strapping, UART0-2, TIMG0/1, SPI0/1 and the GT25Q32A flash, SHA, the internal analog I2C, RNG and the AHB view. Espressif's ROM, ESP-IDF v5.4's second-stage bootloader and hello_world run unmodified to Hello world!
- emblink/esp32_devkitc: the DevKitC V4's power path (BAT760, AMS1117-3.3), power LED, Boot and EN buttons with EN's RC, both 19-pin headers, from Espressif's schematic; three fixtures - test_lx6: programs assembled by Espressif's assembler (gen_lx6_programs.py -> lx6_programs.h) check the core's instructions, windowed recursion through the ROM's window vectors, exceptions, the timer interrupt, FPU, MAC16, and the APP_CPU's ROM data - tests/vendor/esp-idf: esp32_hello_world built for the esp32 target - the description's fidelity and provenance, CHANGELOG, STATUS, coverage - a zero-overhead loop is not taken back when its last instruction branches to LEND (the ROM's strcmp); the DFP accelerator's user registers; no debug hooks in the core
The GPIO LED on GPIO2 (sdkconfig.defaults), an LED and 330 ohm on IO2: gpio_set_level through the matrix every second, 6/6.
run.py skips an example whose toolchain is missing rather than every example, and CI installs xtensa-esp32-elf with riscv32-esp-elf so the esp32_* examples run on the ESP32-DevKitC.
Eight high-speed and eight low-speed channels on four timers each (core/mcu/esp32/soc/ledc.c, the ESP32-C3's model on the ESP32's registers): REF_TICK, APB_CLK or SLOW_CLK over the 10.8 divider, up to 20 bits of duty, high-speed settings at the next overflow and low-speed ones after PARA_UP, fading, the overflow and fade interrupts, the matrix's ledc_hs/ls_sig_out. ledc_basic's 4 kHz on GPIO5: 2/2.
Datasheet v5.3 table 4-2: Modem-sleep of the dual-core chips at 80, 160 and 240 MHz (the range's low end waiting, high end running), 1 uA held; table 5-4's radio currents for when the radios are modelled.
The ESP32's I2C controllers from the C3's bit-level model on the ESP32's registers: 16 commands with its op codes (RSTART 0, WRITE 1, READ 2, STOP 3, END 4), the bus timing in APB_CLK cycles as i2c_ll counts it (SCL high + 7, or the filter's share), ACK_ERR, arbitration, the SCL timeout, the FIFOs through DATA and its AHB view, master and slave. The GPIO model gains the signal watch the controller follows the lines with, and DPORT's PERIP_RST_EN resets I2C0, I2C1 and LEDC. ESP-IDF v5.4's i2c_eeprom passes unmodified on the DevKitC with a 24LC256 (esp32_i2c_eeprom 3/3).
tools/validate.py rejected the ESP32's description: the schema had no xtensa backend and capped a port at 32 pins (the ESP32's GPIO bank has 40), Espressif's SVD lists fields that overlap (a whole-register STATUS beside its parts, two names for one bit), there was no gcc-xtensa toolchain profile, and the fidelity's validation entries were prose. svd2regs.py gains --resolve-overlaps (a field containing another taken out, of fields over the same bits the first kept, recorded in source); the ESP32's register file is regenerated with it, WIFI_CLK_EN kept as one field and the SVD's stray fields in CPUSDIO_INT1 and SAR_MEAS_WAIT2 reserved. The board and the MCU have their French text.
Three more of ESP-IDF's examples run unmodified on the DevKitC: gptimer (TIMG0, 17/17), uart_echo on UART2 (6/6) and real_time_stats across both cores (10/10, with IDLE0 and IDLE1). uart_echo echoed 128 bytes for each line: on the ESP32, ESP-IDF's uart_ll_get_rxfifo_len counts the bytes waiting from MEM_RX_STATUS's read and write addresses (the DPORT read's FIFO count is not to be trusted), and with both at 0 takes a nonzero count for a full FIFO. The UART model now moves the two addresses with each byte.
The ESP32's remote control peripheral from the C3's model on the ESP32's registers: eight channels each sending or receiving through the matrix (rmt_sig_out0-7, rmt_sig_in0-7), 64-word blocks of the 512-word RAM (added to the register file with svd2regs' --memory: the SVD leaves it out), the clock from APB_CLK or REF_TICK, end markers, continuous mode, wrap, TX_LIM, the carrier, the receiver's idle threshold and filter, CHnDATA, three interrupt bits a channel. ESP-IDF's get-started/blink with its LED-strip option runs unmodified on the DevKitC with a WS2812B on IO18 (esp32_blink_strip 7/7).
SENS's RTC controller's one-shot conversions on ADC1 (GPIO36-39, 32-35) and ADC2 (GPIO4, 0, 2, 15, 13, 12, 14, 27, 25, 26): MEAS1/2_START_SAR, the attenuation per channel, 9 to 12 bits, the converter's inverted output and DATA_INV, DONE after the conversion's SAR clocks. The transfer is the line ESP-IDF's Vref calibration fits for the chip, with the chip's eFuse Vref, so the calibrated voltage matches the pin's. ESP-IDF's adc/oneshot_read runs unmodified on the DevKitC with three sources (esp32_adc_oneshot_read 6/6: 1118 for 1.1 V, 2402 for 2.2 V, 433 for 0.5 V on ADC2).
Five sketches compiled for "ESP32 Dev Module" with Arduino-ESP32 3.2.0 run unmodified (tests/vendor/arduino-esp32, ESP32_*): AnalogReadSerial and ReadAnalogVoltage on VP, DigitalReadSerial, GetChipID (ESP32-D0WD-V3 Rev 301, two cores) and RepeatTimer stopped by the board's Boot button. Arduino turns on FreeRTOS's end-of-stack watchpoint, and its loopTask stopped at once with "Stack canary watchpoint triggered": the core took DBREAKC's MASK as the address bits ignored, where its set bits are the low bits compared (ESP-IDF's 32-byte watchpoint writes 0x20). test_lx6 gains a store watchpoint over 32 bytes, missed just past it and taken inside it.
(u32)PADS cut a 64-bit constant, which MSVC's /W4 /WX rejects; the low word is taken with a mask instead.
The branch register's bit is unsigned, the comparison's result an int: MSVC's /W4 /WX rejects the mixed ==.
RTC_IO's PAD_DAC1 and PAD_DAC2: with the pad the RTC IO MUX's and the DAC powered, GPIO25 and GPIO26 carry VDD3P3_RTC x code / 255 (the GPIO model hands the pad to the DAC as an analog output). ESP-IDF's dac/dac_oneshot runs unmodified on the DevKitC, its ADC2 reading both DACs back on their pads (esp32_dac_oneshot 4/4). For that the runtime's pin_volts gives a pin's own DAC voltage when its net has no analog part (it gave the digital level, so an ADC read 0).
ESP32 on the machine framework: LX6 cores, SoC models, DevKitC V4, ESP-IDF boots
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The requested board uses the original dual-core Xtensa ESP32, which is a different target from the existing ESP32-C3. This PR adds experimental execution, memory, storage and I/O foundations with explicit fidelity boundaries and reproducible compiler/vendor evidence. It does not register a complete runnable original-ESP32 board or establish native ROM-to-SDK application boot.
Current native ROM result: 6,902 retired instructions / 6,903 attempts with explicit synthetic eFuse/RTC/GPIO/UART-bank/mask-ROM/calibration fixtures and one supplied source-1 period containing 1,280 XTAL ticks, then an unsupported IO_MUX U0TXD read at 0x3ff49088, PC 0x40009156, opcode 0x498. The digital per-pin hold register now passes. The earlier 6,872 pad-hold failure is preserved against its prior source hashes, not relabeled as successful boot. The calibration period remains synthetic, not a physical capture or verified crystal detection. Positive reference-QEMU SDK boot remains separate from native EmbSIM and physical-board verification.
Implemented behavior
Native ESP32 image inspection: segment/header bounds, XOR checksum and optional SHA-256, with explicit unsupported-format rejection.
Experimental mixed-width Xtensa integer/control-flow execution, 64-AR register windows and spill/fill, hardware loops, MOVSP, selected system/task registers and compiler TLS, conditional stores/acquire/release, selected exceptions, interrupts and explicitly advanced compare-counter clocks. Unknown instructions stop with PC/opcode diagnostics.
Native shared internal-memory fabric, instruction/data aliases, optional externally supplied ROM, serialized two-core execution, DPORT interrupt routing, compiled cross-core mailboxes and bounded APP clock/stall/reset controls. Reset uses the hardware vector input; BOOT_ADDR is consumed by firmware rather than used as a host PC shortcut.
Separate per-core read-only flash MMU mappings, bounded cache control/flush contract, SPI1 byte/buffer transactions and completion source 29. Explicit named Winbond W25Q32JV-IQ and Giantec GT25Q32A-U array-protocol subsets support separately qualified identities, page programming/erase, WEL/BUSY and externally supplied operation time. Cache tags/coherence, full flash modes and physical timing remain unqualified.
Explicit 31-word None-coded eFuse image/read/reload profile, read protection, command-active state, external read-completion events and interrupt source 44. No factory identity/keys/calibration are invented. OTP/burn, other coding and hardware consumers remain unsupported.
ATOMCTL SR99: privileged read/write/exchange, six-bit state/reset, explicit memory-type classification, local-data-RAM atomics, RCW and cause-3 dispatch. Internal-cache/reserved modes and missing attributes fail unchanged.
Original-ESP32 Region Protection Option: eight identity-mapped 512 MiB regions in each ITLB/DTLB, all ten maintenance operations, reset/readback and ISYNC/DSYNC access-table commit. Fetch/load/store permissions dispatch causes 20/28/29 before the denied access; S32C1I checks store permission. The one-ring configuration masks PS/EPS.RING; local-port rights and the unsupported external cache-isolate boundary are explicit. This is distinct from a page-table MMU or the SoC flash cache.
Original-ESP32 MEMCTL bit 0 and a bounded functional 256-byte loop-buffer profile: reset/read/write/exchange, capture/replay of a declared loop prefix, ISYNC/disable/bounds/reset/exception invalidation, protected hits and failed-fetch/decode rollback. Direct and fetched CPU interrupt entry both invalidate. Exact silicon fill/replacement/fetch timing remains unqualified; the policy is not a cycle model.
Buildable physical-board cycle-measurement tooling: ESP-IDF v4.4.7/actual ESP32 GCC, nine IRAM kernels with preserved 24-bit body encodings, both cores sequentially, loop-buffer modes and 3,672 complete framed kernel observations. The firmware builds and produces a complete reference-emulator protocol in Espressif QEMU. Strict capture analysis is part of CTest, rejects incomplete/duplicate/bad data and never marks a timing model qualified. No physical board was programmed or measured, no emulator counter value calibrates silicon, and no guessed instruction-latency table was added.
Opt-in RTC reset-state/eight-word retention snapshots: raw causes are protected from software writes, vector selects and retained words are R/W, and both native CPU views share them. DPORT APP reset records SDK reason 14 after commit, samples the RTC APP vector and retains peer/RTC state. PRO reset production, full RTC/analog/power/global/watchdog/wakeup behavior remain absent. Initial cause/store values are explicit snapshot inputs, not inferred hardware history or undefined-register defaults.
Opt-in shared software GPIO: explicit routing/input/pull/open-drain/initial-latch fixture, OUT/ENABLE and W1 aliases, externally resolved inputs, input-only pins, and independently observable low/high/Hi-Z pad drive. Unknown enabled inputs and unsupported routing/accesses fail explicitly. DIG_ISO global force hold/unhold and externally supplied auto-hold events freeze output controls while input sampling remains live. RTC pad-specific hold, complete matrix/IO_MUX, interrupts, isolation/power/sleep transitions, electrical loading and graphical board integration remain unimplemented; the fixture is not a silicon reset or physical-board configuration.
Opt-in normal asynchronous UART0/1/2: default 128-byte FIFOs plus a separate transmitter, native APB/AHB access, externally advanced selected-clock ticks, fractional-divider carry, 5..8 data bits, parity and 1/1.5 stop bits, projected TX state/bit and completion offsets in 1/32 source-cycle units. CTS gates the next frame; externally decoded RX/error and qualified timeout events feed the receiver. W1C/enables/thresholds and sources 34/35/36 synchronize after instruction commit. Advanced modes, the SDK-documented unreliable RX-reset and two-stop-bit workaround paths, physical clock/pin/USB integration and full SoC reset domains remain unsupported. This serial-clock profile does not qualify CPU timing.
One shared 1024-byte FIFO RAM with TRM allocation bases, bounded block-size changes, real overlapping queued-byte overwrites, extended counts/cursors and high threshold fields. UART1 TX reset also resets UART2 while both serializers are idle; held reset blocks UART2 TX and invalid/active reset requests fail without partial changes. FIFO reset/host attach preserve RAM bytes. End-wrapping allocations, live resize, active reset effects and RAM power-down remain unqualified. The unchanged SDK RX drain helper is now checked on all ports with default allocations.
Explicit per-core SDK mask-ROM profile: exact supplied 448 KiB images, coherent IROM/DROM tail aliases, independent PRO/APP selection, low-ROM remap precedence, read-only/access boundaries, atomic replacement and legacy fallback. The SDK range/ROM symbols and pinned Espressif QEMU mapping justify this opt-in layout; the TRM-only 384 KiB view remains unchanged. Images/missing bytes are not fabricated by the API. Physical contents/authenticity, APP reset/SDK boot, cache coherence after debug image replacement and physical timing remain unqualified.
Opt-in TIMG0 RTC calibration counter/controller: explicit initial control/result, selected full-period XTAL-tick inputs, one-shot MAX/READY completion, single-period cycling, RO fields, rearm/stop/stalls and shared CPU buses. Firmware retirement/MMIO reads do not manufacture clock progress. Active zero MAX, multi-period cycling, simultaneous modes, pending one-shot retarget/resize, zero-tick intervals, overflow, TIMG1, physical clock/phase/gating/oscillator/reset domains and the complete SDK calibration routine remain unqualified. The compiled vendor evidence uses unchanged access macros, not substituted clock-enable/delay helpers.
Digital per-pin hold at RTC_IO_DIG_PAD_HOLD: the SDK-mapped 16 pads, one effective snapshot per routed pad, independent local/global/auto-hold causes and force-unhold handling. Adding/removing overlapping causes does not recapture/release an already held pad; resolved input samples remain live. OUT/OE/open-drain and modeled input/pull controls project captured values while live registers remain readable. RTC pad-specific hold, PICO-only GPIO20/undocumented bits, dual force-hold/unhold assertion, runtime IO_MUX/function/strength changes and physical peripheral pin paths remain unqualified. Invalid masks preserve the entire state.
Hardware and boot evidence
The owner’s physical esptool v5.6.0 readout identifies ESP32-D0WD-V3 v3.1, 40 MHz crystal, JEDEC C4 60 16 and 4 MB flash. Giantec’s GT25Q32A-U V2.5 manufacturer ID table matches; exact ordering/package/die revision, board netlist and full circuitry remain unresolved. The reported 3.3 V is a strapping setting, not an electrical measurement. Serial-download/RAM-stub success does not prove application boot. The unique MAC is omitted.
The native diagnostic supplies an external Espressif QEMU-distributed PRO ROM, an actual ESP-IDF v4.4.7 flash image, SDK-documented PRO PRID=0xcdcd and an explicit synthetic unprogrammed eFuse image. External read-completion opportunities every 64 instruction attempts are a declared artificial fixture, not physical read timing. No unknown-MMIO fallback or host PC shortcut is used. The native ROM completes instruction/data region setup and both barriers; readback and access tables are
[15,1,1,2,2,2,2,2]for both banks after instruction/data initialization. Functional MEMCTL advances beyond this setup; explicit RTC, active GPIO and normal UART0/1/2 fixtures now let the ROM pass the digital pad-hold register and UART initialization, then execute the extended ROM entry and calibration reads, passing digital per-pin hold and reaching UART0 IO_MUX setup. APP ROM boot remains unqualified.Historical seven-instruction no-eFuse failure, the immediate-completion ROM reset path, and later ATOMCTL/WITLB/MEMCTL blockers remain recorded with their original scope. They are superseded by the current hash-recorded diagnostic, not relabeled as successful boot. ROM/QEMU implementation bytes remain external test inputs.
ADR-030 fidelity answers
Validation
Digital per-pin hold: 3,455 additional native assertions, 4,096 independent per-pin/global transition turns, and 256 actual ESP32 C calls / 30,592 retired instructions / eight exercised unchanged SDK helpers on both CPUs. The fixture loads the real SDK mask-table
.rodata; input-mode/normal/open-drain outputs, overlap, force-unhold, live input and held controls are checked. The default nine-helper GPIO mode remains passing; together the two modes exercise eleven distinct helpers. Runtime IO_MUX/strength/function and physical voltage/current behavior are not qualified.RTC calibration: 919,967 native assertions, 19,208 independent period/result/READY comparisons, and 486 actual ESP32 C harness calls / 39,108 retired instructions / ten unchanged SDK access macros, on both core buses. All three selections, partial/completed windows, single-period cycling, stalled clocks, rearm, RO protection, unchanged invalid/overflow behavior and CPU-reset retention pass. Complete SDK calibration/clock-enable/delay functions and physical frequency/timing are not qualified by these harness calls.
Mask ROM: 1,170 native assertions, 18,840 independent per-core fetch/data/alias comparisons, and 1,024 actual ESP32 C calls / 16,896 retired instructions to two unchanged external ROM getters using the SDK structure layout. Distinct supplied PRO/APP images, byte/word boundaries, legacy replacement/fallback, copy isolation, allocation failure and leak-free teardown are checked. This qualifies mappings/getters, not the compression engine, all ROM routines, physical ROM contents or APP reset/SDK boot.
UART bank: 271,883 additional native assertions over every supported size pair on all ports, 4,096 independent shared-RAM/cursor/count/IRQ referee turns, and 384 actual ESP32 C interactive calls / 160,128 retired instructions / twelve unchanged SDK helpers, across all ports on both CPUs. Tests exercise physical-layout byte overlap, extended thresholds/counts, idle shared reset, unchanged failures, source ownership/OR behavior and the SDK drain/no-op-reset procedures. Serial ticks/decoded frames remain explicit inputs; these are not hardware captures.
UART0: 915,199 native assertions, 316,077 independent half-bit/frame/completion-offset comparisons, and 128 actual ESP32 C interactive calls / 44,032 retired instructions / eleven unchanged SDK helpers, on both native core buses. FIFO limits/wrap, CTS gating, errors, interrupt latches, fetched enable-store/next-instruction IRQ entry, fractional/chunked timing and reset retention are checked. Source ticks and decoded RX are explicit inputs, not physical captures or CPU-cycle inference.
GPIO and pad hold: 3,313 native assertions, 2,048 independent latch/pad comparisons, and 216 actual ESP32 C interactive calls / 25,380 instructions / nine unchanged SDK helpers, on both native core buses. Host input and auto-hold events are supplied between firmware execution turns; no host PC shortcut or fabricated sleep transition is used. SDK GPIO20 is a logical register slot, not evidence of an exposed pad on the owner’s board. Write-only alias reads and unsupported high-bank SDK read/modify/write paths remain unqualified.
RTC: 53,787 native assertions, 1,281 pinned field/retention/reset comparisons, and 256 unchanged external PRO-ROM rtc_get_reset_reason calls / 1,792 instructions on native buses. All raw cause-bit patterns exercise field width only, not thousands of physical reset producers. Final hole-access cases rerun successfully under sanitizers. Existing reset/control/mailbox/CPU/flash regressions pass.
MEMCTL: 268,232 native assertions, 96 independent GNU register comparisons, 20 actual ESP32 C calls / 20 compiled hardware loops / 2,332 retired instructions. Final direct-IRQ invalidation cases and coupled IRQ/IPI tests rerun successfully under ASan/UBSan/leak checking.
Timing-capture tooling: real SDK/toolchain build, ELF verification of IRAM placement/nine hardware loops/eighteen CCOUNT reads, complete 3,672-sample QEMU control-flow/protocol run, strict analysis acceptance and four protocol rejection/coverage tests. Counter values are unqualified emulator observations; reports always retain
timing_model_qualified: false. Physical measurement, instruction/pipeline/bus/clock timing calibration and full native SDK boot remain open.58 selected native/protocol CTest targets pass; 34 focused ASan/UBSan/leak-check targets pass. The extended per-pin C fixture was rerun after correcting its exercised-helper count; unused definitions are excluded. Latest-head cross-platform CI is pending; Clang/TCC/MSVC are not available locally. Corrected the prior Windows fixture signed/unsigned comparison warning.
Region protection: 17,068 native assertions, 266,240 independent GNU instruction/register/alias comparisons, and 32 actual ESP32 C maintenance calls / 480 retired instructions, on both cores with native buses and restored data permissions.
Atomic control: 23,665 native atomic assertions, 3,072 GNU register comparisons, 128 actual ESP32 C calls / 2,816 retired instructions.
Shared base decoder: 4,800 assembled execution cases and 1,152 rejected accesses rerun successfully. Twenty-seven affected existing external regression runs pass across compiler windows/system/atomics, native dual-core spinlocks/mailboxes, controls/reset/vector/PS/clock, mapped flash, TLS/dynamic stack, SPI programming, eFuse, ATOMCTL, MEMCTL, region, RTC, GPIO, UART-bank, mask-ROM and RTC-calibration fixtures.
Programming regression includes 32 Giantec-programmed RAM workers, 32 exact replays and 432 firmware-observed BUSY reads; eFuse includes 3,968 register/protection comparisons and 128 actual C helper calls / 6,208 instructions. Earlier flash/CPU evidence and bounded omissions remain documented.
174 documents / 119 requirements, zero docs/banned-text/source-path/whitespace problems. Coverage regenerated; owner commit-identity policy passes. No assistant/coauthor trailers.
Primary contracts and reproduction: target investigation, region protection, atomic control, eFuse, Giantec storage, and hardware/boot verification.
Additional contracts: MEMCTL/functional loop buffering, instruction timing qualification, RTC reset-state and retention, software GPIO and global pad hold, normal UART0, UART bank/shared FIFO RAM, per-core SDK mask ROM, TIMG0 calibration counter, and digital per-pin hold.
The RTC follow-up uses
--rtc-power-on-fixture: raw reason 1 and vector select 1 for each core, plus all eight retention words explicitly zero. The GPIO follow-up adds--gpio-active-fixture: explicit zero output/control words and no routed physical pads, with supported active DIG_ISO controls. The UART0 follow-up uses--uart0-active-fixture; the bank follow-up uses--uart-bank-active-fixtureinstead: explicit empty default disjoint allocations and RXD=1/CTS=0/DSR=0 on all three ports, with no serial-clock advancement. The ROM follow-up adds--mask-rom-profile, supplying the PRO image and explicitly padding only its absent reference-image tail like QEMU; those padding bytes are not measured silicon content. The calibration follow-up adds--rtc-cal-fixture(control 0x13000, prior result 0, no automatic periods) and optionally--rtc-cal-initial-period-ticks 1280(one explicit source-1 event before PRO execution). These are synthetic initial inputs, not the owner's measured RTC/GPIO/UART/ROM/oscillator state. Unknown MMIO remains unsupported; no blanket reset/default/zero fallback was added. The GPIO fixture now includes qualified digital per-pin controls; the next observed boot blocker is IO_MUX U0TXD at 0x3ff49088. No unknown-register fallback or host PC shortcut bypasses it. Complete SDK boot and calibrated instruction timing remain unverified.