Nexus next-generation platform: design from first principles¶
Status: Current factory + polymorphic platform architecture contract; see current delivery for implementation and acceptance mapping. Code uses TOML static assembly, pure typed factories, shared read-only method tables, separate private instances and explicit ownership boundaries. Pseudocode explains contracts; current public headers/tests define compilable interfaces. Software execution, offline reproducible builds and physical qualification are recorded separately. The historical architecture is migration context only.
This iteration implements design, engineering rules, integration contracts and the 33-item checklist in new production code/build chains. New source/artifacts establish independent qualification; historical passes do not carry over.
The user requires existing code formatting/comment style. Architecture may change, while layout, naming and Doxygen retain repository configuration and contribution/comment guides. Better contract content improves maintainability.
Companion material: engineering handbook, integration contracts, base execution checklist and factory/TOML/TDD P0–P5 checklist. Experimental results may revise decisions; architecture proposals do not replace experiments.
1. 平台要解决的问题¶
An MCU platform connects fixed hardware, concurrent execution and finite resources so products can reuse trusted implementations. Establish facts/constraints first, then decide which abstractions justify their cost.
First-principle fact |
Design consequence |
|---|---|
Firmware usually targets one exact chip and PCB. |
Bind CPU, registers, pins, clocks and DMA routes at build time. |
RAM, Flash, bandwidth and execution time are finite. |
Every object has provenance, capacity, lifetime and a budget; allocate only enabled resources. |
Peripherals and buses are real shared resources. |
Establish static write authority and one bus executor; arbitrate shared requests within bounds. |
IRQ, DMA and deferred work can outlive the calling function. |
Borrow requests/buffers until every user has settled. |
CPU time, RAM, Flash and power consumption trade off. |
Compare Pareto candidates after satisfying constraints; one compiler flag cannot prove absolute optimality in every dimension. |
Enterprise projects require parallel maintenance and repeatable delivery. |
Keep boundaries narrow, facts authoritative, tools pinned, failures diagnosable and artifacts consistent with evidence. |
C types/static planning do not isolate malicious native code. |
Programming contracts and hardware isolation are separate promises; MPU/security domains need separate implementations. |
Tasks, updates, manufacturing and health policy vary by product. |
Platforms provide mechanisms/ports; external products own policy and qualification. |
Priority: satisfy correctness and hard product constraints; reduce necessary runtime cost; reduce reserved resources; reduce integration/maintenance cost. Premature DMA-buffer return, missing errors and unchecked bounds cannot buy better benchmark numbers.
First-stage scope: Cortex-M4F, STM32F407ZG Qiming Xinxin V3.1, STM32F407VE Sky Star Youth and GD32F470ZG Liangshan Pi; bare-metal/FreeRTOS backends and Native behavior models. Discovery may remain a development reference without becoming a product dependency. Exact parts, routes, modes and evidence are managed separately.
Existing controller support, pin sources and fault tests identify requirements only. New implementations may replace poor structures directly. With no connected hardware, first-stage delivery covers software and HIL tooling preparation.
1.1 Existing systems and selection rationale¶
The following compares common mechanisms and their conditions. Trimming, compilers, configurations and workloads affect cost; performance rankings require equivalent experiments.
System |
Applicable mechanisms |
Implications for Nexus |
|---|---|---|
Vendor SDK + handwritten BSP |
Direct single-chip control and small handwritten static initialization. |
Keep hardware-close expression; the platform supplies cross-chip contracts, planning and failure semantics. |
Zephyr |
Devicetree hardware descriptions, configuration and a unified device-driver model. |
Use build-time resource descriptions/capability checks. Runtime device sets and product needs determine whether a unified device model is useful. |
FreeRTOS |
Kernel mechanisms with application-provided static task/object storage. |
Use real kernels and per-object capacity; HAL, hardware facts and scheduling remain separate rather than making the kernel the device hub. |
RT-Thread |
I/O registration, lookup, open/close and unified access. |
Pay identity/lifecycle cost only where dynamic access has value; fixed ports use narrower contracts. |
Embassy/Rust async |
Compile-time-sized static tasks and explicit asynchronous execution. |
Use actual-state allocation and explicit execution responsibility. Keep the C ecosystem initially and enforce buffer borrowing/DMA settlement through contracts and fault validation. |
Official mechanism references: Zephyr Devicetree, Zephyr device model, FreeRTOS static task API, RT-Thread I/O framework and Embassy executor. These guide architectural tradeoffs; formal dependencies still need pinned revisions and separate acceptance.
Two SoCs, three Boards, fixed BOMs, ten maintainers and C product consumers favor build-time hardware descriptions, link-time implementation selection and only actual execution/borrow state at runtime. High-frequency fixed industrial outputs and enterprise runtime discovery are different problems with different cost models.
2. 默认运行模型:静态装配、固定绑定、最小驱动¶
Products select resources, components, modes and capacities at build time. Startup configures hardware; RUN keeps port identities, routes and write authority stable. Drivers retain actual peripheral runtime state and request borrows.
The default has no generic registry, runtime probing, per-pin open/close/ref, global inheritance tree or hidden threads. Fixed resources can still fail; drivers manage BUSY, FAULT, cancellation, draining and controlled recovery.
Three paths have different costs:
Path |
Work |
Cost constraint |
|---|---|---|
Build time |
Selection, conflicts, capabilities, static binding, capacity and link layout. |
Extensive checks are allowed without entering hot firmware paths. |
Control path |
Initialization, calibration, start/stop/recovery and reconfiguration. |
Bounded behavior, explicit failures/remaining resources; diagnostics allowed. |
Data path |
GPIO operations, request starts, IRQ data movement and result publication. |
No name lookup, allocation, unbounded scans or default application callbacks. |
Fixed ports use read-only typed faces: shared const ops and private contexts. Generated uint16_t typed IDs return static identity through factories without construction/startup effects. Production SoC and Native providers implement one public contract; multiple instances share tables but own separate state.
Hardware interfaces have a consistent typed polymorphic layout; algorithms use narrow transport/time/storage ports. Provider/mode tables are shared rather than copied per instance. IRQs call concrete providers. OS and bounded owners remain optional, without unnecessary forwarding objects.
Not every call is promised inline, nor every LTO build devirtualized. Judge ordinary functions, shared tables and generated direct bindings through ELF/disassembly and physical measurements. Prefer simple maintainable expression first.
3. 责任边界与建议源码组织¶
Responsibility boundaries are not a mandatory layer-by-layer call chain. GPIO can enter SoC implementations directly; pure protocols need not traverse OS, Board or system lifecycle.
Part |
Owned content |
Public dependency boundary |
|---|---|---|
core |
Small status/type set and shared time/request rules. |
Standard C; no generic mutable device tree. |
arch |
Exception context, atomics/barriers, CPU-local critical sections and required cycle support. |
No vendor, Board or OS dependencies. |
soc |
Exact chip capabilities, clocks/IRQs/DMA, controllers, Flash/memory, startup and private SDK. |
Implements I/O contracts; uses Arch. |
board package |
PCB wiring, oscillators, external-device facts, safe initial values and special electrical actions. |
Read-only resources/narrow hooks; may live externally. |
io |
Separate typed GPIO, UART, SPI, I2C, Flash, timer/ADC and other contracts. |
Public headers expose no SDK/kernel types. |
os |
Necessary time, notifications, locks and optional task/storage adapters. |
Bare-metal, FreeRTOS and Native implement capabilities separately. |
components |
Reusable device/protocol/storage/logging cores with explicit adapters. |
Narrow I/O/time/transport/storage ports. |
tools |
Configuration, build orchestration, resources, evidence, packaging and HIL. |
Standard tools; no generated business execution algorithms. |
External project |
main, tasks, roles, private devices/protocols, layouts and recovery/update/manufacturing policy. |
Consumes source SDKs without reverse platform linking. |
The proposed directory layout follows; the first vertical slice fixes actual names once. Migrate directories with interfaces, without permanent duplicate paths.
core/
arch/<cpu>/
soc/<vendor>/<family>/
io/include/nexus/io/
os/<backend>/
components/<component>/{include,src,adapters}/
boards/<reference-board>/
tools/{configure,dev,evidence,hil}/
tests/{contracts,models,integration}/
docs/{design,contracts,integration}/
Startup/linker/clocks belong to selected chip implementations and assemble once in the final image. No platforms forwarding layer is mandatory. Startup/reverse cleanup can be ordinary C functions; directory symmetry does not justify runtime modules.
Components use standard CMake targets with explicit sources, PUBLIC/PRIVATE dependencies and includes. Vendor/generated-private headers and test fakes stay outside ordinary consumer paths. Tools maintain no parallel dependency graph.
4. 配置体系:三类输入,一份解析结果¶
Assemblies use TOML schema 2, while SoC/Board facts remain JSON. Standard Python tomllib parses the TOML and resolution produces frozen typed IR. Strict models generate editor schemas. init/list-bindings/check/explain lower integration effort; Kconfig/cache do not establish another effective configuration.
Input |
Fact owner |
|---|---|
SoC package |
Exact part/package/density, memory domains, reviewed routes, implemented modes, clock profiles and SDK origins. |
Board package |
Actual HSE, PCB/source revisions, connections, fitted devices, jumpers, electrical facts and safe initial values. |
External assembly.toml |
Board/backend, components/instances, routes, modes, capacities and external layout. |
Reject unknown fields, unimplemented modes, contradictions and conflicts. The first version has no overlay/inherit merging, topology solving or SDK-macro-derived complete routes. Users explicitly select reviewed resources; diagnostics name field paths, resources and declaration origins.
Frozen typed IR directly generates resolved.json, headers, read-only faces, shared ops wiring, factories, linker inputs and resource reports. Generators perform deterministic validation/static assembly without business main/workers, schedulers, device state machines or driver algorithms.
CMake Presets choose assemblies, formal environments, optimization profiles and separate roots. CMake owns sources/dependencies; it reads results and checks component capabilities without rewriting selections. Cache, handwritten CONFIG macros and generated headers cannot jointly decide one fact.
External C composition maps console/control/sensor roles to generated typed physical ports. Schemas/resolved data generate no role policy. Resource declarer IDs support conflict diagnostics, not automatic C access authority or proof of business ownership.
Failed resolution blocks builds. Generation commits atomically without old-output success fallback. Separate Board/backend/ABI/instrumentation roots are required; releases record every input and derived identity.
Plans check pins/AF, electrical constraints, controllers, shared endpoints, DMA streams/requests, IRQ/shared vectors, EXTI lines, timer/channels, timebases, clocks, RTOS-reserved exceptions, memory, layout and ABI. See integration contracts.
5. 设备抽象:controller、endpoint、request、器件¶
Four entities use different models:
Entity |
Required state |
|---|---|
controller |
Actual hardware/clock/IRQ/DMA state, active requests and necessary arbitration/recovery. |
endpoint |
Immutable CS/address, rate/mode, electrical actions and connection parameters. |
request |
Operation buffers, lengths, absolute deadlines, results, borrow state and required epochs. |
Device driver |
Register protocol, calibration, conversion, initialization/retries and device state. |
Controllers own exclusive wire execution. Endpoints do not duplicate controller locks/lifecycles. Sensor drivers use endpoints/narrow transport without choosing PCB pins or creating sampling tasks.
GPIO/PWM/ADC streams are not forced into byte transactions. SPI CS/full-duplex, I2C repeated START/ACK/arbitration and Flash program/erase geometry retain concrete contracts. Shared request helpers do not become universal transaction executors.
Factories are generated pure typed getters: fixed uint16_t IDs, named constants and static switches; invalid IDs return NULL. They perform no dynamic construction, startup or lifecycle management. Diagnostic names stay outside data paths; SPI/I2C controller/endpoint identities are distinct.
GPIOs have no default per-pin owner/generation. Build-time planning proves conflicts absent; applications organize one writer/coordinator. C code obeys that contract; configuration cannot prove every user source avoids unauthorized calls.
Introduce checked sessions/epochs only for runtime owner changes, reclamation, rebinding, revocable observers or independent loans. Shared read-only fixed inputs do not need that cost. Managed modes use the same controller and exclude unmanaged direct calls; adding a token while old static calls bypass revocation is invalid. The first stage has no platform-wide dynamic device manager.
GPIO batch masks must be disjoint authorized subsets. Runtime out-of-range inputs fail; compiler-proven constants may eliminate repeated checks. Reads snapshot one selected port, not multiple ports simultaneously. Toggle requires an exclusive serial writer or explicit atomic implementation, without implied compatibility with ISR writes. Emergency and ordinary control sharing pins need explicit product arbitration/hardware interlocks; calling both contexts one owner does not remove races.
6. 默认并发模型¶
Every fixed controller has one explicit executor. One component controls GPIO outputs; one executor serializes shared buses. Multiple clients may submit through bounded explicit adapter queues. Bare-metal owners can be loops; FreeRTOS owners can be application-declared tasks.
No automatic bus/log/completion workers. Requests do not duplicate lifecycle metadata in HAL, OS and completion queues. Distinct business queues have product-owned budgets.
Single-owner paths avoid kernel locks; explicit multi-producer adapters add necessary synchronization. APIs define context/serialization; public async calls still check actual BUSY/FAULT, lengths, request states and capacity.
One request owner serializes prepare/submit/cancel/result-consume/reuse. Other tasks send adapter cancellation commands instead of using old request pointers. Cross-task controls use stable adapter-owned identity/expected epoch and retain storage until owner acknowledgment. Owners resolve still-valid records before accessing requests; they cannot read epochs from potentially freed pointers.
Direct submission has the same request owner/controller executor. Shared clients prepare, submit controls, consume results and reclaim storage; the adapter exclusively starts/cancels/services/drains controllers. Clients do not modify ACCEPTED requests or service controllers through waits. Adapters protect cross-task command storage/identity.
Short critical sections protect admission, active pointers, cancellation flags and IRQ publication. Large copies, waits, blocking vendor calls and user code stay outside. DMA does not hold task mutexes throughout transfers; multi-producer adapters admit controls while owners continue cancellation/drain.
SPSC requires exactly one nonreentrant producer and one consumer. IRQ, error IRQ and task recovery enqueueing concurrently breaks that condition. Indices use explicit atomics/release-acquire or short critical sections, never volatile as synchronization. Increment/compare wrap avoids mandatory power-of-two capacities wasting RAM.
IRQs perform prescribed data actions, publish state and issue supported wakeups. No allocation, formatted logs, unbounded lookup, blocking or arbitrary application callbacks. FreeRTOS FromISR obeys syscall ceilings; higher-priority handlers need proven deferred paths.
CPU metadata PRIMASK, FreeRTOS BASEPRI, bus ownership and DMA lifetimes are distinct mechanisms. Architecture review determines minimum barriers; benchmarks do not justify deleting hardware ordering. Plan kernel/HAL time independently; lower RTOS tick rates require a genuinely usable HAL time source.
7. 请求、deadline、取消与完成¶
Async defaults use caller-owned requests/payload; queues borrow pointers or small descriptors only. The following illustrates contracts; compilable interfaces are in core/include/nexus/core/request.h:
nx_spi_request_prepare(&request, tx, rx, length, transfer_deadline);
status = nx_spi_submit(endpoint, &request);
/* status == NX_OK means admitted, not transfer success. */
nx_spi_cancel(endpoint, &request);
wait_status = nx_spi_wait_settled(endpoint, &request, wait_deadline);
/* A wait timeout retains request and payload lifetime. */
The illustration is direct single-executor use. Wait conveniences require adapters with waiting/service capability. Shared adapters expose their own client admission/cancel/wait APIs; shared request helpers are not mandatory universal controller schedulers.
Submission states admission explicitly:
REJECTED: no request/buffer borrows and no residual hardware needing settlement.
ACCEPTED: borrowing starts; later start/IRQ/timeout/abort failures report through requests rather than relabeling borrowed requests as ordinary rejection.
Queue acceptance is the shared chain’s only admission point, immediately starting borrowing and total deadlines. Temporary controller BUSY retains QUEUED; actual start failures are request results, never retroactive REJECTED. Queued cancellation removes all references before settlement; full-queue rejection leaves no borrow. Direct/adapter paths share request-state rules.
Default requests have one owner/result consumer. Preparation/reuse requires prior settlement and released consumer/adapter references. Allocate sequences/epochs only for retained delayed identity/control records; identities never repeat and exhaustion fails explicitly. Fully serial requests with no escaping references and drained old sources need no mandatory epoch, nor do fixed pins need extra lifecycles.
Request state |
Backend borrows request/buffer |
Meaning |
|---|---|---|
READY |
No |
May prepare/submit. |
QUEUED |
Yes |
Admitted, waiting for controller. |
ACTIVE |
Yes |
Hardware/handlers may access. |
DRAINING |
Yes |
Stopping sources and draining users. |
SETTLED |
No |
Hardware, IRQ and deferred accesses have ended. |
QUARANTINED |
Yes |
Drain cannot be proven; retain responsibility until controlled recovery/reset. |
Transfer deadlines are absolute in an explicit monotonic domain and include queueing. Wait deadlines bound only waiter residence. Cancellation acceptance, transfer timeout and wait timeout do not mean SETTLED.
Every profile declares deadline observers, service scheduling, cancellation capability and drain bounds. Polling does not claim low-CPU async behavior. C deadlines cannot automatically preempt Flash pulses or abnormal DMA; residual accesses remain owned after timeout.
Completion is a level state in requests plus single-owner notification. Notifications are wake hints; lost/full notifications cannot erase the sole result. Explicit task adapters execute user callbacks while retaining/returning required borrows. Default drivers retain no application callbacks.
Optional executor waits must preserve progress: bounded service, request/control checks, arm static notifications, recheck completion/service predicates, then wait for the earliest wait deadline, transfer deadline or maximum service interval. The sole executor cannot block waiting for its own drain. Shared clients observe only their own results and prevent lost wakes; adapter executors retain service/deadline/drain responsibility without client takeover. Bare metal pumps explicitly; absent wait capability never masquerades as successful blocking.
Notification ports provide level-latched or sequence semantics without lost wakes between arming, rechecking and sleeping. Ports lacking reliable notification use bounded rechecks rather than infinite sleep. IRQ results, controls and deadline expiry can all make owners service again; no generic executor/hidden worker is required.
Before publishing SETTLED, stop every hardware source that can access the request, prove DMA no longer accesses its storage, drain IRQ/deferred users and apply necessary ordering. Independent continuous RX storage need not stop. Epochs do not replace drain: untagged old IRQs may read new active pointers.
Default IRQs latch completion/errors and wake owners; owners perform task-context drain. Prepare result fields, detach from controllers and acquire needed notification identities first. Release-publication of SETTLED is the backend’s final request access; callers observe with acquire. Post-publication notification uses pre-acquired still-valid static owner objects. IRQ-direct publication is allowed only by explicit profiles with old sources settled, no later request access and no tail interference with subsequent transfers. Native concurrency models prove the same borrow endpoint.
Synchronous conveniences obey these rules. Stack requests must settle before return. If wait budgets expire without settlement, returning cannot invalidate their stacks. Use caller-owned long-lived requests or explicit fail-stop/reset policy.
SETTLED ends backend borrowing; reuse also needs consumed results and exited observers/callback adapters. Driver states cannot revoke independent adapter borrows. Single-owner defaults add no separate completion latch; requests remain the sole result authority.
8. 启动、故障与停止¶
Static assembly provides readable initialization order. Ordinary serial C calls establish CPU/clocks/timebases, safe values, required static kernel objects and selected drivers. External applications start business components/schedulers explicitly. Platforms generate no business main or automatic all-device startup.
Undo only acquired resources in reverse order; retain original failures, cleanup errors and remaining ownership. Residual DMA/IRQ keeps contexts/requests alive rather than falsely returning to OFFLINE.
Initialization declares reversible/irreversible effects. Enabled IWDG, Flash option bytes and hardware locks cannot be pretended undone by reverse cleanup. Products explicitly choose watchdog enabling; existing enabling must be detected. Later failures record irreversible effects and leave products to continue feeding in controlled failure states or reset. Rollback never falsely reports watchdog stopped.
RUN fixes identity/write authority. Controlled recovery restores the same port without changing owner/routes. Stop closes admission and asks producers to stop new operations; executors continue controls/deadlines/drain until requests/adapter borrows settle. Notification publishers also exit; applications then join clients/executors, reclaim OS storage and finally disable clocks/pins. Never stop the sole executor before joining producers waiting for SETTLED.
Direct GPIO writers without admission, and related ISRs, must quiesce before changing modes/clocks; generic stop flags cannot revoke unchecked calls. Static notification objects cannot be deleted, reused or unregistered while wakeups may still access them. Request SETTLED alone does not prove notification reclamation safe.
Low-cost fixed hot paths depend on quiescence. The default promises no arbitrary concurrent teardown/rebinding. Products requiring that use separately reviewed managed-binding contracts and pay corresponding state/check costs.
Boards describe physical initial output levels; products choose stop, degradation or reset on errors. Reset/start levels, external-device timing and output continuity require physical proof. Platform-wide hot restart during kernel execution is not promised by default.
Board initial values express electrical constraints and known inactive polarity; process-safe valve/heater states belong to products. The word “safe” does not make them interchangeable.
9. 内存与资源策略¶
Default core/I/O has no heap, hidden OS objects or all-resource pools. Controllers, selected-mode state, endpoints, queues and buffers allocate for actual instances. Fixed configurations/bindings/tables live in Flash; mutable zeroed contexts live in BSS.
Resource |
Default policy |
|---|---|
Request payload |
Caller-owned, borrowed until SETTLED; copy APIs are separately selected. |
queue |
Actual depth/item size; only necessary data, explicit overflow policy. |
task |
Externally declared stack/TCB storage; budget totals each task. |
RX |
Exact event/byte/block semantics and capacity; no maximum default event pool. |
DMA |
State only for DMA modes; check domains, alignment, aliases and borrowing. |
trace/stats |
Separate compile choices; disabled modes leave no permanent formatting or per-operation statistics branch. |
managed heap |
Explicit opt-in with domain/capacity/failure/sealing; account libc/kernel heaps separately. |
Per-byte UART timestamps, byte streams and DMA block loans are different contracts. Frame-gap applications choose faithful event profiles; block users accept actual provided timing. DMA completion cannot reconstruct each byte’s arrival across gaps.
Circular DMA loans must prevent overwrite of unreleased windows. Otherwise use bounded copying, flow control, stopping or explicit drop policy. Non-NULL does not mean DMA-reachable. Separate F407 CCM/other CPU-only domains from DMA domains; describe GD domains from exact chip documents.
Account static RAM from actual ELF regions and independent reservations, without adding BSS stacks/heaps/buffers twice. High-water marks describe use without shrinking reserved allocations. Flash includes vectors, code, rodata, registration/bindings and RAM initialization loads, not text alone.
Remove large generic metadata first. Preserve actual busy/fault, active-request, IRQ/drain, callback/loan and necessary epoch state. Field sizes alone do not justify removing safety invariants.
9.1 Industrial-control categories and initial scope¶
Define category contracts first, then implement reviewed wiring and actual requirements. Public types alone establish no provider support; unimplemented modes fail configuration.
Category |
Required abstraction |
Required acceptance |
|---|---|---|
GPIO/EXTI |
Fixed authorized masks; inputs/outputs; actual line ownership, edges and events. |
Initial/atomic outputs, shared EXTI vectors, event overflow and shutdown drain. |
UART/RS485 |
Byte/event/block RX; TX memory settlement versus wire-idle; explicit DE/RE electrical actions. |
Errors/loss/TC/cancel, frame gaps, actual transceivers and wiring. |
SPI |
Controllers, static CS endpoints, modes/speeds and complete transactions. |
CS hold/release, synchronized full-duplex, DMA/cancel/deadlines. |
I2C |
Address endpoints, message sequences, repeated START/STOP and errors. |
NACK/arbitration/stuck buses, recovery and terminal states; no false recovery success. |
timer/PWM/capture |
Clock domains, timer/channels, periods/duty, hardware triggers and fixed safe values. |
Timing precision/bounds, atomic updates, ADC trigger resources and shutdown outputs. |
ADC |
Reviewed channels/scans/triggers, sample formats, calibration, block borrowing/overflow. |
Rates/accuracy, DMA reachability, sequences/triggers, loss and buffer return. |
watchdog/reset |
Hardware ranges, feeding and reset causes. |
Actual timeout reset, debug freezing and power-on/reset differences. |
Internal Flash |
Physical geometry, regions, programming/erasing and nonpreemptible pulses. |
Bounds/alignment, hardware terminal states, power loss and pause budgets. |
The first slice establishes GPIO, clocks and requests; UART/SPI/internal Flash provide basic communication/persistence. I2C/watchdog/timer/PWM/ADC/EXTI enter subsequent mode-specific industrial batches. NG-018/031/032/033 separately govern watchdog, EXTI, fixed timer/PWM and single/low-rate ADC scan with fault/resource acceptance and candidate dependencies; aggregate category status cannot close all modes.
CAN/CANopen, Ethernet, USB, low power, cache/MPU, secure boot and remote updates need explicit product demand, maintained dependencies and independent budgets. Narrow integration ports remain available, but the first candidate need not cover all chip peripherals or expose SDK-only shells.
RTOS ticks, HAL time, UART timing and ADC/PWM triggers each consume actual timebases. Selection must not accidentally share one timer/channel across incompatible uses. Chip capabilities do not establish unverified Board wiring.
Maintained modes include bounded EXTI events, fixed PWM, ADC polling/scan and IWDG feed/reset causes. Selected STM32F407/GD32F470 routes also provide UART dma-tx, irq-blocks, rx-dma-idle, rx-dma-continuous, dma-duplex and dma-duplex-continuous, finite full-duplex SPI DMA, ADC trigger-dma/trigger-dma-continuous, and capture/break/deadtime mechanisms through edge-capture and complementary-pwm. ADC trigger-dma stops and drains each block, then explicit service restarts after consumer release, leaving inter-block gaps. Continuous modes use double buffering and explicit replacement blocks; exhausted capacity or failed hardware drain retains borrows without overwriting consumer storage. They do not promise lossless operation under arbitrary IRQ latency, service intervals or consumer speed. DMA domains, hardware routes, IRQs, stop and consumer-loan drain retain exact-mode contracts and software models. The derived capability matrix and corresponding contracts define configuration and production-implementation scope. All related physical timing, electrical and continuous-acquisition qualification remains unexecuted.
Timers define frequency, tick units, wrap extension, maximum maintenance intervals and clock/stop behavior. PWM checks shared PSC/ARR/base modes and defines 0%/100%, shadow updates, error and start/stop levels.
ADC defines resolution, sample time, reference voltage/raw counts, sequences/triggers, overruns, timing information and timeout output validity. DMA streams separately define window overwrite and borrowing.
EXTI defines line/port muxing, shared vectors, merged/lost edges, timing precision and pending cleanup. Products choose debounce policy.
IWDG defines irreversible enabling, existing state, timeout range including LSI error, fixed feeding responsibility, reset causes and debug freezing. Health decisions stay external.
10. 性能策略与成本验收¶
Optimize total cost: CPU cycles, maximum observed masking duration, Flash loads, reserved RAM, peak stacks, throughput/loss, energy and marginal per-instance cost.
Measure minimal bare-metal/FreeRTOS slices first: empty images, GPIO and UART/SPI requests. Board profiles select only slice-essential resources; complete Board configurations are not minimal platform cost.
Operation |
Cost target |
Validation |
|---|---|---|
Fixed GPIO set/reset |
No registry lookup/generic refs/OS locks; authorized masks and same-port batches. |
Disassembly + DWT/logic analyzer. |
request admission |
O(1) or explicit fixed queue bounds; no payload copy, allocation or name lookup. |
Fault models + boundary inputs + cycles. |
IRQ data publication |
Bounded actions without application callbacks/unbounded scans; correct index publication. |
Race models + priority loads + physical Boards. |
Completion observation |
Read existing request state; notifications are not result authority. |
Full/lost notifications + cancellation/late IRQ. |
New instance |
Only necessary instance context/storage/read-only bindings. |
Image delta/maps + configuration explanation. |
Disabled capability |
No retained RAM or unreachable method references. |
Symbol/section/actual ELF differences. |
Select a few formal profiles by comparing O2/Os/O3/LTO, not CMake defaults or hardcoded publishers. Apply hotspot-local optimizations where proven. No global fast-math or deletion of necessary checks.
Measurements record clocks/wait states, ABI/FPU, compiler, modes, loads, IRQ interference, overhead and ELF identity. Instruction counts are not cycles; Native wall time is not MCU deadlines; observed maxima are not strict WCET. DWT uses snapshot differences; profilers do not reset driver-shared monotonic clocks.
Reference benchmarks and products define absolute budgets. The platform establishes structural constraints/software gates first and promises performance only when measured under stated conditions/loads. Architecture cannot prove unconditional global optimality across workloads, compilers and hardware.
11. 工程工具、风格与管理¶
Production defaults to C11/public C ABI. C++ may support host tests, not driver object systems. Formal tools use locked ARM/Native compilers, CMake/Ninja/CTest, Python, clang-format/selected clang-tidy and one host framework. Other tools enter only for explicit gaps.
Lock formal versions/OCI digests and separately source contents/licenses. One thin dev entry orchestrates native commands for local/CI; no second build/test/workflow engine.
Preserve root .clang-format/.editorconfig: 80 columns, four spaces, attached K&R braces and type-side pointers. Keep module prefixes, _t types and current naming; private code is static, headers self-contained and integer/length/encoding rules explicit. Vendor targets stay separate; global warning suppression never hides owned defects.
Comments retain backslash Doxygen, file headers and section/inline forms. Public headers define parameters/returns; sources avoid duplication. Existing tags describe context, blocking/deadline origins, ownership, output validity, cancel/settlement and residual failures. Shared rules live on types/modules; functions state differences. Internals explain races, barriers, errata and tradeoffs. Headers retain authors/versions/dates and Git supplements history. See handbook section 12.
Statuses support actionable caller recovery; vendor diagnostics are optional detail. APIs do not format logs implicitly, write global last errors or call global application handlers in IRQs. Ordinary errors and invariant violations are distinct.
The ten-person capacity follows responsibilities, not old code boundaries: TL1, core/I/O/OS2, STM/GD BSP2, device/communications2, QA/HIL2, build/release1. Each domain has primary/backup responsibility. Ordinary changes need independent domain review; public contracts, IRQ/DMA, synchronization, persistence and publishing add consumer/cross-layer review.
Distinguish design, implementation, software, hardware and release qualification. Code lines, PRs, pages and test counts do not close tasks. See engineering handbook.
12. 验证、交付与平台接入¶
Validation layers: fast local → PR integration → nightly breadth/load → dedicated HIL → same-artifact promotion. Contracts/risks drive selection; configuration, synchronization, public APIs and linker/toolchain changes trigger cross-layer checks.
Core invariants: REJECTED retains no borrow; ACCEPTED failures remain owned; after SETTLED no backend/DMA/IRQ/deferred access to the request/buffer remains; reclamation also needs consumer/adapter exit; reuse drains old sources; one wire-active transaction per bus; stop closes admission then drains; overflow/full notifications cannot fake success; waits preserve drain/protect against lost wakes; resource plans match implementations.
Models cover partial starts, late IRQs, epoch reuse, full queues, cancel/deadline races, failed aborts and stop retries. Actual ARM links cover startup/vectors/strong IRQs, layout, ABI and resources. Physical testing covers TC, DMA drain, electrical behavior, masking duration, high-water marks and sustained loads; currently not executed.
Provenance binds inputs/commands/outputs; hermeticity proves reading only declared inputs; reproducibility proves identical independent clean-build bytes. Accept them separately. Formal artifacts build from complete locked inputs and seal ELF/BIN/maps/config/manifests. Promote identical hashes without rebuilding at publication.
Support units include exact part, Board source/PCB revision, routes, modes, backend and resolved configuration. Source review, compile/link, models, physical tests and product loads are separate evidence dimensions. Board names do not imply all-peripheral support.
New Boards provide small fact sets/electrical hooks; SoCs provide actual providers/startup/clocks/IRQs/memory/SDKs; devices provide narrow transport/logic; protocols provide pure cores/adapters; products provide assembly/main/tasks/policy. See integration contracts for workflows and SDK upgrades.
13. 实施顺序与退出条件¶
Each batch atomically updates implementations, callers, tests and docs to new contracts. External examples update SDK pins separately. Old interfaces may be deleted directly; deployed persistence still requires migration/rollback policy.
Batch |
Content |
Software exit condition |
|---|---|---|
B0 |
Freeze design, requirements/risks, reference workloads and budget schemas. |
One reviewable contract set with truthful unimplemented/unmeasured states. |
B1 |
Formal tools, source packages, schema configuration and minimum images/targets. |
Actual minimum ELFs for two SoCs; real invalid-input rejection; one resolved configuration. |
B2 |
CPU/clocks/memory/startup and fixed GPIO. |
Three-Board base combinations, direct/batch paths, consistent safe values/input identity. |
B3 |
Requests, UART/SPI/I2C/Flash and first EXTI/PWM/ADC/IWDG modes. |
Cancel/deadline/drain and irreversible-effect invariants; actual mode-specific linking/fault regressions. |
B4 |
Per-object OS storage, shared devices/components and external examples. |
Actual external consumers, no internal business logic or unused resident resources. |
B5 |
Static analysis, resource/performance tools, hermetic/reproducible builds and HIL preparation. |
Software gates, independent rebuilds and actual artifact admission; physical results still unexecuted. |
B6 |
New candidates and migration closure. |
Complete new-source qualification/evidence, removed old entries and truthful support scope. |
See execution checklist for dependencies/domain owners. Ten people over 3–6 months deliver controlled scope, not automatically every peripheral, topology solver, dynamic device system, low power, MPU, secure updates or enterprise LTS.
The following schedule assumes ten-person capacity; dependencies/evidence take precedence over calendars. Each provider’s first slice includes faults, style/warnings and minimal budgets. B5 expands/closes checks rather than deferring them until the end.
Window |
Main and parallel work |
Stage outcome |
|---|---|---|
Weeks 1–2 |
B0; tools/QA prepare minimum workloads and locked environments. |
Explicit initial modes, resource accounting and failure/borrow contracts. |
Weeks 3–6 |
B1; BSPs prepare exact startup/memory while interfaces establish request models. |
Complete external-consumer-to-minimum-ELF slices on two SoCs. |
Weeks 7–12 |
B2 and base B3; parallel GPIO/UART BSP work with concurrent QA fault models. |
Three-Board base communications software baseline and resource reports. |
Weeks 13–18 |
Industrial B3 and B4; device/communications teams migrate components and six base examples. |
Initial EXTI/PWM/ADC/IWDG and explicit I2C scope; closed bare-metal/FreeRTOS consumption. |
Weeks 19–24 |
B5/B6; QA/build close gates, offline rebuilds, HIL preparation and old paths. |
Controlled-scope software candidates, exact support records and usable tooling. |
Month-three baselines and month-six candidates have different scopes. After hardware connects, perform physical acceptance on actual artifacts. Unclosed hardware dependencies remain not executed; do not shrink tests to preserve calendar promises.
Begin with fixed GPIO and caller-owned request state, then implement one necessary actual UART/SPI path. DMA modes/qualification remain separate; SDK functions do not establish completion. Software candidates and product physical qualification are delivered separately.
14. 会删除或不引入的默认复杂度¶
Per-GPIO generic registration/owner/ref/generation and hot-path string lookup.
Per-instance mutable OOP tables and permanent raw-getter/managed-reference coexistence.
Unselected DMA handles, maximum legacy copy buffers and all-class maximum pools.
Mandatory OSAL traversal for all kernel functions, generic executors, hidden workers and default completion queues.
Duplicate configuration facts, multiple overlays, generated business DSLs and all-pin automatic solvers.
Duplicate build/release entries, count-only qualification and PASS reports for different artifacts.
Repository splits, forwarding directories or multiple build/package systems introduced only to modernize names.
Retain the state/evidence real problems need: fixed planning, genuine borrows, faults/draining, explicit contexts, actual memory/timing and repeatable engineering with external product boundaries.