docs: document board configuration workflow
This commit is contained in:
1 parent
b7631c0bc7
commit
97acb2a2d7
13 files changed
+470
-173
No files matched your search
+43
-30
@@ -10,19 +10,22 @@ board declaration
|
||||
F722 platform / RTIC application ──► data channel ──► MAVLink telemetry
|
||||
│
|
||||
├── physical sensor drivers
|
||||
└── motor-pin inhibit interlock
|
||||
└── startup motor-pin inhibition
|
||||
|
||||
portable libraries
|
||||
math ─► navigation ─► control ─► safety
|
||||
```
|
||||
|
||||
The board contract selects one immutable `BoardProfile`. The checked-in
|
||||
profile is `TelemetryOnly`; `ExternalControlOnly` is represented explicitly
|
||||
but rejected at validation time because it has no reviewed runtime.
|
||||
Each F722 board contract pairs a board-owned `UserConfig` schema and explicit
|
||||
`FACTORY_USER_CONFIG` with a board-owned `ImmutableConfig`. The immutable root
|
||||
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,
|
||||
and bounded TX classification. Board code supplies physical routes and
|
||||
telemetry configuration; it does not receive generic output authority.
|
||||
and bounded TX classification. Board code supplies physical routes, target
|
||||
schema, and factory values; it does not receive generic output authority.
|
||||
|
||||
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
|
||||
│ borrows
|
||||
kaptan-flight-runtime
|
||||
├── one ConfigManager ──► kaptan-config ──► flight schema/CBOR
|
||||
└── one kaptan-log hub
|
||||
├── one ConfigManager ──► kaptan-config ──► flight schema/store
|
||||
└── one bounded MAVLink log-sink queue
|
||||
│
|
||||
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
|
||||
adapter. The core uses numeric field IDs and typed scalar values; descriptor
|
||||
text is metadata, not a wire identity. Discovery/value reads, bounded
|
||||
descriptor pages, and structured results are custom-dialect records. Runtime
|
||||
logs use one bounded text message with MAVLink severity and flags. CBOR import uses a fixed
|
||||
4 KiB transaction buffer and
|
||||
fixed 192-byte chunks; its decoded candidate still goes through the same whole
|
||||
profile validation path. The core owns one RAM transaction and the distinction
|
||||
text is metadata, not a wire identity. Discovery/value reads, exact-index
|
||||
descriptor and enum-option requests, and structured results are custom-dialect
|
||||
records. Runtime logs use one bounded text message with MAVLink severity and
|
||||
flags. Remote writes use only schema-described typed scalar setters. The core
|
||||
owns one RAM transaction and the distinction
|
||||
between boot-active, committed, and editable candidate snapshots. In the
|
||||
current P1 policy a commit is restart-only. It cannot mutate controller or
|
||||
estimator state in flight.
|
||||
|
||||
One current CBOR profile format is a bounded complete snapshot. There is no
|
||||
migration reader: any other format is rejected. SITL supplies the host file
|
||||
adapter and persists a nonzero generation alongside its raw profile payload.
|
||||
Motor allocation/mixer topology is immutable compiled
|
||||
vehicle capability data, never a scalar field or CBOR candidate member. The
|
||||
bare-metal receiver continues to reject inbound control authority. Target
|
||||
persistence, authenticated ingress, durable audit logging, disarmed
|
||||
activation, and atomic consumer reconstruction remain separate reviewed work
|
||||
and cannot be implied by a valid CBOR file or CRC.
|
||||
Target-owned stores may serialize one bounded complete CBOR snapshot. SITL
|
||||
supplies the host file adapter and persists a private nonzero storage sequence
|
||||
alongside that snapshot. The serialization and sequence are not configuration
|
||||
state and are never exposed by the MAVLink protocol.
|
||||
Motor allocation/mixer topology is immutable compiled vehicle capability data,
|
||||
never a scalar field or CBOR candidate member. F722 now recovers operational
|
||||
settings from a generic two-slot journal before constructing consumers. Its
|
||||
directly wired local UART accepts only exact-target, CRC-valid configuration
|
||||
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`,
|
||||
`kaptan/error.xml`, and `kaptan/shutdown.xml`.
|
||||
The build watches every fragment and generates one `message::kaptan` module;
|
||||
fragments are never separately generated Rust modules. `kaptan-log` itself has
|
||||
no MAVLink, platform, time, allocation, filesystem, or configuration
|
||||
dependency. It assigns bounded Critical and BestEffort queues for text logs.
|
||||
The platform drains a record only after TX admission. `KAPTAN_LOG` carries
|
||||
severity plus one bounded text field; `KAPTAN_ERROR` carries flags plus bounded
|
||||
path and additional-information fields. Local saturation accounting remains
|
||||
inside the hub, facade, and producer mailboxes; heartbeat and safety telemetry
|
||||
remain separate from diagnostics.
|
||||
dependency. Event creation is independent from sink filtering, allowing a
|
||||
future blackbox and MAVLink to select different policies. Each sink owns
|
||||
bounded Critical and BestEffort queues. The platform drains a MAVLink record
|
||||
only after TX admission. `KAPTAN_LOG` carries
|
||||
severity plus one bounded text field; `KAPTAN_ERROR` carries exact error
|
||||
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)
|
||||
for derived-error and failure-reporting scope.
|
||||
|
||||
|
||||
@@ -1,21 +1,72 @@
|
||||
# GEPRC GEP-F722-HD V2
|
||||
|
||||
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
|
||||
MAVLink `Serial2`, endpoint `1/1`, 115200 baud, the documented telemetry
|
||||
schedule, and an `INFO` optional-log threshold. The platform verifies these
|
||||
values against the checked SPI3/USART2 typestate route before it enables
|
||||
peripherals. They are compiled image policy, not ground-station parameters.
|
||||
Its board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU and
|
||||
heartbeat publication rates, and an enabled MAVLink diagnostic sink with an
|
||||
`INFO` maximum severity. The web configurator may replace those
|
||||
target-advertised values in the journal. Range
|
||||
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
|
||||
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
|
||||
```
|
||||
|
||||
The resulting image is telemetry-only and has the shared physical motor-pin
|
||||
inhibit boundary.
|
||||
The packaging script validates the ELF against the shared F722 linker layout
|
||||
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.
|
||||
@@ -5,11 +5,15 @@ MAVLink telemetry on USART1, and the MTF01 range/optical-flow route on UART4.
|
||||
The checked-in manufacturer datasheet is
|
||||
`firmware/boards/kakute-f7-mini-v3/datasheet.pdf`.
|
||||
|
||||
Its immutable board policy selects the MPU-6000 body-aligned mount, logical
|
||||
MAVLink `Serial1`, endpoint `1/1`, 115200 baud, the documented telemetry
|
||||
schedule, and an `INFO` optional-log threshold. The platform verifies these
|
||||
values against the checked SPI1/USART1/MTF01 typestate route before it enables
|
||||
peripherals. They are compiled image policy, not ground-station parameters.
|
||||
Its board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU, range,
|
||||
optical-flow and heartbeat publication rates, and an enabled MAVLink diagnostic
|
||||
sink with an `INFO` maximum severity. The web configurator may replace those
|
||||
target-advertised values in the journal. Its `ImmutableConfig` keeps the
|
||||
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
|
||||
|
||||
@@ -17,22 +21,33 @@ From the firmware workspace:
|
||||
|
||||
```sh
|
||||
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
|
||||
```
|
||||
|
||||
The packaging script derives the matching binary and linker layout, then
|
||||
prints the flash and RAM report.
|
||||
The packaging script uses the shared F722 linker layout 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.
|
||||
|
||||
1. Disconnect USB.
|
||||
2. Hold the board's `Boot` button.
|
||||
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
|
||||
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
|
||||
@@ -45,4 +60,18 @@ Use a 3.3 V USB-to-UART adapter with crossed data lines and common ground:
|
||||
| `TX` | `R1` |
|
||||
| `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
@@ -1,21 +1,102 @@
|
||||
# Configuration
|
||||
|
||||
Kaptan has one generic configuration lifecycle crate, `kaptan-config`. It
|
||||
owns descriptors, typed writes, transactions, validation, generations, and
|
||||
stores. It does not grow a crate per subsystem. Flight-specific values live in
|
||||
the single `kaptan-flight-config` candidate; board electrical topology remains
|
||||
in the immutable board declaration.
|
||||
Kaptan has one generic configuration lifecycle in `kaptan-config`: descriptors,
|
||||
typed writes, transactions, validation, scalar snapshots, and a
|
||||
power-loss-safe two-slot journal. Target models declare fields once; derive code
|
||||
generates the registry consumed by both the protocol and the browser. There is
|
||||
no board, driver, sensor, schema, or parameter catalog in the configurator.
|
||||
|
||||
## Current deployment matrix
|
||||
|
||||
| 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` | The validated factory Quad-X profile. | No persistent store; commits are rejected. |
|
||||
| STM32F722 telemetry image | Immutable compiled `BoardConfig` plus checked typestate routes. | Disabled: all inbound MAVLink remains discarded. |
|
||||
| `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 configuration. | No persistent store; commits are rejected. |
|
||||
| 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,
|
||||
controller, safety supervisor, allocator envelope, or log hub:
|
||||
## Web configurator
|
||||
|
||||
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;
|
||||
- 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;
|
||||
- rate PID gains and limits;
|
||||
- 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
|
||||
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,
|
||||
and local validation in one `#[config(...)]` attribute. The derive generates
|
||||
the descriptor registry and local validation from that declaration; the only
|
||||
handwritten checks are whole-profile physical relationships such as thrust
|
||||
margin, timing ordering, and actuator limits.
|
||||
Each editable scalar declares its ID, display key, unit, type, and local
|
||||
validation in one `#[config(...)]` attribute. Unannotated fields of a derived
|
||||
record are configuration children; no per-field section marker is needed.
|
||||
Factory values belong to the composition root, not the field attributes or a
|
||||
`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
|
||||
peripheral initialization:
|
||||
The checked-in F722 `ImmutableConfig` literals retain the facts that cannot
|
||||
safely be changed by a scalar transaction:
|
||||
|
||||
- IMU model and its fixed body mount (`BodyAligned` or `Yaw180`);
|
||||
- logical MAVLink port, endpoint IDs, and baud rate;
|
||||
- vertical-sensor capability and telemetry schedule; and
|
||||
- maximum optional MAVLink log severity.
|
||||
- logical MAVLink port and bootstrap baud rate;
|
||||
- vertical-sensor presence, electrical route, and bootstrap baud rate; and
|
||||
- output-inhibit and status-LED routes; and
|
||||
- service-timer frequency.
|
||||
|
||||
The platform compares that metadata with the selected `F722BoardRoutes` before
|
||||
claiming pins, UARTs, DMA, or IRQs. A board declaration therefore cannot claim
|
||||
an MPU-6000 while selecting the ICM route, select the wrong serial port or
|
||||
mount, or request a baud rate that cannot carry the fixed link budget. The
|
||||
physical port, sensor driver, pins, DMA, timers, and calibration are not file
|
||||
configuration and are not GCS-editable.
|
||||
The const typestate expression becomes the platform's sole hardware manifest;
|
||||
there is no second route structure to compare against it. Incomplete or
|
||||
unsupported IMU, UART, vertical-sensor, status-LED, and output-inhibit
|
||||
combinations cannot call `telemetry_only()`. Runtime validation still rejects a
|
||||
service frequency the selected timer cannot provide or a baud rate that cannot
|
||||
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
|
||||
from the SITL profile’s `observability.maximum_log_level`: the F722 image does
|
||||
not construct a runtime `ConfigManager` or profile store.
|
||||
Endpoint identity, raw-IMU/heartbeat rates, and MAVLink diagnostic-sink policy
|
||||
are overlaid from the recovered operational snapshot before their consumers
|
||||
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;
|
||||
- key `0` is `profile_format = 1` and reserved key `65535` is the 16-byte
|
||||
`schema_id = "KAPTANPROFILE-01"`;
|
||||
### SITL CBOR file
|
||||
|
||||
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
|
||||
- malformed, trailing, wrong-format, non-finite, out-of-range, cross-field,
|
||||
and capability-invalid values are rejected.
|
||||
|
||||
The map is exact: it has those 26 keys once each. Unknown, duplicate, missing,
|
||||
or indefinite-map keys are rejected. That keeps the unreleased file contract
|
||||
unambiguous instead of silently accepting undeclared extensions.
|
||||
The map is exact for the compiled schema: every advertised field is present
|
||||
once. Unknown, duplicate, missing, or indefinite-map keys are rejected. Its
|
||||
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
|
||||
future GCS import/export representation. The SITL file is a
|
||||
private host envelope `[generation, raw-profile-blob]`; it is not an upload
|
||||
blob and must not be sent to `IMPORT_*` directly.
|
||||
Saving writes a same-directory temporary file, synchronizes its contents, and
|
||||
atomically renames it over the configured file. The file contains no generation
|
||||
or journal envelope; host filesystem replacement is distinct from the F722
|
||||
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
|
||||
`PARAM_*` semantics. A client will:
|
||||
|
||||
1. send `KAPTAN_CONFIG_INFO_REQUEST` and require the exact protocol, profile
|
||||
format, and schema ID in the correlated `KAPTAN_CONFIG_INFO` reply;
|
||||
2. request descriptors and values as needed;
|
||||
1. send `KAPTAN_CONFIG_INFO_REQUEST`, require the exact breaking protocol
|
||||
version `2.0`,
|
||||
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`;
|
||||
4. either issue typed setters or begin a raw-CBOR upload with the advertised
|
||||
schema ID, then send aligned idempotent chunks in any order;
|
||||
4. issue typed setters for changed fields;
|
||||
5. validate and commit; and
|
||||
6. treat `COMMITTED_RESTART_REQUIRED` as persistence only, never live
|
||||
activation.
|
||||
|
||||
An accepted import begin returns a server-issued transfer ID. Every chunk and
|
||||
finish request echoes it, preventing delayed data from an earlier transfer
|
||||
from entering the current one. The service validates CRC-32C and the entire
|
||||
candidate before it replaces the RAM transaction.
|
||||
The directly wired local UART is the initial operational configuration
|
||||
transport. The board composition admits CRC-valid unsigned configuration
|
||||
commands on that link; CRC supplies integrity, not authentication. This does
|
||||
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:
|
||||
F722 needs authenticated ingress, source binding and replay protection,
|
||||
journalled target storage, a disarmed/inhibited activation permit, and atomic
|
||||
consumer rebuild/reset before it may accept any configuration command.
|
||||
The first accepted `BEGIN` binds the one protocol instance to that MAVLink
|
||||
source. The binding and its sole most-recent result remain for a ten-second
|
||||
lease, including after `COMMIT` or `ABORT`, so retrying a lost terminal reply
|
||||
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.
|
||||
@@ -7,7 +7,7 @@ cd firmware
|
||||
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 -p platform-stm32f7 --all-targets --offline -- -D warnings
|
||||
cargo fmt --check
|
||||
cargo fmt --all --check
|
||||
git diff --check
|
||||
```
|
||||
|
||||
@@ -15,8 +15,11 @@ git diff --check
|
||||
|
||||
```sh
|
||||
cd firmware
|
||||
cargo check -p kaptan-geprc-f722-v2 --release --target thumbv7em-none-eabihf --offline
|
||||
cargo check -p kaptan-kakute-f7-mini-v3 --release --target thumbv7em-none-eabihf --offline
|
||||
cargo clippy -p kaptan-geprc-f722-v2 -p kaptan-kakute-f7-mini-v3 \
|
||||
--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
|
||||
|
||||
+7
-6
@@ -28,12 +28,13 @@ for safety state, actuator inhibit, or typed configuration results.
|
||||
rule, and protocol error code.
|
||||
- Runtime driver and link faults reach the F722 MAVLink worker as a
|
||||
`KAPTAN_ERROR` path, subject to bounded transport admission. The error
|
||||
payload is `{ flags, path_length, additional_information_length, path[96],
|
||||
additional_information[64] }`; each length identifies the valid UTF-8
|
||||
prefix and the optional information field may be empty. A `KaptanError`
|
||||
derive supplies the type/variant path and normally leaves additional
|
||||
information empty. `log::error!` uses the Rust log target as the path and
|
||||
the formatted message as additional information.
|
||||
payload is `{ level, flags, path_length, additional_information_length,
|
||||
path[96], additional_information[64] }`; `level` preserves the originating
|
||||
MAVLink-compatible severity from Emergency through Error, each length
|
||||
identifies the valid UTF-8 prefix, and the optional information field may be
|
||||
empty. A `KaptanError` derive supplies the type/variant path and normally
|
||||
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`
|
||||
whose path is the high-level `ProtocolError` identity. It is intentionally
|
||||
not correlated and carries no field/rule detail; the matching
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
|
||||
Use the firmware toolchain, Rust 1.90. The firmware workspace declares the
|
||||
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:
|
||||
|
||||
@@ -20,10 +26,11 @@ target-specific commands in [Development and verification](development.md).
|
||||
|
||||
| Path | Responsibility |
|
||||
| --- | --- |
|
||||
| `firmware/boards/` | Immutable board declarations and linker layouts. |
|
||||
| `firmware/platforms/stm32f7/` | Reviewed F722 RTIC platform and peripheral ownership. |
|
||||
| `firmware/boards/` | Board-owned user schemas, factory values, immutable hardware declarations, and image composition roots. |
|
||||
| `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/tools/sitl/` | Host-only closed-loop Gazebo simulation. |
|
||||
| `firmware/tools/configurator/` | Board-agnostic loopback web UI and serial bridge. |
|
||||
| `docs/` | This Markdown documentation site. |
|
||||
|
||||
Do not add board-local READMEs. Add a page here instead, then link it from
|
||||
|
||||
+6
-6
@@ -15,8 +15,8 @@ Markdown.
|
||||
- Firmware source and its Rust workspace begin in `firmware/`.
|
||||
- Board work belongs under [Boards](boards/index.md).
|
||||
- The currently supported closed-loop simulation is [Host SITL](sitl.md).
|
||||
- [Configuration](configuration.md) distinguishes the current SITL profile
|
||||
from immutable F722 board policy.
|
||||
- [Configuration](configuration.md) explains target-described user settings
|
||||
and immutable F722 hardware policy.
|
||||
- [Logs](logs.md) and [Errors](errors.md) describe the custom MAVLink
|
||||
observability surface and its current safety scope.
|
||||
- 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
|
||||
boundary they depend on.
|
||||
|
||||
The current configuration contract is intentionally deployment-specific. A
|
||||
SITL Quad-X profile is a bounded restart-only CBOR snapshot; F722 hardware
|
||||
selection remains immutable board policy. Neither is permission for an
|
||||
operator to substitute runtime values or bypass an immutable safety decision.
|
||||
The current configuration contract is target-described. A SITL Quad-X profile
|
||||
and each F722 board expose only values consumed by that compiled target;
|
||||
physical F722 hardware selection remains immutable board policy. No writable
|
||||
snapshot can bypass an immutable safety decision.
|
||||
+44
-17
@@ -9,9 +9,13 @@ log::warn!("range aid stale");
|
||||
log::error!("sensor transfer failed"); // emitted as KAPTAN_ERROR
|
||||
```
|
||||
|
||||
`kaptan-log` formats once into a fixed bounded buffer, queues locally, and
|
||||
never sends MAVLink, allocates, blocks, changes flight state, or touches DMA.
|
||||
The sole MAVLink worker drains admitted records. F722 deliberately does not
|
||||
`kaptan-log` formats each event once into a fixed bounded buffer and never
|
||||
sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The
|
||||
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
|
||||
contexts; those paths use static fault mailboxes that the worker turns into
|
||||
messages later.
|
||||
@@ -25,7 +29,7 @@ orderly-shutdown observations:
|
||||
```text
|
||||
KAPTAN_LOG { level, flags, message_length, message[160] }
|
||||
KAPTAN_ERROR {
|
||||
flags, path_length, additional_information_length,
|
||||
level, flags, path_length, additional_information_length,
|
||||
path[96], additional_information[64]
|
||||
}
|
||||
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
|
||||
MAVLink severity in `level`; `TRACE` is encoded as `DEBUG` plus the `TRACE`
|
||||
flag.
|
||||
`KAPTAN_ERROR` is error-only and accepts only `TRUNCATED` and `COALESCED`; a
|
||||
`TRACE` bit is never emitted there. Unknown future flag bits must be ignored.
|
||||
`KAPTAN_ERROR.level` preserves the originating MAVLink-compatible severity from
|
||||
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
|
||||
its Rust module/type/variant changes that identity. Error details requiring
|
||||
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
|
||||
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
|
||||
|
||||
The SITL profile’s restart-only `observability.maximum_log_level` accepts
|
||||
MAVLink severities Error (3) through Debug (7). For example, selecting Warning
|
||||
permits warning records while suppressing info and debug records. Error-level
|
||||
records always use `KAPTAN_ERROR` and remain non-filterable. F722 uses its
|
||||
immutable board log threshold instead, because it has no active runtime
|
||||
profile.
|
||||
The restart-only `mavlink.logging.enabled` field controls the MAVLink
|
||||
diagnostic sink independently from future sinks such as a blackbox.
|
||||
`mavlink.logging.maximum_severity` accepts the complete MAVLink severity range,
|
||||
Emergency (0) through Debug (7). For example, selecting Warning permits warning
|
||||
and more severe events while suppressing notice, info, and debug. Disabling the
|
||||
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
|
||||
them; they are not a supported filtering mechanism. The build policy keeps
|
||||
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_ERROR` companion without replacing their authoritative result. `kaptan-sitl
|
||||
serve` does not yet attach a config/diagnostic MAVLink link, and F722 emits only
|
||||
outbound telemetry/diagnostic frames while rejecting all inbound authority.
|
||||
`KAPTAN_ERROR` companion without replacing their authoritative result.
|
||||
`kaptan-sitl serve` does not yet attach a config/diagnostic MAVLink link. F722
|
||||
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
@@ -1,30 +1,59 @@
|
||||
# MAVLink and telemetry
|
||||
|
||||
Kaptan emits telemetry using MAVLink 2 framing. The production receiver does
|
||||
not promote inbound MAVLink frames to authority records:
|
||||
Kaptan emits telemetry using MAVLink 2 framing. Inbound processing is narrowly
|
||||
scoped:
|
||||
|
||||
- MAVLink 1 is discarded.
|
||||
- CRC-invalid MAVLink 2 frames are discarded.
|
||||
- Signed frames are discarded because no signature verifier or persistent
|
||||
replay state exists.
|
||||
- Unsigned MAVLink 2 frames are also discarded; a V2 CRC detects corruption,
|
||||
not authentication.
|
||||
- CRC-valid unsigned MAVLink 2 frames are accepted only for the exact-target
|
||||
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
|
||||
signing, configured source/target binding, persistent anti-replay state, and a
|
||||
provisioning/key-rotation policy as one reviewed feature.
|
||||
`TODO(signing)`: any future shared or remote inbound authority requires verified
|
||||
MAVLink 2 signing, configured source/target binding, persistent anti-replay
|
||||
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
|
||||
replace pending best-effort traffic, but never the DMA-owned active buffer.
|
||||
Completion retries preserve ordering and retain a transiently busy frame for a
|
||||
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
|
||||
`kaptan/config.xml`, `kaptan/log.xml`, `kaptan/error.xml`, and
|
||||
`kaptan/shutdown.xml`.
|
||||
`KAPTAN_LOG` is an outbound human-readable four-field record. `KAPTAN_ERROR`
|
||||
is its separate bounded error channel, while `KAPTAN_SHUTDOWN` represents only
|
||||
a completed orderly output-inhibited shutdown. Configuration messages are GCS
|
||||
groundwork only: the current F722 receiver rejects every inbound frame before
|
||||
configuration dispatch. See [Configuration](configuration.md), [Logs](logs.md),
|
||||
and [Errors](errors.md) for the exact contracts.
|
||||
is its separate bounded error channel and preserves the originating error
|
||||
severity, while `KAPTAN_SHUTDOWN` represents only
|
||||
a completed orderly output-inhibited shutdown. Configuration messages back the
|
||||
current target-described web configurator and the future signed GCS. See
|
||||
[Configuration](configuration.md), [Logs](logs.md), and [Errors](errors.md) for
|
||||
the exact contracts.
|
||||
+15
-11
@@ -4,15 +4,15 @@ This page collects stable limits and points to the detailed contracts.
|
||||
|
||||
| Surface | Current contract |
|
||||
| --- | --- |
|
||||
| Flight profile | One 4 KiB-or-smaller raw CBOR blob, `profile_format = 1`, schema ID `KAPTANPROFILE-01`. |
|
||||
| SITL file | Private `[generation, raw-profile-blob]` envelope; not a MAVLink upload blob. |
|
||||
| Config transaction | One owner-bound RAM transaction; typed writes or 192-byte idempotent CBOR chunks; commit is restart-required. |
|
||||
| Config discovery | Correlated `KAPTAN_CONFIG_INFO_REQUEST` / `KAPTAN_CONFIG_INFO`, then descriptor/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. |
|
||||
| F722 configuration | Immutable compiled board policy only; inbound MAVLink configuration remains disabled. |
|
||||
| SITL file | One raw bounded CBOR configuration snapshot, replaced through a same-directory temporary file and atomic rename. |
|
||||
| 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 with typed scalar writes; commit is restart-required. |
|
||||
| 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 `{ level, path[96], additional_information[64] }` error; and `KAPTAN_SHUTDOWN` (51022) for completed orderly output-inhibited shutdowns. |
|
||||
| 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
|
||||
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.
|
||||
|
||||
## Verification
|
||||
@@ -23,9 +23,13 @@ Before review, run:
|
||||
cd firmware
|
||||
cargo fmt --all --check
|
||||
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
|
||||
host workspace test suite continues to assert that the telemetry F722 image
|
||||
has no inbound authority or actuator path.
|
||||
The target-specific lint verifies the local configuration receiver and journal
|
||||
path. The host suite separately asserts that configuration ingress cannot reach
|
||||
an actuator path.
|
||||
@@ -1,14 +1,23 @@
|
||||
# Safety boundary
|
||||
|
||||
Every checked-in F722 image inhibits PB0, PB1, PB4, and PB5 before normal
|
||||
board initialization. The interlock configures each pin as a low, push-pull
|
||||
GPIO output; it runs before clocks, board routing, UART setup, or RTIC tasks.
|
||||
Every checked-in F722 image drives PB0, PB1, PB4, and PB5 low before normal
|
||||
board initialization. This startup output inhibition configures each pin as a
|
||||
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:
|
||||
|
||||
- no DShot or PWM peripheral implementation is linked;
|
||||
- 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.
|
||||
|
||||
The protocol reference crate remains in the workspace only as a framing and
|
||||
|
||||
+4
-3
@@ -46,10 +46,11 @@ kaptan-sitl serve --config kaptan-sitl.cbor
|
||||
```
|
||||
|
||||
The file selects the restart-only profile used to build the estimator,
|
||||
controller, allocator envelope, safety supervisor, and optional log filter at
|
||||
process start. It is not the raw GCS upload blob. `kaptan-sitl serve` retains
|
||||
controller, allocator envelope, safety supervisor, and MAVLink log-sink policy at
|
||||
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
|
||||
endpoint; see [Configuration](configuration.md) for the exact upload groundwork
|
||||
endpoint; see [Configuration](configuration.md) for the exact transaction contract
|
||||
and safety boundary.
|
||||
|
||||
## Limits
|
||||
|
||||
Reference in new issue
Block a user