Current system architecture

Directories and responsibility

Layer and directory

Owned responsibility

Dependency boundary

core/

Neutral results, absolute monotonic deadlines and caller-owned request state

C11; no Board, RTOS or SDK

arch/arm/cortex_m/、arch/native/

Compile-time Cortex-M/Native primitives, exception/privilege/mask queries, interrupt save/restore, barriers, cycle snapshots; explicitly selected Cache/MPU/SAU and Secure CMSE permission observation

Public headers remain in arch/include/nexus/arch/; no SDK/OS/SoC policy; primitive compilation and whole-platform qualification are recorded separately

soc/<vendor>/<family>/

Exact memory/clock/IRQ/startup, timebase and typed controller implementations for F103, GD303, F407, F470, G474, H743 and U575 under stm32/gd32

Private SDK/provider storage; each family exposes only maintained modes

drivers/<kind>/<ip>/

Shared UART, I2C, ADC, timer and Flash register-protocol algorithms reviewed for each participating chip

Compiled privately by the selected SoC target; no ownership of chip routes, clocks, Board or runtime registration

boards/<board>/board.json

Exact part, reviewed routes, declared crystals, safe initial values, provenance and unknown PCB facts

Read-only resource package; creates no product tasks

io/

Public includes, checked dispatch in src/api, shared rules in src/mechanisms, controller engines in src/controllers; private hardware boundaries

Public headers contain no vendor types; Native providers in soc/native/drivers establish behavior models

os/

Optional wait/wake and per-object static task/stack/TCB/queue adaptation

Drivers do not depend on OS or create application workers

components/

Explicitly selected generic owner, BMP280, Modbus, Storage and Log mechanisms; exact-chip extensions are maintained under components/soc/stm32

Access devices, time and external policy through narrow ports; chip-specific extensions do not broaden support for other parts

tools/、cmake/

Strict input parsing, one generated result, source SDK and ELF/qualification/HIL tools

CMake is the sole authority for code dependencies

External application projects

Product composition, tasks, policy, layout, budgets, recovery and business behavior

Pin an explicit platform version and own actual execution progress

The source contracts own the complete physical layout and adjacent READMEs. Vendor and ISA grouping changes only build-time source ownership; public includes, CMake targets and authored family identifiers remain stable. The public wait/wake port can connect across backends, while Task/Queue/join/static control blocks retain backend-specific APIs. Products switching RTOS explicitly adapt their lifecycle; no universal maximum pool is introduced.

SoC translation units are organized by controller kind/mode; one implementation serves multiple independent instances. Selecting one UART does not retain all peripherals, RTOS queues or maximum object pools. Startup/system sources are explicit firmware inputs; correct reset/vectors do not depend on unreferenced weak symbols in static archives. Strong provider IRQs enter the image only with selected implementations; section GC removes unused implementations.

CMake reads selected controller kind/mode from the same resolved result, querying selection facts only; each family’s CMake still owns source sets. Unselected drivers are not compiled, and endpoint base drivers are supplied by composition. Empty STM configurations compile no peripheral drivers; GD retains base SDK sources required by system/timebase. Final section GC removes unreferenced functions. Compilation trimming and image trimming are verified separately.

The G474 HSE24/170 MHz reference maintains static GPIO, six UARTs, SPI1/2, TIM3/4 PWM, IWDG and EXTI. A separate acquisition fixture selects ADC1 bulb shots/finite TIM6 DMA, I2C1 and physical Flash. ADC DMA admits SRAM1/2 only; CCM CPU/DMA aliases still count as one physical capacity and are excluded by the current policy. Each mode generates only its selected state, ring, block extension and IRQ entries; an empty assembly retains none of these peripherals. PA0/PA1 EXTI each have a caller-sized event ring and withdrawal responsibility. Failed construction cleans up in reverse order; refused withdrawal retains clock/pin/state ownership. Source, models and ARM linking do not establish reference PCB, analog timing, ThreadX G474 or physical qualification.

H743 and U575 add concrete M7/M33 SoC assemblies. H743 maintains LDO, fixed HSI32/HSI64 with Cache off/on, TIM2, PB0 and USART3 PD8/PD9. UART selects IRQ bytes, finite TX DMA or finite RX DMA-IDLE; owner service restarts RX with gaps. D2 SRAM1 can be explicitly budgeted beside default AXI SRAM. Startup copies DATA and clears BSS; callers initialize NOINIT, and DMA admits only initialized selected domains after rechecking their gate. Cache-on still requires complete exclusively owned 32-byte lines. A separate H743 software Board fixture selects SPI4, I2C1, ADC1, TIM3, EXTI, IWDG1 and Cache-off physical Flash. The default U575 Platform maintains externally confirmed TZEN=0, SWAP_BANK=0, MSIS4 MHz, Cache off, TIM2, PC7 and USART1 PA9/PA10. Its separate finite fixture adds SPI1, I2C1, ADC4, TIM3, EXTI and physical Flash; the actual power owner remains responsible for external VDDA/ASV and GPIO VDDIO2 admission. Both Platforms maintain baremetal/FreeRTOS without deriving other modes or PCB wiring from chip facts. H743 executes a separate bounded power entry before main RAM becomes writable. U575 also has a no-OS TZEN=1 dual-world reference: two Runtime images, a cold attribution owner and synchronous CMSE GPIO gateway, independent of the TZEN=0 factory. A second narrow SG entry copies up to eight PC7 commands into one Secure slot; SERVICE advances at most one item, and POLL/CANCEL/CONSUME use nonwrapping tickets. No NS pointer survives return and no asynchronous borrow is created. Neither U575 path writes option bytes; external provisioning must establish the dual-world boot state. See SoC refinement and the U575 dual-world contract. The initial record retains historical qualification; the extension record separately records later evidence.

F103/GD303 reuse compatible UART channel-DMA, I2C V1, ADC, PWM and halfword Flash algorithms through private legacy engines; each family checks official register ABI, clocks, IRQs and memory facts. TX-only UART state excludes the duplex RX-block extension; methods and direct IRQ entries are selected by mode. F103’s 16-bit TIM2 needs overflow service within 65.536 ms. GD303 uses a TIMER1/TIMER4 hardware cascade rather than assuming one low-word IRQ can recover a maximum 800 ms Flash erase stall. Actual timer carry, same-bank fetch stalls and kernel tick loss still require physical measurements; the time domain does not catch up kernel ticks.

Boards do not duplicate SoC drivers. GD32 I2C/PWM/ADC/EXTI routes and STM32 advanced-controller routes may compile/link in external Board packages explicitly marked software fixtures; this does not mean the three reference PCBs have matching verified connectors/electrical facts. Default Boards bind only routes with existing provenance.

Build and configuration

Current configuration chain: strict parsing and an atomic bundle enter the sole CMake target graph

Input/artifact relations for the current figure are in FIG-03 and source basis. Software evidence and physical qualification are obtained separately; see FIG-11. The sketch source below is retained only as historical migration input; its arrows cannot represent current HIL admission or completed verification.

Historical build sketch source:

flowchart LR
    S[精确 SoC facts/routes] --> R[严格 resolver]
    B[Board board.json] --> R
    A[外部 assembly/layout] --> R
    R --> G[原子 resolved/bindings/linker/budget]
    G --> C[CMake 显式 targets]
    V[锁定私有 SDK] --> C
    C --> E[真实 ELF/BIN/map]
    E --> M[LOAD/RAM/MSP/heap 门禁]
    E --> Q[clean-source 软件证据]
    Q --> H[独立实板资格]

One assembly selects Board, clock profile, OS backend, controller instances, bounded modes, capacities, IRQ priorities, endpoints and budgets. The generator creates only static hardware assembly, not tasks, business code or software dependency graphs. Unknown keys, invalid inputs/modes, pin/IRQ/timer conflicts and out-of-range capacities are rejected. Failed reconfiguration invalidates the old bundle instead of silently reusing a previous success.

SoC/Board facts use JSON; platform assemblies accept only schema-2 TOML. AuthoredAssembly retains frozen user intent. After strict validation of facts, modes and resources, resolve_ir() directly produces immutable ConfigurationIR. Production resolver, factory and emitters use named fields, without a Mapping interface or a second values copy of decisions. to_dict() derives resolved.json for audits and independent artifact checks; it cannot be fed back as configuration. The legacy schema-1 JSON assembly entry has been removed. Historical evidence retains its original format and read-only verification; it grants no qualification to current code.

IR identity, budgets and controller/endpoint/CPU/kernel/resource options use frozen records; IRQ is a nested record, and ADC channels/sample times are tuples. Original JSON hardware facts and identity-keyed readonly mappings remain explicit leaf data, and local resolver validation drafts may still use dictionaries. This does not give every JSON field a nominal type. source_fields records only projection-field presence, not duplicate decision values. Python typed source epoch is 2, while JSON projection remains schema 1; they have separate generations and do not change MCU C factory interfaces.

soc/<vendor>/<family>/configure/ (soc/native/configure/ for Native) explicitly owns ABI, mode-to-implementation selection, DMA routes, triggers, shared IRQ and CS contracts, static construction descriptions, IRQ forwarding and system-clock bindings. Concrete C11 adapters own hardware admission, register access and readback, prepare/start/stop, withdrawal and recovery. Generated Platform code preserves explicit calls and reverse cleanup; Python does not maintain hardware algorithms. The common resolver owns schema, facts, resources, input identity and output; common bindings assemble Nexus faces and uniform lifecycle progress. New SoCs must explicitly register their real provider module and maintain required CMake/SDK files. Unknown families and modes are rejected without a Native or Cortex-M4 fallback. Ordinary Boards reuse existing implementations without copying drivers; documentation matrices cannot determine configuration.

The explicit provider map and shared leaf contracts remain in tools/configure/providers/; configuration tests remain in tools/configure/tests/providers/<family>/. Shared IP source selection, configuration package placement and physical qualification are reviewed separately. This layout refactor does not expand supported modes; physical status remains not_executed.

ConfigurationIR.physical_part and ControllerIR.integration are named views of existing frozen facts and resource plans. They reuse the original Flash/memory, resource claim, DMA lane, IRQ and clock objects; they add neither JSON/configuration-identity fields nor another route resolver. F407 SPI and paired secondary-controller paths consume the integration, while other constructors can retain their existing adapters. A nominal APB frequency does not replace the reviewed clock-domain envelope. See the provider porting guide for field responsibilities and new-part checks.

Immutable family descriptors unify configuration entry, dependency identity and required SDK payloads. Controller descriptors reuse exact register bases, IRQ, DMA and pin facts; production-C SDK static assertions independently check them. clock.source/input_hz express real HSE/HSI/MSIS sources; legacy hse_hz is normalized only at parsing, without inventing external crystals for internal oscillators. Complex chips use dma_engines for actual per-master reachability rather than one boolean hiding differences. These are build-time facts, not a runtime registry/query layer or second source graph.

CMake Nexus::Platform exports configuration, typed factory and immutable interfaces. SDK headers/provider storage are visible only to implementation/generated binding TUs. Public consumption has no vendor-SDK ABI. External firmware explicitly adds startup/system/linker/resource checks through nexus_add_firmware().

The seven SoC family entries select the pinned official CMSIS-Core v6.4.0 CPU headers, while each family retains its locked vendor Device/startup and HAL/LL sources. The build target graph owns the internal nexus_cmsis_core and nexus_use_cmsis_core(target), distinct from the public neutral Nexus::Core mechanisms. Ordinary public consumers do not inherit vendor Core headers or types. The old Core bytes and notices in the GD32F470 import remain; the selected source is shared, and directory presence alone does not establish a compiler dependency. See vendor versions for version and license identities. This dependency migration does not change public Arch context, ownership or mask-restoration contracts, or automatically enable a new chip, profile or security domain. Actual include closure, ARM links, relocated-SDK consumption and physical qualification have separate acceptance scopes.

Fixed objects and execution

CPU primitives, privilege, interrupt masks and FreeRTOS startup contracts are in Cortex-M integration. Arch selects implementation at compile time without a runtime CPU factory; device typed factories/shared polymorphic tables remain. F407/F470 launch modes and limited G474/H743/U575 vertical slices are maintained separately. Nine-core CPU models/compilation cannot replace concrete SoC integration or physical verification.

Independent CPU runtime reads external runtime.toml/explicit cpu.json, reusing frozen CpuProfileIR and production CMake targets. nexus_add_runtime(ASSEMBLY ...) exports Nexus::Runtime with Config/ABI, Core, Arch, typed I/O faces and selected baremetal/FreeRTOS adapter. Installed find_package(Nexus REQUIRED COMPONENTS Runtime) exposes the same entry. There is no SoC/Board/startup/linker script/typed factory. External projects implement actual memory/clock/IRQ resources, device providers, security policy and final firmware. Nine-core FPU/MVE/cache/MPU/DWT/security/SAU are explicit facts; the parser selects legal combinations/exact kernel ports, never CMake-cache inference/override. Hardware/product qualification remains separate. Single-region MPU/SAU mechanisms alone provide neither user-task isolation nor split-world gateways. The U575 split-domain reference explicitly combines independent SoC ownership and external image partitioning; Runtime/default Platform does not generate it automatically.

ThreadX is a separate actual-kernel backend, selecting locked Eclipse ThreadX Linux GNU/Cortex-M4 GNU ports without reusing FreeRTOS configuration fields. Initial scope maintains three F407/F470 Boards, Native Linux and explicit M4-integer/M4F CPU runtime; other Cortex-M ports are rejected. Products enter the kernel with nx_threadx_kernel_enter(). Only real tx_application_define permits prestart task creation/reclamation. Abnormal return after a start attempt retains all effects and fail-stops; it cannot restore prestart reclamation. Linux uses actual pthreads/CLOCK_MONOTONIC kernel timers, but caller stack parameters are not actual host-pthread stack budgets. See ThreadX integration.

The factory/polymorphic skeleton is restored, with construction completed during generation. Each interface face has only const ops*/context*. Faces/operation tables are read-only; mutable provider state and selected per-instance buffers use independent static storage. Methods receive their own context rather than infer instances from operation-table addresses.

Generated nexus_factory.h defines assembly-local IDs. Typed functions such as nx_factory_uart() return existing objects only: no heap, hardware start, string lookup or locks. Invalid IDs return NULL. Lookup, nx_platform_start(), request borrow and stop are separate actions. Static handles are not revocable sessions; shutdown must settle callers, IRQs, owners and notification publishers.

Default factory IDs are class-named uint16_t; C typedefs do not prevent passing another class’s numeric value. Optional class-specific struct references prevent ordinary ID mixing, or read-only capability queries may be selected. Both return the same static objects without runtime registration/construction. Capability queries describe selected bounded modes, not current state, PCB electrical facts or admission. IDs are local to the current assembly, not persistent cross-version numbers. One external executor serializes start/stop without hidden platform locks. Public I/O has no uniform global-started check; contracts govern business exit/cleanup after start failure. Stop may withdraw some instances before returning BUSY; BUSY does not restore complete running state.

Cold startup first rejects observable external owners. GPIO assembly observes every selected bank gate, then every selected pin mode/lock, before saving leases/modifying pins; it cannot modify one bank then claim no effects on another-bank conflict. Controller routes and endpoint CS share this check. Unselected pins in shared banks remain externally owned.

H743 establishes fixed clocks/Cache from trusted reset or successfully completed owned clean/disable, never claiming unknown bootloader state from disabled CCR bits alone. Arch cold-Cache control retains owned I/D Cache and selector-recovery responsibility; only M7 is maintained. Finite UART DMA accepts only selected, initialized AXI SRAM or explicitly budgeted D2 SRAM1; unselected domains, TCM and an unready SRAM1 gate are rejected. Cache on requires exclusive complete 32-byte-line borrow. TX submission acquires PREPARING borrow before cleaning outside a long IRQ-masked section; cancellation cannot publish SETTLED before preparation ends. Platform stop drains providers, withdraws TIM2, cleans/disables Cache and restores the HSI divider in that order. Uncleared effects remain with original owners. This is cold lifecycle, not live frequency scaling.

Driver GPIO stop preserves declared safe idle. Full Platform stop restores selected-pin leases/releases gates only after all IRQ/DMA/caller references drain; failed restoration readback retains cleanup responsibility. Full release therefore does not promise active product-safe levels indefinitely. Products needing continued drive retain the platform owner or first exit under external power/safety policy. This is resource ownership, not built-in product shutdown policy.

Timebase publishes a valid epoch only after successful start. Startup excludes old UIF before observing a new UG update. Runtime ACK refusal invalidates time and boundedly withdraws interrupt sources instead of incrementing epoch. Regardless of isolation success, it retains terminal interrupt masking and calls fault observation; returned observers still halt, without zero-time deadline processing or releasing request/low-power borrows. Products may provide separately reviewed nonreturning recovery. Normal stop/restart/cleanup retries cannot recover this terminal path. Reads recheck epoch validity under the same mask to prevent entry-gap IRQ invalidation. Old deadlines cannot cross stop/failure/restart.

SPI/I2C controller factories return actual controllers; device factories return CS/address endpoints. A controller arbitrates all children and owns recovery, rather than borrowing the first endpoint as a bus alias. Different providers share public interfaces within one image but retain their own tables/state. Native generated objects no longer bind multiple names to one global model.

Public functions do bounded validation and shared-table calls. Providers may directly call their own implementation to avoid repeated dispatch in register hot paths. Components use public contracts; external projects own application roles/tasks/recovery. Compile-time instance selection means neither started hardware nor completed requests.

Private generated objects are named separately by port/endpoint/CS/buffer/platform state, preventing legal IDs from sharing storage with helpers. Device fields are transport-validated. I2C endpoints declare addresses, rejecting irrelevant SPI mode/frequency/generic capacity. devices generates bus endpoints and components selects libraries; applications explicitly construct device/owner instances.

Path

Resources and responsibility

Direct GPIO access

Authorized mask; one BSRR/BOP for set/reset; single writer required for toggle

Direct UART access

Caller request/payload; one execution owner; actual TC determines wire completion

SPI/I2C/Flash/ADC polling

Explicit CPU-active polling; bounded modes; only valid completed prefixes reported

UART/SPI finite DMA

Exact domains/channels; zero implicit copying; separate memory/line drain; retained borrows on failure

UART RX blocks

IRQ/IDLE; exact caller block arrays; immutable consumer loans; visible loss

ADC trigger blocks

Exact timer/DMA; stop per block; explicit service for stabilization/calibration/rearm; inter-block gaps

Multi-producer owner

Externally capacity-sized slots/storage; single admission; slot/epoch prevents stale cancellation of new requests

OS wait/wake

Sequence/predicate prevents lost wake; notifications are hints; clients do not service hardware

shutdown

Reject producers→keep executor draining→settle borrows/notification publishers→join→reverse interface release; running kernels retain clock/Tick and products choose park/reset

Flash geometry program_flags exposes ECC fresh-erase prerequisites to callers. A unit requiring fresh erase cannot be reused after a pulse merely because reads return FF. Failed/interrupted pulses require another erase; all-FF input issues no pulse. Every started pulse must obtain fresh completion evidence and actually drain before return or another pulse. A deadline cannot interrupt a hardware pulse. Products own supply declarations, writable regions, execution stalls, watchdog and power-loss recovery.

CAN uses three real mailboxes/shared filter domain. USB FS uses explicit endpoint/FIFO/event capacities, PIO packet loans and a separate 48 MHz owner. Ethernet uses caller-sized normal descriptor rings, RX loans and a narrow MDIO port. None contains protocol stacks/product workers. Capture/complementary PWM are separate from ordinary PWM and own exact timer/IRQ/break resources. SoC implementation, selectable routes, Board authorization and physical measurements are independently verified; public types alone cannot prove complete reference-PCB integration. See support.

Optional UserIoBroker admits only scalar GPIO read/set-reset through a privileged kernel gateway. Callers provide actual principals, memory pin/copy/unpin and bounded policy; user messages cannot select pointers/MMIO/trusted identity. Failed release retains mapping; cleanup does not replay GPIO. The independent OS-free U575 reference uses real SG for one fixed NonSecure-world principal, retains/masks NS IRQs and synchronously pins/copies under static attribution/no concurrent masters. Output-span prevalidation precedes GPIO effects. CMSE range checks observe permissions but do not alone guarantee borrowing. No generic SVC, multitasking userspace or asynchronous user-DMA transport is provided. Models/ARM instruction/layout gates confer no physical-isolation/electrical-safety qualification.

FreeRTOS lowpower_port = "timebase" explicitly selects F407/GD470 private shallow-Sleep timer adaptation; default custom retains application-port/weak-NULL behavior. The actual getter validates fixed PLL/timebase/IRQ state without repairing unknown configuration. Shared timers retain monotonic overflow; extra compare channels supply wake alarms only. Failed source withdrawal retains loans and fail-stops. There is no dynamic clock, STOP/deep sleep or default low-power worker. Software quantization-phase models are not measured power/timing. See shallow-sleep contract.

UART REJECTED borrows no request/buffer; ACCEPTED borrows until acquire-observed SETTLED. Providers detach before release-publication and cannot read requests afterward. Cancellation/timeout cannot release early. Unproven drain enters QUARANTINED and retains execution/recovery responsibility. TC-IRQ observation checks the absolute deadline; later service cannot overwrite earlier completion facts.

STM32 cancellation retains until actual TC drain. GD32 may terminate wire intervals by controlled USART reset; without observed TC, count=0 conservatively and RX loss results. Neither counts DR/DATA writes as completely sent bytes. Error-only RX/loss markers have NO_BYTE and cannot consume stale register data.

Performance and space

Default C11 paths have no heap/runtime registry/string lookup/hidden worker/mandatory OS lock/idle DMA-copy pool. RX/EXTI queues, OS objects, owner slots and component workspace are sized to selected instances. IRQs move bounded facts; bulk reads use short critical sections and ring hot paths avoid unnecessary dynamic division.

Resource tools calculate actual ELF Flash LOAD/footprint, each physical RAM domain, MSP, heap and unused-provider GC. O2/Os/O3/LTO selection uses measurements on the same workload, not source-line counts. Host-test time, assembly counts and actual MCU cycles/latency are separate. With no hardware, minimum cycles/completed physical timing budgets cannot be promised.

Fixed capacities still require worst-case critical-section measurement. Owner admission uses a free-head chain; submission/reusable-slot return are O(1); exhausted-epoch slots retire permanently. Streams count FILLING/READY/BORROWED through outstanding, making stop checks O(1); failures/duplicates preserve counts. Each Owner/stream logically adds one size_t, not per-slot storage. Actual Cortex-M4 compilation changes Owner control 80→84 B and stream 32→40 B, including 64-bit-epoch padding; slots remain 48/40 B. Cold initialization builds chains/zeros/checks overlap; overlap checks are O(n²), before startup without IRQ guards. Complexity does not prove cycles/IRQ latency; measure the same ELF. Default FIFO provides no priority preemption/deadline ordering; applications budget transaction lengths, service intervals and quarantine effects on later requests.

tools/measurement/interfaces.py audits retained faces/operation tables in actual ELFs. Non-LTO ARM faces occupy 8 bytes Flash/0 bytes RAM; providers share tables and independent state is accounted separately. Simple LTO workloads may remove entire faces/tables; arbitrary applications do not inherit that guarantee.

Testing and new-version qualification

New host contracts use pinned GoogleTest/GoogleMock; firmware stays C11. Framework/C++ runtime/dependency archives do not enter MCU images. Existing production-TU C register/fault regressions remain; new mocks replace hardware interaction, not owners/dispatch/generators under test.

TDD follows Red→Green→Refactor and retains failure evidence before new behavior. Commit hooks actually execute tests and validate complete discovery, fresh unfiltered XML and exits. Mechanical gates prove current execution, not every developer’s historical editing order. Formatting/backslash Doxygen retain existing rules.

This factory/TOML/polymorphic/SoC iteration inherits no previous-candidate qualification. Initial SoC execution binds historical code revision and covers no later extension. Extension execution independently binds corresponding source/results/raw evidence. Host gates, ARM matrices, installed SDK, external examples and offline reproduction are verified separately; documentation does not replace tested-code identity. New candidates have independent exit conditions. No hardware is connected; physical results remain not_executed.