docs: document board configuration workflow

This commit is contained in:
Onur Özkan committed 2026-08-22 18:41:07 +03:00
1 parent b7631c0bc7
commit 97acb2a2d7
13 files changed
+470 -173

No files matched your search

+43 -30
View File
@@ -10,19 +10,22 @@ board declaration
F722 platform / RTIC application ──► data channel ──► MAVLink telemetry F722 platform / RTIC application ──► data channel ──► MAVLink telemetry
│ │
├── physical sensor drivers ├── physical sensor drivers
└── motor-pin inhibit interlock └── startup motor-pin inhibition
portable libraries portable libraries
math ─► navigation ─► control ─► safety math ─► navigation ─► control ─► safety
``` ```
The board contract selects one immutable `BoardProfile`. The checked-in Each F722 board contract pairs a board-owned `UserConfig` schema and explicit
profile is `TelemetryOnly`; `ExternalControlOnly` is represented explicitly `FACTORY_USER_CONFIG` with a board-owned `ImmutableConfig`. The immutable root
but rejected at validation time because it has no reviewed runtime. is one literal typestate manifest and the sole source of output inhibition,
physical routes, driver setup, sensor mount, bootstrap line rates, status LED,
image role, and service frequency. The user root contains only settings
consumed by that compiled driver graph.
The data channel owns rate selection, mailbox consumption, message encoding, The data channel owns rate selection, mailbox consumption, message encoding,
and bounded TX classification. Board code supplies physical routes and and bounded TX classification. Board code supplies physical routes, target
telemetry configuration; it does not receive generic output authority. schema, and factory values; it does not receive generic output authority.
Configuration and runtime observability are separate, one-way planes: Configuration and runtime observability are separate, one-way planes:
@@ -33,8 +36,8 @@ Kaptan GCS custom MAVLink V2 messages
kaptan-config-mavlink ──► state-only ConfigProtocol kaptan-config-mavlink ──► state-only ConfigProtocol
│ borrows │ borrows
kaptan-flight-runtime kaptan-flight-runtime
├── one ConfigManager ──► kaptan-config ──► flight schema/CBOR ├── one ConfigManager ──► kaptan-config ──► flight schema/store
└── one kaptan-log hub └── one bounded MAVLink log-sink queue
│ │
kaptan-log-mavlink payload adapter kaptan-log-mavlink payload adapter
│ │
@@ -43,39 +46,49 @@ kaptan-config-mavlink ──► state-only ConfigProtocol
The generated dialect is intentionally custom rather than a `PARAM_*` or QGC The generated dialect is intentionally custom rather than a `PARAM_*` or QGC
adapter. The core uses numeric field IDs and typed scalar values; descriptor adapter. The core uses numeric field IDs and typed scalar values; descriptor
text is metadata, not a wire identity. Discovery/value reads, bounded text is metadata, not a wire identity. Discovery/value reads, exact-index
descriptor pages, and structured results are custom-dialect records. Runtime descriptor and enum-option requests, and structured results are custom-dialect
logs use one bounded text message with MAVLink severity and flags. CBOR import uses a fixed records. Runtime logs use one bounded text message with MAVLink severity and
4 KiB transaction buffer and flags. Remote writes use only schema-described typed scalar setters. The core
fixed 192-byte chunks; its decoded candidate still goes through the same whole owns one RAM transaction and the distinction
profile validation path. The core owns one RAM transaction and the distinction
between boot-active, committed, and editable candidate snapshots. In the between boot-active, committed, and editable candidate snapshots. In the
current P1 policy a commit is restart-only. It cannot mutate controller or current P1 policy a commit is restart-only. It cannot mutate controller or
estimator state in flight. estimator state in flight.
One current CBOR profile format is a bounded complete snapshot. There is no Target-owned stores may serialize one bounded complete CBOR snapshot. SITL
migration reader: any other format is rejected. SITL supplies the host file supplies the host file adapter and persists a private nonzero storage sequence
adapter and persists a nonzero generation alongside its raw profile payload. alongside that snapshot. The serialization and sequence are not configuration
Motor allocation/mixer topology is immutable compiled state and are never exposed by the MAVLink protocol.
vehicle capability data, never a scalar field or CBOR candidate member. The Motor allocation/mixer topology is immutable compiled vehicle capability data,
bare-metal receiver continues to reject inbound control authority. Target never a scalar field or CBOR candidate member. F722 now recovers operational
persistence, authenticated ingress, durable audit logging, disarmed settings from a generic two-slot journal before constructing consumers. Its
activation, and atomic consumer reconstruction remain separate reviewed work directly wired local UART accepts only exact-target, CRC-valid configuration
and cannot be implied by a valid CBOR file or CRC. commands while physical outputs remain inhibited. CRC is integrity-only; a
shared or remote GCS still needs production authentication, durable audit
logging, source binding, and persistent anti-replay state. Disarmed activation
and flight-consumer reconstruction remain separate reviewed work and cannot be
implied by a valid snapshot or CRC.
Configuration wire layout `2.0` uses one exact response per descriptor or enum
option request. The first accepted transaction binds one source principal
through a bounded post-terminal replay lease; foreign traffic cannot evict a
lost result before that lease expires.
The MAVLink dialect root includes `kaptan/config.xml`, `kaptan/log.xml`, The MAVLink dialect root includes `kaptan/config.xml`, `kaptan/log.xml`,
`kaptan/error.xml`, and `kaptan/shutdown.xml`. `kaptan/error.xml`, and `kaptan/shutdown.xml`.
The build watches every fragment and generates one `message::kaptan` module; The build watches every fragment and generates one `message::kaptan` module;
fragments are never separately generated Rust modules. `kaptan-log` itself has fragments are never separately generated Rust modules. `kaptan-log` itself has
no MAVLink, platform, time, allocation, filesystem, or configuration no MAVLink, platform, time, allocation, filesystem, or configuration
dependency. It assigns bounded Critical and BestEffort queues for text logs. dependency. Event creation is independent from sink filtering, allowing a
The platform drains a record only after TX admission. `KAPTAN_LOG` carries future blackbox and MAVLink to select different policies. Each sink owns
severity plus one bounded text field; `KAPTAN_ERROR` carries flags plus bounded bounded Critical and BestEffort queues. The platform drains a MAVLink record
path and additional-information fields. Local saturation accounting remains only after TX admission. `KAPTAN_LOG` carries
inside the hub, facade, and producer mailboxes; heartbeat and safety telemetry severity plus one bounded text field; `KAPTAN_ERROR` carries exact error
remain separate from diagnostics. severity and flags plus bounded path and additional-information fields. Local saturation accounting remains
inside the sink queue, facade, and producer mailboxes; heartbeat and safety
telemetry remain separate from diagnostics.
See [Configuration](configuration.md) for the deployment matrix and GCS upload See [Configuration](configuration.md) for the deployment matrix and GCS transaction
contract, [Logs](logs.md) for the receiver contract, and [Errors](errors.md) contract, [Logs](logs.md) for the receiver contract, and [Errors](errors.md)
for derived-error and failure-reporting scope. for derived-error and failure-reporting scope.
+61 -10
View File
@@ -1,21 +1,72 @@
# GEPRC GEP-F722-HD V2 # GEPRC GEP-F722-HD V2
The GEPRC GEP-F722-HD V2 board declaration uses the ICM-42688-P on SPI3 and The GEPRC GEP-F722-HD V2 board declaration uses the ICM-42688-P on SPI3 and
MAVLink telemetry on USART2. It declares no vertical sensor stream. MAVLink telemetry on USART2. It declares no vertical sensor stream. The
manufacturer's [GEP-F722-HD V2 manual](https://geprc.com/wp-content/uploads/2025/05/GEP-F722-HD-v2%E9%A3%9E%E6%8E%A7_%E4%BA%A7%E5%93%81%E8%AF%B4%E6%98%8E%E4%B9%A6-.pdf)
labels the external UART2 pads `T2` and `R2`.
Its immutable board policy selects the ICM-42688-P yaw-180° mount, logical Its board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU and
MAVLink `Serial2`, endpoint `1/1`, 115200 baud, the documented telemetry heartbeat publication rates, and an enabled MAVLink diagnostic sink with an
schedule, and an `INFO` optional-log threshold. The platform verifies these `INFO` maximum severity. The web configurator may replace those
values against the checked SPI3/USART2 typestate route before it enables target-advertised values in the journal. Range
peripherals. They are compiled image policy, not ground-station parameters. and optical-flow fields are absent because this image has no vertical-sensor
route. Its `ImmutableConfig` keeps the ICM-42688-P route, yaw-180° mount,
USART2 pins and baud, active-high PA13 status LED, and PB0/PB1/PB4/PB5 output
inhibition outside the writable schema. These selections appear together in
the board's immutable typestate literal.
Build and package from the firmware workspace: ## Build and package
From the firmware workspace:
```sh ```sh
cd firmware cd firmware
cargo build --release -p kaptan-geprc-f722-v2 --target thumbv7em-none-eabihf cargo build --release --locked -p kaptan-geprc-f722-v2 \
--target thumbv7em-none-eabihf
./scripts/create-dfu-image.sh target/thumbv7em-none-eabihf/release/kaptan-geprc-f722-v2 ./scripts/create-dfu-image.sh target/thumbv7em-none-eabihf/release/kaptan-geprc-f722-v2
``` ```
The resulting image is telemetry-only and has the shared physical motor-pin The packaging script validates the ELF against the shared F722 linker layout
inhibit boundary. and prints the flash and RAM report before producing the raw binary.
## Flash over USB DFU
Remove the propellers and disconnect the LiPo before connecting USB. This image
is linked at the beginning of internal flash and the command below assumes the
STM32 system-memory ROM DFU loader, not a flash-resident bootloader with an
application offset. Enter the board's documented ROM DFU mode, disconnect any
other STM32 boards in DFU mode, and verify that the intended device is the
listed `0483:df11` target before flashing:
```sh
dfu-util --list
dfu-util --device 0483:df11 --alt 0 \
--dfuse-address 0x08000000:leave \
--download target/thumbv7em-none-eabihf/release/kaptan-geprc-f722-v2.bin
```
## Telemetry wiring
Connect a 3.3 V USB-UART adapter with crossed data lines and common ground:
| Adapter | Flight controller |
| --- | --- |
| `RX` | `T2` |
| `TX` | `R2` |
| `GND` | `GND` |
Then run:
```sh
cargo run --locked -p kaptan-configurator -- \
--serial /dev/serial/by-id/<adapter> --baud 115200
```
Open `http://127.0.0.1:4861`, Save the discovered fields, and manually
power-cycle the controller after Save completes. The flash journal is outside
the application image, so the exact range-limited DFU command above preserves
it. A mass erase or full-chip erase removes committed settings and restores
board factory defaults at the next boot. The image remains telemetry-only and
applies startup motor-pin inhibition. The unsigned local configuration path
assumes this direct wiring; disconnect every other transmitter from `R2` while
configuring.
+40 -11
View File
@@ -5,11 +5,15 @@ MAVLink telemetry on USART1, and the MTF01 range/optical-flow route on UART4.
The checked-in manufacturer datasheet is The checked-in manufacturer datasheet is
`firmware/boards/kakute-f7-mini-v3/datasheet.pdf`. `firmware/boards/kakute-f7-mini-v3/datasheet.pdf`.
Its immutable board policy selects the MPU-6000 body-aligned mount, logical Its board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU, range,
MAVLink `Serial1`, endpoint `1/1`, 115200 baud, the documented telemetry optical-flow and heartbeat publication rates, and an enabled MAVLink diagnostic
schedule, and an `INFO` optional-log threshold. The platform verifies these sink with an `INFO` maximum severity. The web configurator may replace those
values against the checked SPI1/USART1/MTF01 typestate route before it enables target-advertised values in the journal. Its `ImmutableConfig` keeps the
peripherals. They are compiled image policy, not ground-station parameters. MPU-6000 route, body-aligned
mount and concrete driver setup, USART1 pins and baud, MTF01 route and baud,
active-low PD2 status LED, and PB0/PB1/PB4/PB5 output inhibition outside the
writable schema. These selections appear together in the board's immutable
typestate literal.
## Build and package ## Build and package
@@ -17,22 +21,33 @@ From the firmware workspace:
```sh ```sh
cd firmware cd firmware
cargo build --release -p kaptan-kakute-f7-mini-v3 --target thumbv7em-none-eabihf cargo build --release --locked -p kaptan-kakute-f7-mini-v3 \
--target thumbv7em-none-eabihf
./scripts/create-dfu-image.sh target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3 ./scripts/create-dfu-image.sh target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3
``` ```
The packaging script derives the matching binary and linker layout, then The packaging script uses the shared F722 linker layout and prints the flash
prints the flash and RAM report. and RAM report before producing the raw binary.
## Flash over USB DFU ## Flash over USB DFU
Remove the propellers and disconnect the LiPo before connecting USB. This image
is linked at the beginning of internal flash and the command below assumes the
STM32 system-memory ROM DFU loader, not a flash-resident bootloader with an
application offset.
1. Disconnect USB. 1. Disconnect USB.
2. Hold the board's `Boot` button. 2. Hold the board's `Boot` button.
3. Connect USB, then release `Boot` once the STM32 DFU device enumerates. 3. Connect USB, then release `Boot` once the STM32 DFU device enumerates.
4. Flash the generated image: 4. Disconnect any other STM32 boards in DFU mode and verify that the intended
device is the listed `0483:df11` target.
5. Flash the generated image:
```sh ```sh
dfu-util --alt 0 --dfuse-address 0x08000000:leave --download target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3.bin dfu-util --list
dfu-util --device 0483:df11 --alt 0 \
--dfuse-address 0x08000000:leave \
--download target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3.bin
``` ```
## Telemetry wiring ## Telemetry wiring
@@ -45,4 +60,18 @@ Use a 3.3 V USB-to-UART adapter with crossed data lines and common ground:
| `TX` | `R1` | | `TX` | `R1` |
| `GND` | `G` | | `GND` | `G` |
This wiring is telemetry only. It does not enable motor control. Launch the target-described web UI:
```sh
cargo run --locked -p kaptan-configurator -- \
--serial /dev/serial/by-id/<adapter> --baud 115200
```
Open `http://127.0.0.1:4861`, edit the discovered fields, press Save, and
manually power-cycle the controller after Save completes. The flash journal is
outside the application image, so the exact range-limited DFU command above
preserves it. A mass erase or full-chip erase removes committed settings and
restores board factory defaults at the next boot. The image remains
telemetry-only and does not enable motor control. The unsigned local
configuration path assumes this direct wiring; disconnect every other
transmitter from `R1` while configuring.
+181 -58
View File
@@ -1,21 +1,102 @@
# Configuration # Configuration
Kaptan has one generic configuration lifecycle crate, `kaptan-config`. It Kaptan has one generic configuration lifecycle in `kaptan-config`: descriptors,
owns descriptors, typed writes, transactions, validation, generations, and typed writes, transactions, validation, scalar snapshots, and a
stores. It does not grow a crate per subsystem. Flight-specific values live in power-loss-safe two-slot journal. Target models declare fields once; derive code
the single `kaptan-flight-config` candidate; board electrical topology remains generates the registry consumed by both the protocol and the browser. There is
in the immutable board declaration. no board, driver, sensor, schema, or parameter catalog in the configurator.
## Current deployment matrix ## Current deployment matrix
| Deployment | Configuration consumed today | Remote writes | | Deployment | Configuration consumed today | Remote writes |
| --- | --- | --- | | --- | --- | --- |
| `kaptan-sitl serve --config FILE.cbor` | One validated Quad-X profile at process construction. | No live MAVLink endpoint is attached yet. | | `kaptan-sitl serve --config FILE.cbor` | One validated Quad-X configuration at process construction. | No live MAVLink endpoint is attached yet. |
| `kaptan-sitl serve` | The validated factory Quad-X profile. | No persistent store; commits are rejected. | | `kaptan-sitl serve` | The validated factory Quad-X configuration. | No persistent store; commits are rejected. |
| STM32F722 telemetry image | Immutable compiled `BoardConfig` plus checked typestate routes. | Disabled: all inbound MAVLink remains discarded. | | STM32F722 image | Board factory settings, or the newest valid flash-journal snapshot. | Enabled on the directly wired local UART while motor pins remain inhibited. |
The current SITL profile has only settings consumed by its estimator, ## Web configurator
controller, safety supervisor, allocator envelope, or log hub:
Build and flash the board image, connect its MAVLink UART directly to a 3.3 V
USB-UART adapter, then run from `firmware`:
```sh
cargo run --locked -p kaptan-configurator -- \
--serial /dev/serial/by-id/<adapter> --baud 115200
```
Open `http://127.0.0.1:4861`. Edit discovered fields and press
Save. Save commits the complete candidate to the inactive flash slot and writes
the commit marker last. The active runtime does not change. Once Save completes,
manually power-cycle the controller to recover the committed journal and
activate it.
Saving erases one 128-KiB STM32F7 journal sector synchronously. Expect roughly
one second without telemetry or sensor servicing while the target flash
controller is busy; the host uses a separate five-second Save timeout. Keep the
vehicle unpowered except for setup power and do not disconnect it during Save.
The tool discovers the target's protocol version and schema identity, renders
advertised descriptors, and reads/writes values only by stable `FieldId`. A new
board or field needs no host release. The board package remains the composition
root for erased-flash defaults; the platform never switches on a board name.
Enum-backed fields advertise their valid value/label pairs through exact
descriptor and option-index requests, so the browser renders a select control
without knowing the field key or compiling its choices.
The Incoming MAVLink table at the bottom groups live, CRC-valid packets by
source and message ID and shows the measured receive frequency and total count.
Names come from the generated MAVLink dialect decoders; the browser contains no
message catalog. Selecting a message name shows the latest decoded field values;
the diagnostic projection renders `KAPTAN_ERROR` path and additional information
as text. The configurator keeps only one latest value per bounded aggregate,
rather than packet history, and clears it for every serial-link session.
The separate Runtime logs section retains the most recent 512 `KAPTAN_LOG` and
`KAPTAN_ERROR` events in receive order. Each row shows local receive time,
decoded severity, and readable diagnostic text. Repeated events remain separate;
older host-side entries are discarded at the fixed display bound and the UI
reports that count. This event history is independent of the packet table's
single latest-value projection and resets when the serial link changes.
Each F722 board owns the exact settings consumed by its compiled image. Both
current boards advertise:
- MAVLink system and component identity;
- raw-IMU and heartbeat publication rates; and
- whether the MAVLink diagnostic sink is enabled and its maximum severity.
The Kakute image also advertises range and optical-flow publication rates
because its immutable route includes an MTF01. The GEPRC image declares no
vertical sensor, so those fields are absent rather than present-but-disabled.
The UART baud is the immutable bootstrap link for this first configuration
transport. Pass it explicitly to the host with `--baud`.
Each board declares one `UserConfig` root for its compiled driver graph. That
root composes board-local `MavlinkConfig` and `TelemetryConfig` records; derive
code generates recursive routing, validation, and the schema fingerprint. The
board's explicit `FACTORY_USER_CONFIG` literal supplies erased-flash values.
Board-native IDs and publication rates retain their narrow `u8` representation.
Compact enums advertise names and values through explicit indexed descriptor
metadata rather than a hardcoded browser-side configuration catalog.
There is no platform-wide union, reusable concrete board schema, or host-side
switch.
The F722 platform consumes only its stable semantic field IDs through the
generic `Config::field_value` boundary; it never names a board section, Rust
field, or aggregate shape. Range and optical-flow rates are required only when
the immutable hardware manifest exposes those capabilities. Driver- and
board-specific fields remain in the same discovered tree without platform
forwarding code.
The adjacent `IMMUTABLE_CONFIG` literal is the complete physical manifest. Its
typestate expression visibly selects the inhibited output pins, IMU route,
mount and driver setup, MAVLink route and baud, optional vertical-sensor route
and baud, status LED, and telemetry-only role. Those choices are not hidden in
board-specific getters or a `build()` function.
The current SITL configuration has only settings consumed by its estimator,
controller, safety supervisor, allocator envelope, or MAVLink diagnostic sink:
- prearm dwell; - prearm dwell;
- IMU, local-aiding, and command freshness/timing; - IMU, local-aiding, and command freshness/timing;
@@ -24,79 +105,121 @@ controller, safety supervisor, allocator envelope, or log hub:
- mass, collective-thrust, and tilt limits; - mass, collective-thrust, and tilt limits;
- rate PID gains and limits; - rate PID gains and limits;
- actuator minimum, maximum, and slew limits; and - actuator minimum, maximum, and slew limits; and
- the restart-only maximum optional log severity. - the restart-only MAVLink diagnostic-sink enable and maximum severity.
The fixed Quad-X mixer is intentionally not configurable. It is reviewed The fixed Quad-X mixer is intentionally not configurable. It is reviewed
capability data, not an operator-editable array. capability data, not a user-editable array.
Each editable field declares its ID, display key, unit, default, scalar type, Each editable scalar declares its ID, display key, unit, type, and local
and local validation in one `#[config(...)]` attribute. The derive generates validation in one `#[config(...)]` attribute. Unannotated fields of a derived
the descriptor registry and local validation from that declaration; the only record are configuration children; no per-field section marker is needed.
handwritten checks are whole-profile physical relationships such as thrust Factory values belong to the composition root, not the field attributes or a
margin, timing ordering, and actuator limits. `Default` implementation. The only handwritten checks are whole-candidate
physical relationships such as thrust margin, timing ordering, actuator
limits, and compatibility with immutable target capabilities.
## Immutable F722 board policy ## Immutable hardware topology
The checked-in F722 boards consume these compiled `BoardConfig` settings before The checked-in F722 `ImmutableConfig` literals retain the facts that cannot
peripheral initialization: safely be changed by a scalar transaction:
- IMU model and its fixed body mount (`BodyAligned` or `Yaw180`); - IMU model and its fixed body mount (`BodyAligned` or `Yaw180`);
- logical MAVLink port, endpoint IDs, and baud rate; - logical MAVLink port and bootstrap baud rate;
- vertical-sensor capability and telemetry schedule; and - vertical-sensor presence, electrical route, and bootstrap baud rate; and
- maximum optional MAVLink log severity. - output-inhibit and status-LED routes; and
- service-timer frequency.
The platform compares that metadata with the selected `F722BoardRoutes` before The const typestate expression becomes the platform's sole hardware manifest;
claiming pins, UARTs, DMA, or IRQs. A board declaration therefore cannot claim there is no second route structure to compare against it. Incomplete or
an MPU-6000 while selecting the ICM route, select the wrong serial port or unsupported IMU, UART, vertical-sensor, status-LED, and output-inhibit
mount, or request a baud rate that cannot carry the fixed link budget. The combinations cannot call `telemetry_only()`. Runtime validation still rejects a
physical port, sensor driver, pins, DMA, timers, and calibration are not file service frequency the selected timer cannot provide or a baud rate that cannot
configuration and are not GCS-editable. carry the fixed link budget. The physical port, sensor driver, pins, DMA,
timers, and calibration are not file configuration and are not GCS-editable.
F722’s log threshold is immutable board policy. It is deliberately separate Endpoint identity, raw-IMU/heartbeat rates, and MAVLink diagnostic-sink policy
from the SITL profile’s `observability.maximum_log_level`: the F722 image does are overlaid from the recovered operational snapshot before their consumers
not construct a runtime `ConfigManager` or profile store. are constructed.
Pins, sensor models, driver routes, DMA ownership, and calibration remain board
support or dedicated calibration concerns, not UI-selectable strings.
## One CBOR profile format ## Local persistence
There is one unreleased raw profile blob format: SITL and F722 share the same configuration lifecycle and validation rules, but
use target-appropriate private persistence formats. Neither format is exposed
by the MAVLink configuration protocol.
- it is a CBOR map keyed by the discovered numeric `FieldId`s; ### SITL CBOR file
- key `0` is `profile_format = 1` and reserved key `65535` is the 16-byte
`schema_id = "KAPTANPROFILE-01"`; SITL stores one raw, bounded CBOR configuration snapshot directly:
- it is a map keyed by the discovered numeric `FieldId`s;
- key `0` is `snapshot_format = 2` and reserved key `65535` is the 16-byte
fingerprint generated from the complete schema;
- the complete blob is at most 4 KiB; and - the complete blob is at most 4 KiB; and
- malformed, trailing, wrong-format, non-finite, out-of-range, cross-field, - malformed, trailing, wrong-format, non-finite, out-of-range, cross-field,
and capability-invalid values are rejected. and capability-invalid values are rejected.
The map is exact: it has those 26 keys once each. Unknown, duplicate, missing, The map is exact for the compiled schema: every advertised field is present
or indefinite-map keys are rejected. That keeps the unreleased file contract once. Unknown, duplicate, missing, or indefinite-map keys are rejected. Its
unambiguous instead of silently accepting undeclared extensions. field count therefore follows the SITL composition instead of a global
parameter list.
There is no migration path because no version has shipped. The raw blob is the Saving writes a same-directory temporary file, synchronizes its contents, and
future GCS import/export representation. The SITL file is a atomically renames it over the configured file. The file contains no generation
private host envelope `[generation, raw-profile-blob]`; it is not an upload or journal envelope; host filesystem replacement is distinct from the F722
blob and must not be sent to `IMPORT_*` directly. flash power-loss protocol.
## Future GCS upload contract ### F722 flash journal
F722 serializes the board's `UserConfig` as a bounded fixed scalar snapshot:
a magic/version header and schema fingerprint followed by the exact field count
and one `(FieldId, value kind, raw scalar bits)` entry per field. It is not
CBOR. Recovery rejects a wrong schema, field set, value kind, scalar encoding,
or complete-model validation result.
The snapshot is wrapped in a private journal record containing its payload
length, CRC-32C, commit marker, and monotonically increasing sequence. Two
independently erasable flash slots hold at most the old and replacement
snapshots. Saving erases the inactive slot, programs and verifies the complete
record, then writes its commit marker last; the previous valid slot remains
recoverable until then. The private sequence only selects the newer record when
both slots are valid. It does not append configuration history.
There is no migration path because no version has shipped.
## GCS protocol contract
The custom dialect is prepared for a first-party GCS without borrowing The custom dialect is prepared for a first-party GCS without borrowing
`PARAM_*` semantics. A client will: `PARAM_*` semantics. A client will:
1. send `KAPTAN_CONFIG_INFO_REQUEST` and require the exact protocol, profile 1. send `KAPTAN_CONFIG_INFO_REQUEST`, require the exact breaking protocol
format, and schema ID in the correlated `KAPTAN_CONFIG_INFO` reply; version `2.0`,
2. request descriptors and values as needed; and retain the target-advertised schema ID as the exact identity of that
configuration session;
2. request descriptors, enum options, and values by exact index or field ID;
3. open a transaction with `KAPTAN_CONFIG_BEGIN`; 3. open a transaction with `KAPTAN_CONFIG_BEGIN`;
4. either issue typed setters or begin a raw-CBOR upload with the advertised 4. issue typed setters for changed fields;
schema ID, then send aligned idempotent chunks in any order;
5. validate and commit; and 5. validate and commit; and
6. treat `COMMITTED_RESTART_REQUIRED` as persistence only, never live 6. treat `COMMITTED_RESTART_REQUIRED` as persistence only, never live
activation. activation.
An accepted import begin returns a server-issued transfer ID. Every chunk and The directly wired local UART is the initial operational configuration
finish request echoes it, preventing delayed data from an earlier transfer transport. The board composition admits CRC-valid unsigned configuration
from entering the current one. The service validates CRC-32C and the entire commands on that link; CRC supplies integrity, not authentication. This does
candidate before it replaces the RAM transaction. not authorize a shared or remotely reachable MAVLink network. Use a direct
adapter connection and disconnect every other transmitter from the board's RX
line because the firmware cannot prove electrical exclusivity. Motor outputs
remain physically inhibited in both current F722 images.
This is protocol groundwork, not a claim of active aircraft configuration: The first accepted `BEGIN` binds the one protocol instance to that MAVLink
F722 needs authenticated ingress, source binding and replay protection, source. The binding and its sole most-recent result remain for a ten-second
journalled target storage, a disarmed/inhibited activation permit, and atomic lease, including after `COMMIT` or `ABORT`, so retrying a lost terminal reply
consumer rebuild/reset before it may accept any configuration command. cannot be displaced by another source. A UART receive fault or lease expiry
clears the binding; another source may then begin. This is bounded direct-link
serialization, not authentication.
A remotely reachable GCS transport still requires MAVLink signing, source/key
binding, persistent anti-replay state, and provisioning/rotation. Those are
future additions to the same target-described configuration protocol, not a
different board or parameter catalog.
+6 -3
View File
@@ -7,7 +7,7 @@ cd firmware
cargo test --workspace --offline cargo test --workspace --offline
cargo clippy --workspace --all-targets --offline --exclude kaptan-geprc-f722-v2 --exclude kaptan-kakute-f7-mini-v3 -- -D warnings cargo clippy --workspace --all-targets --offline --exclude kaptan-geprc-f722-v2 --exclude kaptan-kakute-f7-mini-v3 -- -D warnings
cargo clippy -p platform-stm32f7 --all-targets --offline -- -D warnings cargo clippy -p platform-stm32f7 --all-targets --offline -- -D warnings
cargo fmt --check cargo fmt --all --check
git diff --check git diff --check
``` ```
@@ -15,8 +15,11 @@ git diff --check
```sh ```sh
cd firmware cd firmware
cargo check -p kaptan-geprc-f722-v2 --release --target thumbv7em-none-eabihf --offline cargo clippy -p kaptan-geprc-f722-v2 -p kaptan-kakute-f7-mini-v3 \
cargo check -p kaptan-kakute-f7-mini-v3 --release --target thumbv7em-none-eabihf --offline --target thumbv7em-none-eabihf --offline -- -D warnings
cargo build --release --locked \
-p kaptan-geprc-f722-v2 -p kaptan-kakute-f7-mini-v3 \
--target thumbv7em-none-eabihf --offline
``` ```
## Strict core coverage ## Strict core coverage
+7 -6
View File
@@ -28,12 +28,13 @@ for safety state, actuator inhibit, or typed configuration results.
rule, and protocol error code. rule, and protocol error code.
- Runtime driver and link faults reach the F722 MAVLink worker as a - Runtime driver and link faults reach the F722 MAVLink worker as a
`KAPTAN_ERROR` path, subject to bounded transport admission. The error `KAPTAN_ERROR` path, subject to bounded transport admission. The error
payload is `{ flags, path_length, additional_information_length, path[96], payload is `{ level, flags, path_length, additional_information_length,
additional_information[64] }`; each length identifies the valid UTF-8 path[96], additional_information[64] }`; `level` preserves the originating
prefix and the optional information field may be empty. A `KaptanError` MAVLink-compatible severity from Emergency through Error, each length
derive supplies the type/variant path and normally leaves additional identifies the valid UTF-8 prefix, and the optional information field may be
information empty. `log::error!` uses the Rust log target as the path and empty. A `KaptanError` derive supplies the type/variant path and normally
the formatted message as additional information. leaves additional information empty. `log::error!` uses the Rust log target
as the path and the formatted message as additional information.
- A rejected configuration operation may enqueue a companion `KAPTAN_ERROR` - A rejected configuration operation may enqueue a companion `KAPTAN_ERROR`
whose path is the high-level `ProtocolError` identity. It is intentionally whose path is the high-level `ProtocolError` identity. It is intentionally
not correlated and carries no field/rule detail; the matching not correlated and carries no field/rule detail; the matching
+9 -2
View File
@@ -4,6 +4,12 @@
Use the firmware toolchain, Rust 1.90. The firmware workspace declares the Use the firmware toolchain, Rust 1.90. The firmware workspace declares the
embedded F7 targets and `llvm-tools-preview` in `firmware/rust-toolchain.toml`. embedded F7 targets and `llvm-tools-preview` in `firmware/rust-toolchain.toml`.
The repository development shell also supplies `dfu-util` and the checked
`mdbook` version:
```sh
nix develop
```
For host development, run: For host development, run:
@@ -20,10 +26,11 @@ target-specific commands in [Development and verification](development.md).
| Path | Responsibility | | Path | Responsibility |
| --- | --- | | --- | --- |
| `firmware/boards/` | Immutable board declarations and linker layouts. | | `firmware/boards/` | Board-owned user schemas, factory values, immutable hardware declarations, and image composition roots. |
| `firmware/platforms/stm32f7/` | Reviewed F722 RTIC platform and peripheral ownership. | | `firmware/platforms/stm32f7/` | Reviewed F722 RTIC platform, peripheral ownership, and shared linker layout. |
| `firmware/libs/` | Typed math, estimation, control, safety, protocol, and driver crates. | | `firmware/libs/` | Typed math, estimation, control, safety, protocol, and driver crates. |
| `firmware/tools/sitl/` | Host-only closed-loop Gazebo simulation. | | `firmware/tools/sitl/` | Host-only closed-loop Gazebo simulation. |
| `firmware/tools/configurator/` | Board-agnostic loopback web UI and serial bridge. |
| `docs/` | This Markdown documentation site. | | `docs/` | This Markdown documentation site. |
Do not add board-local READMEs. Add a page here instead, then link it from Do not add board-local READMEs. Add a page here instead, then link it from
+6 -6
View File
@@ -15,8 +15,8 @@ Markdown.
- Firmware source and its Rust workspace begin in `firmware/`. - Firmware source and its Rust workspace begin in `firmware/`.
- Board work belongs under [Boards](boards/index.md). - Board work belongs under [Boards](boards/index.md).
- The currently supported closed-loop simulation is [Host SITL](sitl.md). - The currently supported closed-loop simulation is [Host SITL](sitl.md).
- [Configuration](configuration.md) distinguishes the current SITL profile - [Configuration](configuration.md) explains target-described user settings
from immutable F722 board policy. and immutable F722 hardware policy.
- [Logs](logs.md) and [Errors](errors.md) describe the custom MAVLink - [Logs](logs.md) and [Errors](errors.md) describe the custom MAVLink
observability surface and its current safety scope. observability surface and its current safety scope.
- Before submitting changes, follow [Development and verification](development.md). - Before submitting changes, follow [Development and verification](development.md).
@@ -29,7 +29,7 @@ only defines the firmware workspace boundary. Keep pages in Markdown, add each
page to `SUMMARY.md`, and place commands beside the assumptions and safety page to `SUMMARY.md`, and place commands beside the assumptions and safety
boundary they depend on. boundary they depend on.
The current configuration contract is intentionally deployment-specific. A The current configuration contract is target-described. A SITL Quad-X profile
SITL Quad-X profile is a bounded restart-only CBOR snapshot; F722 hardware and each F722 board expose only values consumed by that compiled target;
selection remains immutable board policy. Neither is permission for an physical F722 hardware selection remains immutable board policy. No writable
operator to substitute runtime values or bypass an immutable safety decision. snapshot can bypass an immutable safety decision.
+44 -17
View File
@@ -9,9 +9,13 @@ log::warn!("range aid stale");
log::error!("sensor transfer failed"); // emitted as KAPTAN_ERROR log::error!("sensor transfer failed"); // emitted as KAPTAN_ERROR
``` ```
`kaptan-log` formats once into a fixed bounded buffer, queues locally, and `kaptan-log` formats each event once into a fixed bounded buffer and never
never sends MAVLink, allocates, blocks, changes flight state, or touches DMA. sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The
The sole MAVLink worker drains admitted records. F722 deliberately does not composition fans the event into each enabled sink; the sole MAVLink worker
drains its bounded sink queue. Ordinary text, error paths, and error details
use distinct 160-, 96-, and 64-byte storage types, so a queued record retains
exactly the common diagnostic-envelope capacity and needs no adapter-side
clipping buffer. F722 deliberately does not
link this facade in ISR, DMA, control, actuator, panic, hard-fault, or shutdown link this facade in ISR, DMA, control, actuator, panic, hard-fault, or shutdown
contexts; those paths use static fault mailboxes that the worker turns into contexts; those paths use static fault mailboxes that the worker turns into
messages later. messages later.
@@ -25,7 +29,7 @@ orderly-shutdown observations:
```text ```text
KAPTAN_LOG { level, flags, message_length, message[160] } KAPTAN_LOG { level, flags, message_length, message[160] }
KAPTAN_ERROR { KAPTAN_ERROR {
flags, path_length, additional_information_length, level, flags, path_length, additional_information_length,
path[96], additional_information[64] path[96], additional_information[64]
} }
KAPTAN_SHUTDOWN { reason } KAPTAN_SHUTDOWN { reason }
@@ -38,31 +42,54 @@ fixed arrays into UTF-8 prefixes. Generated MAVLink framing alone does not
enforce these semantic length fields. `KAPTAN_LOG` displays its text at the enforce these semantic length fields. `KAPTAN_LOG` displays its text at the
MAVLink severity in `level`; `TRACE` is encoded as `DEBUG` plus the `TRACE` MAVLink severity in `level`; `TRACE` is encoded as `DEBUG` plus the `TRACE`
flag. flag.
`KAPTAN_ERROR` is error-only and accepts only `TRUNCATED` and `COALESCED`; a `KAPTAN_ERROR.level` preserves the originating MAVLink-compatible severity from
`TRACE` bit is never emitted there. Unknown future flag bits must be ignored. Emergency through Error. The error channel accepts only `TRUNCATED` and
`COALESCED`; a `TRACE` bit is never emitted there. Unknown future flag bits
must be ignored. `COALESCED` means that one or more later observations from
the same source mailbox were folded while the retained first error was pending;
it does not claim that their paths or details were identical.
The derived error path is intentionally not a numeric error catalog; renaming The derived error path is intentionally not a numeric error catalog; renaming
its Rust module/type/variant changes that identity. Error details requiring its Rust module/type/variant changes that identity. Error details requiring
machine action stay in their owning protocol, notably `KAPTAN_CONFIG_RESULT`. machine action stay in their owning protocol, notably `KAPTAN_CONFIG_RESULT`.
`KAPTAN_SHUTDOWN` has only its typed reason and is valid only after an orderly `KAPTAN_SHUTDOWN` has only its typed reason and is valid only after an orderly
output-inhibited completion. Delivery is bounded and lossy under link pressure; output-inhibited completion. Delivery is bounded and lossy under link pressure;
heartbeat and safety telemetry use separate paths. heartbeat and safety telemetry use separate paths. Logs have no publication
rate setting and are not periodic streams. A retained event leaves the
MAVLink sink queue once the lower transport admits it; temporary queue pressure
only defers that same event.
## Filtering ## Filtering
The SITL profile’s restart-only `observability.maximum_log_level` accepts The restart-only `mavlink.logging.enabled` field controls the MAVLink
MAVLink severities Error (3) through Debug (7). For example, selecting Warning diagnostic sink independently from future sinks such as a blackbox.
permits warning records while suppressing info and debug records. Error-level `mavlink.logging.maximum_severity` accepts the complete MAVLink severity range,
records always use `KAPTAN_ERROR` and remain non-filterable. F722 uses its Emergency (0) through Debug (7). For example, selecting Warning permits warning
immutable board log threshold instead, because it has no active runtime and more severe events while suppressing notice, info, and debug. Disabling the
profile. sink suppresses both `KAPTAN_LOG` and `KAPTAN_ERROR` on MAVLink without
suppressing events from another sink. F722 uses the validated policy recovered
at boot, falling back to its board factory when the journal is empty or
invalid.
Severity remains a typed `Severity` value inside the board and runtime. Generic
schema discovery exposes its named choices one at a time to the configurator,
so the UI does not carry a field-key-specific severity list; numeric conversion
exists only at the generic configuration transport and snapshot boundary. The MAVLink `level`
field intentionally remains `uint8_t`: this generator represents XML enums as
four-byte Rust values, so attaching an XML enum would widen the generated
payload type. The adapter performs the checked one-byte conversion at that
unavoidable wire boundary instead.
Cargo `log/max_level_*` features compile calls away before the facade sees Cargo `log/max_level_*` features compile calls away before the facade sees
them; they are not a supported filtering mechanism. The build policy keeps them; they are not a supported filtering mechanism. The build policy keeps
that decision out of workspace dependencies. that decision out of workspace dependencies.
The tested `SitlConfigRuntime` composition proves `log!` reaches a generated The SITL facade ingress is transport-neutral and unfiltered. The tested
`SitlConfigRuntime` composition applies the configured MAVLink policy when
fanning an event into that sink and proves `log!` reaches a generated
`KAPTAN_LOG` payload, and rejected configuration replies enqueue a generated `KAPTAN_LOG` payload, and rejected configuration replies enqueue a generated
`KAPTAN_ERROR` companion without replacing their authoritative result. `kaptan-sitl `KAPTAN_ERROR` companion without replacing their authoritative result.
serve` does not yet attach a config/diagnostic MAVLink link, and F722 emits only `kaptan-sitl serve` does not yet attach a config/diagnostic MAVLink link. F722
outbound telemetry/diagnostic frames while rejecting all inbound authority. images accept only the unsigned configuration service on their directly wired
local UART; that direct-wire assumption does not extend to a shared or remote
MAVLink network.
+41 -12
View File
@@ -1,30 +1,59 @@
# MAVLink and telemetry # MAVLink and telemetry
Kaptan emits telemetry using MAVLink 2 framing. The production receiver does Kaptan emits telemetry using MAVLink 2 framing. Inbound processing is narrowly
not promote inbound MAVLink frames to authority records: scoped:
- MAVLink 1 is discarded. - MAVLink 1 is discarded.
- CRC-invalid MAVLink 2 frames are discarded. - CRC-invalid MAVLink 2 frames are discarded.
- Signed frames are discarded because no signature verifier or persistent - Signed frames are discarded because no signature verifier or persistent
replay state exists. replay state exists.
- Unsigned MAVLink 2 frames are also discarded; a V2 CRC detects corruption, - CRC-valid unsigned MAVLink 2 frames are accepted only for the exact-target
not authentication. Kaptan configuration service on the directly wired local UART. Other inbound
messages do not become authority.
`TODO(signing)`: any future inbound authority requires verified MAVLink 2 `TODO(signing)`: any future shared or remote inbound authority requires verified
signing, configured source/target binding, persistent anti-replay state, and a MAVLink 2 signing, configured source/target binding, persistent anti-replay
provisioning/key-rotation policy as one reviewed feature. state, and a provisioning/key-rotation policy as one reviewed feature.
The local UART is Kaptan's initial operational configuration transport, not an
authenticated remote-control channel. Any transmitter electrically connected
to that RX line can issue configuration commands, so connect the USB-UART
adapter directly and disconnect other transmitters. The platform retains its
startup-configured low motor-output state throughout this workflow; no marker
type is treated as GPIO ownership or command authority. A networked GCS must
add verified signing, source binding, and durable replay protection before it
can receive authority.
Configuration protocol `2.0` admits one source principal from `BEGIN` until
its ten-second lease expires or the UART receive path faults. That lease also
covers the post-commit retry window, preventing another source from evicting a
lost result. It serializes the direct link but does not authenticate its peer.
Telemetry transmission uses bounded frame classes. A critical frame may Telemetry transmission uses bounded frame classes. A critical frame may
replace pending best-effort traffic, but never the DMA-owned active buffer. replace pending best-effort traffic, but never the DMA-owned active buffer.
Completion retries preserve ordering and retain a transiently busy frame for a Completion retries preserve ordering and retain a transiently busy frame for a
later service turn. later service turn.
The local web configurator exposes a bounded live view of CRC-valid inbound
frames. It groups packets by source and message ID and measures receive
frequency in one-second windows. Selecting a message reveals the latest decoded
fields, including human-readable `KAPTAN_ERROR` text. This observation path
retains one latest value per bounded aggregate rather than packet history and
grants no additional command authority.
Diagnostic events also feed a separate bounded Runtime logs view at
`http://127.0.0.1:4861`. That view retains individual `KAPTAN_LOG` and
`KAPTAN_ERROR` events in receive order with local receive time, severity, and
readable text. Packet inspection remains a latest-value view; it is not used as
log history.
The custom Kaptan definitions are aggregated by `definitions/kaptan.xml` from The custom Kaptan definitions are aggregated by `definitions/kaptan.xml` from
`kaptan/config.xml`, `kaptan/log.xml`, `kaptan/error.xml`, and `kaptan/config.xml`, `kaptan/log.xml`, `kaptan/error.xml`, and
`kaptan/shutdown.xml`. `kaptan/shutdown.xml`.
`KAPTAN_LOG` is an outbound human-readable four-field record. `KAPTAN_ERROR` `KAPTAN_LOG` is an outbound human-readable four-field record. `KAPTAN_ERROR`
is its separate bounded error channel, while `KAPTAN_SHUTDOWN` represents only is its separate bounded error channel and preserves the originating error
a completed orderly output-inhibited shutdown. Configuration messages are GCS severity, while `KAPTAN_SHUTDOWN` represents only
groundwork only: the current F722 receiver rejects every inbound frame before a completed orderly output-inhibited shutdown. Configuration messages back the
configuration dispatch. See [Configuration](configuration.md), [Logs](logs.md), current target-described web configurator and the future signed GCS. See
and [Errors](errors.md) for the exact contracts. [Configuration](configuration.md), [Logs](logs.md), and [Errors](errors.md) for
the exact contracts.
+15 -11
View File
@@ -4,15 +4,15 @@ This page collects stable limits and points to the detailed contracts.
| Surface | Current contract | | Surface | Current contract |
| --- | --- | | --- | --- |
| Flight profile | One 4 KiB-or-smaller raw CBOR blob, `profile_format = 1`, schema ID `KAPTANPROFILE-01`. | | SITL file | One raw bounded CBOR configuration snapshot, replaced through a same-directory temporary file and atomic rename. |
| SITL file | Private `[generation, raw-profile-blob]` envelope; not a MAVLink upload blob. | | F722 persistence | One bounded fixed scalar snapshot inside each slot of a power-loss-safe two-slot flash journal. |
| Config transaction | One owner-bound RAM transaction; typed writes or 192-byte idempotent CBOR chunks; commit is restart-required. | | Config transaction | One owner-bound RAM transaction with typed scalar writes; commit is restart-required. |
| Config discovery | Correlated `KAPTAN_CONFIG_INFO_REQUEST` / `KAPTAN_CONFIG_INFO`, then descriptor/value requests. | | Config discovery | Correlated `KAPTAN_CONFIG_INFO_REQUEST` / `KAPTAN_CONFIG_INFO`, then exact-index descriptor/enum-option and field-value requests. |
| Diagnostics | `KAPTAN_LOG` (51020) for ordinary severity/text; `KAPTAN_ERROR` (51021) for a bounded `{ path[96], additional_information[64] }` error; and `KAPTAN_SHUTDOWN` (51022) for completed orderly output-inhibited shutdowns. | | Diagnostics | `KAPTAN_LOG` (51020) for ordinary severity/text; `KAPTAN_ERROR` (51021) for a bounded `{ level, path[96], additional_information[64] }` error; and `KAPTAN_SHUTDOWN` (51022) for completed orderly output-inhibited shutdowns. |
| F722 configuration | Immutable compiled board policy only; inbound MAVLink configuration remains disabled. | | F722 configuration | Target-described fields and board factory defaults; the current local transport is a directly wired unsigned UART with motor outputs physically inhibited. |
Read [Configuration](configuration.md) for the field/consumer matrix and GCS Read [Configuration](configuration.md) for the field/consumer matrix and GCS
upload sequence, [Logs](logs.md) for receiver decoding and filtering, and transaction sequence, [Logs](logs.md) for receiver decoding and filtering, and
[Errors](errors.md) for error propagation and panic scope. [Errors](errors.md) for error propagation and panic scope.
## Verification ## Verification
@@ -23,9 +23,13 @@ Before review, run:
cd firmware cd firmware
cargo fmt --all --check cargo fmt --all --check
cargo test --workspace --locked --offline cargo test --workspace --locked --offline
cargo clippy --workspace --all-targets --locked -- -D warnings cargo clippy --workspace --all-targets \
--exclude kaptan-kakute-f7-mini-v3 \
--exclude kaptan-geprc-f722-v2 --locked --offline -- -D warnings
cargo clippy -p kaptan-kakute-f7-mini-v3 -p kaptan-geprc-f722-v2 \
--target thumbv7em-none-eabihf --locked --offline -- -D warnings
``` ```
The embedded no-std binaries require their target-specific build setup; the The target-specific lint verifies the local configuration receiver and journal
host workspace test suite continues to assert that the telemetry F722 image path. The host suite separately asserts that configuration ingress cannot reach
has no inbound authority or actuator path. an actuator path.
+13 -4
View File
@@ -1,14 +1,23 @@
# Safety boundary # Safety boundary
Every checked-in F722 image inhibits PB0, PB1, PB4, and PB5 before normal Every checked-in F722 image drives PB0, PB1, PB4, and PB5 low before normal
board initialization. The interlock configures each pin as a low, push-pull board initialization. This startup output inhibition configures each pin as a
GPIO output; it runs before clocks, board routing, UART setup, or RTIC tasks. low, push-pull GPIO output; it runs before clock-tree setup, board routing,
UART setup, or RTIC tasks. There is no marker or token standing in for the
register writes.
This is a firmware startup property, not a hardware latch. Reset temporarily
returns GPIO configuration to the MCU reset state, and the code cannot prove
external routing, pull resistors, ESC polarity, or ESC power behavior. Board
support must document those electrical assumptions; continuous inhibition
through reset requires board hardware that provides it.
There is no checked-in platform actuator route: There is no checked-in platform actuator route:
- no DShot or PWM peripheral implementation is linked; - no DShot or PWM peripheral implementation is linked;
- no TIM3/TIM5 motor task or DMA output path exists; - no TIM3/TIM5 motor task or DMA output path exists;
- MAVLink input has no production authority path; - MAVLink input is accepted only by the configuration service and has no
actuator path;
- a future verified arm command is still acknowledged as unsupported. - a future verified arm command is still acknowledged as unsupported.
The protocol reference crate remains in the workspace only as a framing and The protocol reference crate remains in the workspace only as a framing and
+4 -3
View File
@@ -46,10 +46,11 @@ kaptan-sitl serve --config kaptan-sitl.cbor
``` ```
The file selects the restart-only profile used to build the estimator, The file selects the restart-only profile used to build the estimator,
controller, allocator envelope, safety supervisor, and optional log filter at controller, allocator envelope, safety supervisor, and MAVLink log-sink policy at
process start. It is not the raw GCS upload blob. `kaptan-sitl serve` retains process start. It is local persistence and never appears on MAVLink.
`kaptan-sitl serve` retains
the central manager for that boot but does not yet open a MAVLink config/log the central manager for that boot but does not yet open a MAVLink config/log
endpoint; see [Configuration](configuration.md) for the exact upload groundwork endpoint; see [Configuration](configuration.md) for the exact transaction contract
and safety boundary. and safety boundary.
## Limits ## Limits