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/

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

No SDK/OS/SoC policy; primitive compilation and whole-platform qualification are recorded separately

soc/<family>/

Exact memory/clock/IRQ/startup, timebase and typed-controller implementations for F407, F470, G474, H743 and U575

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

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/

Typed polymorphic contracts, shared operation tables, DMA/stream/wake; optional CAN, USB, Ethernet and advanced-timer contracts

Public headers contain no vendor types; Native is a behavior model

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

Access devices, time and external policy through narrow ports

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

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 actual generated factory, clock/GPIO/LPUART/EXTI algorithms and baremetal/FreeRTOS ARM fixtures for empty/GPIO-UART/selected-EXTI. PA0/PA1 EXTI use separate caller-sized event rings and own interrupt-source withdrawal. Empty configurations have no GPIO/UART provider. Selected LPUART IRQ91 and system TIM2 IRQ28 bind actual vector bytes. FreeRTOS retains real SVC/PendSV/SysTick; 170 MHz and 1 kHz Tick correspond to reload169999. Start rejects occupied LPUART control registers before changing clocks. Failed construction cleans in reverse order; failed withdrawal retains clock/pin/state responsibility. These are independent development evidence, not reference-PCB, physical-timing or ThreadX-G474 support.

H743/U575 add concrete M7/M33 SoC assemblies. H743 maintains LDO, fixed HSI32/HSI64 × Cache off/on, TIM2, PB0 and USART3 PD8/PD9; RX remains IRQ bytes while TX selects IRQ or bounded DMA. Default U575 Platform maintains externally confirmed TZEN=0/SWAP_BANK=0, MSIS4 MHz, Cache off, TIM2, PC7 and USART1 PA9/PA10. Both Platforms maintain baremetal/FreeRTOS and derive no other peripherals automatically from chip facts. H743 runs an independent bounded power entry before main RAM is writable. U575 separately has an OS-free TZEN=1 reference: two Runtime images, cold-ownership owner and synchronous CMSE GPIO gateway, independent of TZEN=0 factory. Neither path changes option bytes; split-domain startup requires external preconfiguration. Exact scope is in SoC refinement contracts and U575 split-domain contract. Initial execution retains historical qualification; extension execution records later evidence separately.

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 and consumers author schema-2 TOML. A strict resolver produces immutable typed IR consumed by every generator. resolved.json serializes that result and is not hand-authored configuration input. Migration schema-1 JSON fixtures have explicit entry points and are not overlaid with TOML.

IR identity, budgets and controller options use frozen records; IRQ is nested, ADC channels/sample times are tuples. Full JSON-fact projections retain read-only mappings, so not every field has nominal strong typing. tools/configure/providers/<family>/ owns ABI, mode→implementation, DMA routes, triggers, shared IRQ/CS contracts and constructor/rollback/IRQ/system-clock generation. The common resolver owns schema/facts/resources/input identity/output; common binding code orchestrates Nexus faces and lifecycle progress. New SoCs require explicit actual provider registration and maintained CMake/SDK payloads. Unknown families/modes are rejected rather than inheriting Native/Cortex-M4 defaults. Ordinary Boards reuse implementations without duplicating drivers; documentation matrices cannot determine configuration backward.

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().

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. Selected TX DMA accesses AXI SRAM only and requires exclusive complete 32-byte-line borrow with Cache on. 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

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.