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
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -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
@@ -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.
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in new issue
Block a user