Software Architecture ===================== Purpose ------- This document describes the firmware and host-side software architecture of the MOTSEN Tool: the layers, the modules within each layer, the threading and timing model, and the seams that make the firmware portable across MCUs. It sits between :doc:`../02_System/system_description` and :doc:`software_requirements`. The architecture is intentionally **MCU-agnostic**. Every MCU-specific concern is confined to the hardware abstraction layer (HAL). Application, services, and measurement code use only HAL interfaces, never vendor SDK calls or register access. Architecture Overview --------------------- .. swarch:: Layered architecture :id: SWARCH_001 :status: draft :derived_from: DESC_033 The firmware is organized in four layers, lower layers do not call upward: 1. **HAL** — thin abstraction over MCU peripherals (GPIO, UART, timer, ADC, PWM, NVM). 2. **Drivers** — peripheral-oriented modules built on the HAL (PWM driver, ADC sampler, Hall reader, comms framer). 3. **Services** — cross-cutting facilities (system tick, scheduler, parameter store, safety supervisor, comms protocol, logger). 4. **Application** — operating-mode state machine, measurement procedures, control loops. The host side adds two further layers above the link: a local web server and a browser UI. The on-wire protocol is the seam between firmware and host. .. swarch:: Layer diagram :id: SWARCH_002 :status: draft :derived_from: DESC_033 .. graphviz:: digraph sw_layers { rankdir=BT; node [shape=box, style="rounded,filled", fillcolor="#D5F5E3"]; HAL [label="HAL\n(GPIO, UART, Timer, ADC, PWM, NVM)"]; Drv [label="Drivers\n(PWM, ADC, Hall, Comms framer)"]; Svc [label="Services\n(Tick, Scheduler, Params, Safety, Protocol, Logger)"]; App [label="Application\n(State machine, Measurement, Control)"]; Wire [label="On-wire protocol", shape=ellipse, fillcolor="#FCF3CF"]; Host [label="Host: local web server + browser UI", fillcolor="#D6EAF8"]; HAL -> Drv; Drv -> Svc; Svc -> App; App -> Wire [style=dashed, dir=both]; Wire -> Host [style=dashed, dir=both]; } Hardware Abstraction Layer -------------------------- .. swarch:: HAL scope :id: SWARCH_010 :status: draft :derived_from: DESC_033 The HAL exposes interfaces for the peripheral classes required by :need:`HWARCH_060`: GPIO, UART, timer, ADC, PWM, and NVM. Each interface is defined in pure C and contains no MCU-specific identifiers. .. swarch:: HAL portability seam :id: SWARCH_011 :status: draft :derived_from: DESC_033 The HAL is the only place where MCU vendor headers, SDK calls, or register access may appear. Layers above the HAL #include only HAL headers. A new MCU is supported by adding a new HAL implementation; no change above the HAL is required. .. swarch:: HAL build-time configuration :id: SWARCH_012 :status: draft :derived_from: DESC_033 The HAL implementation for a given MCU is selected at build time. Pin assignments and peripheral instances are passed in as build-time configuration, not hard-coded in the HAL source. .. swarch:: HAL minimal surface :id: SWARCH_013 :status: draft :derived_from: DESC_033 :linked_to: RISK_002 The HAL is sized to the minimum needed by the current phase. New HAL functions are added only when a driver or service needs them. This is the mitigation for RISK_002 (HAL over-engineered prematurely). .. swarch:: HAL implementation strategy :id: SWARCH_014 :status: placeholder :derived_from: DESC_063 :linked_to: DEC_005 Whether each HAL implementation wraps the MCU vendor's RTD/SDK or sits directly on registers is pending DEC_005. Drivers Layer ------------- .. swarch:: PWM driver :id: SWARCH_020 :status: draft :derived_from: DESC_030 The PWM driver translates the application's duty-cycle commands into HAL calls. It configures center-aligned mode, complementary outputs, dead-time, and ADC trigger generation. It exposes a single ``apply_duties(a, b, c)`` entry point and an ``enable / disable`` pair. .. swarch:: ADC sampler :id: SWARCH_021 :status: draft :derived_from: DESC_031 The ADC sampler runs in the ADC end-of-conversion interrupt and delivers a struct of fresh phase currents and DC-bus voltage to the control loop within one PWM period. It applies calibration scale and offset before publishing the values. .. swarch:: Hall reader :id: SWARCH_022 :status: draft :derived_from: DESC_032 The Hall reader samples Hall inputs on edge interrupts and on a periodic poll. It maintains the current commutation sector and an inferred direction, and exposes them as read-only state. .. swarch:: Encoder reader :id: SWARCH_023 :status: placeholder :derived_from: DESC_032 :linked_to: MIL_042 Incremental encoder driver. Scheduled for Phase 2 (MIL_042). .. swarch:: Resolver driver :id: SWARCH_024 :status: placeholder :derived_from: DESC_032 :linked_to: MIL_077 Resolver excitation and demodulation driver. Scheduled for Phase 3 (MIL_077). .. swarch:: Comms framer :id: SWARCH_025 :status: draft :derived_from: DESC_035 The comms framer encodes and decodes frames on the host link using the selected on-wire format (pending DEC_003). It exposes a byte-stream interface to the protocol service and a frame interface to the link's HAL UART instance. Services Layer -------------- .. swarch:: System tick and scheduler :id: SWARCH_030 :status: draft :derived_from: DESC_033 A single timer-driven system tick provides non-blocking timing primitives and drives a cooperative scheduler for periodic work that is not time-critical (telemetry assembly, host comms, status updates). .. swarch:: Real-time execution model :id: SWARCH_031 :status: draft :derived_from: DESC_033 Real-time work runs in interrupt context, not on the scheduler: * ADC end-of-conversion ISR → control / measurement step. * Hall edge ISR → sector update. * Comms RX ISR → byte intake. The application loop runs at lower priority and is preempted by these ISRs. No RTOS is required. .. swarch:: Parameter store :id: SWARCH_040 :status: draft :derived_from: DESC_036 The parameter store holds the runtime-tunable values (limits, measurement settings, calibration). Parameters are accessible by ID from the host link. RAM-only in Phase 1; non-volatile persistence is a placeholder until the NVM-bearing HAL is required. .. swarch:: Calibration store :id: SWARCH_041 :status: draft :derived_from: DESC_031 Sensing-chain calibration coefficients (scale, offset for each channel) live in the calibration store and are applied by the ADC sampler. The measurement engine refuses to publish a characterization result if the calibration store is empty (see :need:`SYS_044`). .. swarch:: Comms protocol :id: SWARCH_050 :status: draft :derived_from: DESC_035 The protocol service runs on top of the comms framer. It defines three message classes: * **Parameter** read / write requests and responses. * **Telemetry** streaming records published periodically. * **Command** request / response for measurement procedures and mode transitions. Protocol versioning is included in the frame header so that host and firmware can detect a mismatch. .. swarch:: Safety supervisor :id: SWARCH_060 :status: draft :derived_from: DESC_034 The safety supervisor runs on every ADC sample and checks instantaneous current and DC-bus voltage against firmware-configurable limits. On any limit breach it: 1. Disables PWM via the PWM driver. 2. Transitions the state machine to Fault. 3. Captures the fault cause and the contents of the latest sample frame to the logger. .. swarch:: Logger :id: SWARCH_070 :status: draft :derived_from: DESC_036 The logger collects diagnostic events into a small in-RAM ring buffer and forwards them on the telemetry channel. Events include faults, mode transitions, and procedure start/end markers. The logger has no blocking calls and never allocates. Application Layer ----------------- .. swarch:: Operating-mode state machine :id: SWARCH_080 :status: draft :derived_from: DESC_040 The state machine is the single owner of the operating mode (Idle, Sensor Check, Characterization, Run, Fault). It accepts transition requests from the protocol service, validates them against the rules in :need:`SYS_111` to :need:`SYS_114`, and drives mode-entry / exit actions (PWM enable/disable, current limit selection). .. swarch:: Sensor health check procedure :id: SWARCH_090 :status: draft :derived_from: DESC_037 The sensor health check is a sequence of low-energy stimuli that validates phase sequence, Hall alignment, and basic connectivity. It runs entirely in firmware, with the host receiving only command and result frames. .. swarch:: Rs measurement procedure :id: SWARCH_091 :status: draft :derived_from: DESC_037 Rs is measured by applying a controlled DC current along a known electrical axis and computing R = V / I after settling. The procedure declares its own current limit, ramps to the test current, and aborts the procedure if the limit is breached. .. swarch:: Ld / Lq measurement procedure :id: SWARCH_092 :status: placeholder :derived_from: DESC_037 :linked_to: MIL_040 Ld / Lq measurement. Scheduled for Phase 2 (MIL_040). .. swarch:: Back-EMF / Kt measurement procedure :id: SWARCH_093 :status: placeholder :derived_from: DESC_037 :linked_to: MIL_041 Back-EMF and torque-constant measurement. Scheduled for Phase 2 (MIL_041). .. swarch:: Open-loop commutation control :id: SWARCH_100 :status: draft :derived_from: DESC_040 The Phase 1 control loop drives open-loop sinusoidal commutation with an enforced current limit. The control loop runs synchronously with the ADC sampler (see :need:`SWARCH_031`). .. swarch:: FOC control :id: SWARCH_101 :status: placeholder :derived_from: DESC_040 :linked_to: MIL_045 Field-oriented control. Scheduled for Phase 2 (MIL_045). Host-Side Software ------------------ .. swarch:: Local web server :id: SWARCH_110 :status: placeholder :derived_from: DESC_036 :linked_to: DEC_002; MIL_017 A local web server on the host PC serves the UI static assets and bridges a real-time channel to the firmware over the host link. The backend language and framework are pending DEC_002. .. swarch:: Browser UI :id: SWARCH_111 :status: draft :derived_from: DESC_036 The browser UI provides a single-page application showing live phase currents, sensor state, the current operating mode, and any active fault. It triggers measurement procedures via the protocol and displays their results. .. swarch:: Host protocol client :id: SWARCH_112 :status: draft :derived_from: DESC_035 The host has its own implementation of the comms protocol defined by :need:`SWARCH_050`. Frame format and physical layer match the firmware side (pending DEC_003). .. swarch:: Scripting interface :id: SWARCH_113 :status: placeholder :derived_from: DESC_036 :linked_to: MIL_044 A scriptable interface on the host allows running measurement sequences without the browser UI. Scheduled for Phase 2 (MIL_044). .. swarch:: Host parameter & result persistence :id: SWARCH_114 :status: placeholder :derived_from: DESC_036 :linked_to: MIL_047 Persistent storage of motor parameters and measurement results on the host filesystem. Scheduled for Phase 2 (MIL_047). Build and Configuration ----------------------- .. swarch:: Build configuration :id: SWARCH_120 :status: draft :derived_from: DESC_033 The firmware build accepts a "target" parameter that selects the HAL implementation, the pin/peripheral mapping, and the feature set for the target phase. The same source tree builds for all supported targets. .. swarch:: Compile-time feature gating :id: SWARCH_121 :status: draft :derived_from: DESC_050 Optional features (CAN, encoder, resolver, FOC, etc.) are gated at compile time so that the Phase 1 build does not pull in Phase 2 or 3 code. .. swarch:: No dynamic allocation in firmware :id: SWARCH_122 :status: draft :derived_from: DESC_033 The firmware shall not use dynamic memory allocation after startup. All buffers are sized at build time. Open Items ---------- .. swarch:: Host backend stack — pending :id: SWARCH_900 :status: placeholder :derived_from: DESC_062 :linked_to: DEC_002 Backend language and framework for the local web server are pending DEC_002. .. swarch:: Host link protocol — pending :id: SWARCH_901 :status: placeholder :derived_from: DESC_061 :linked_to: DEC_003 The exact frame format and physical layer of the host link are pending DEC_003. The architecture above assumes the existence of a framed bi-directional channel but does not bind it. .. swarch:: Sensorless control — pending :id: SWARCH_902 :status: placeholder :derived_from: DESC_065 :linked_to: DEC_006 Whether observer-based sensorless control is in scope is pending DEC_006. Traceability ------------ Each ``swarch`` node above declares ``derived_from`` exactly one ``DESC_*`` node in :doc:`../02_System/system_description`. The forward direction is populated by ``swreq`` nodes in :doc:`software_requirements`, which declare ``derived_from`` either a ``SYS_*`` requirement or a ``SWARCH_*`` block here.