docs: document the kaptan-native protocol
This commit is contained in:
1 parent
5f91465e66
commit
4bc98adbc6
10 files changed
+314
-307
No files matched your search
+48
-53
@@ -27,73 +27,68 @@ The data channel owns rate selection, mailbox consumption, message encoding,
|
||||
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:
|
||||
Configuration and runtime observability are separate planes:
|
||||
|
||||
```text
|
||||
Kaptan GCS custom MAVLink V2 messages
|
||||
│ (future: verified signing, source binding, replay state)
|
||||
FILE_CONTROL / FILE_DATA
|
||||
│
|
||||
▼
|
||||
kaptan-config-mavlink ──► state-only ConfigProtocol
|
||||
│ borrows
|
||||
kaptan-flight-runtime
|
||||
├── one ConfigManager ──► kaptan-config ──► flight schema/store
|
||||
└── one bounded MAVLink log-sink queue
|
||||
kaptan-file-mavlink ──► virtual FileProvider
|
||||
│
|
||||
kaptan-diagnostics-mavlink payload adapter
|
||||
KCFG importer/exporter
|
||||
│
|
||||
platform-owned sole encoder / DMA TX link
|
||||
ConfigManager ──► private store
|
||||
|
||||
kaptan-log / kaptan-err-reportable
|
||||
│
|
||||
▼
|
||||
kaptan-diagnostics-mavlink ──► platform-owned encoder / DMA TX
|
||||
```
|
||||
|
||||
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, exact-index
|
||||
descriptor and enum-option requests, and structured results are custom-dialect
|
||||
records. Runtime logs use one bounded text message with a conventional level
|
||||
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.
|
||||
The file dialect is intentionally Kaptan-native rather than standard MAVLink
|
||||
FTP, `PARAM_*`, or a QGC adapter. Its two messages know only bounded paths,
|
||||
bytes, positions, checksums, transfer ownership, and retries. The configuration
|
||||
provider maps `/config/user.kcfg` to a canonical self-describing artifact.
|
||||
KCFG carries generated metadata and a complete committed value set; the target
|
||||
streams it without retaining a whole-file buffer. Saving imports and validates
|
||||
one complete replacement candidate. The core distinguishes only immutable
|
||||
boot-active values from the latest committed values. A save cannot mutate
|
||||
controller or estimator state in flight.
|
||||
|
||||
Target-owned stores may serialize one bounded complete CBOR snapshot. SITL
|
||||
supplies the host file adapter and atomically replaces that snapshot through a
|
||||
same-directory temporary file. The serialization is not configuration state
|
||||
and is never exposed by the MAVLink protocol.
|
||||
Target-owned stores use private persistence formats. SITL atomically replaces a
|
||||
bounded CBOR snapshot. F722 alternates compact `KCSP` snapshots between two
|
||||
erase sectors, retaining only the old and replacement records across the commit
|
||||
boundary. Neither format is exposed as the public KCFG file.
|
||||
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.
|
||||
never a scalar field or persistence member. F722 recovers operational settings
|
||||
before constructing consumers. Its directly wired local UART accepts only
|
||||
exact-target, CRC-valid Kaptan file requests while physical outputs remain
|
||||
inhibited. CRC is integrity-only; a shared or remote GCS still needs production
|
||||
authentication, source binding, and persistent anti-replay state. Disarmed
|
||||
activation and flight-consumer reconstruction remain separate reviewed work.
|
||||
|
||||
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`, and
|
||||
`kaptan/error.xml`.
|
||||
The build watches every fragment and generates one `message::kaptan` module;
|
||||
fragments are never separately generated Rust modules. `kaptan-log` itself has
|
||||
The MAVLink dialect root directly includes one-message XML leaves under
|
||||
`publish/` and `transfer/`. The `exchange/` contract remains empty until a
|
||||
current consumer justifies a message. There are no category index XML files or
|
||||
separate enum catalogs. The build watches the definitions tree and generates
|
||||
one `generated::kaptan` module; leaves are never separately generated Rust
|
||||
modules. `kaptan-log` itself has
|
||||
no MAVLink, platform, time, allocation, or filesystem dependency; its sole
|
||||
configuration coupling is compile-time enum metadata for `LevelFilter`.
|
||||
`kaptan-err-reportable` independently owns explicitly assigned reportable-error
|
||||
identity and a bounded nonblocking ingress; it has
|
||||
no logging, MAVLink, platform, filesystem, or clock dependency. Event creation
|
||||
is independent from sink filtering, allowing a future blackbox and MAVLink to
|
||||
select different policies. The platform drains reportable errors before its bounded
|
||||
critical and best-effort log queues and removes a pending record only after TX
|
||||
admission. `KAPTAN_LOG` carries one conventional level plus one bounded text
|
||||
field; `KAPTAN_ERROR` carries an explicitly assigned 16-bit ID and the bounded
|
||||
`file:line` of the reporting point. Its
|
||||
message kind already identifies a reportable firmware error. Heartbeat and safety
|
||||
telemetry remain separate from diagnostics.
|
||||
identity and a bounded nonblocking ingress; it has no logging, MAVLink,
|
||||
platform, filesystem, or clock dependency. Event creation is independent from
|
||||
sink filtering, allowing a future blackbox and MAVLink to select different
|
||||
policies. The platform drains reportable errors before its bounded critical and
|
||||
best-effort log queues and removes a pending record only after TX admission.
|
||||
`LOG` carries one conventional level plus one bounded text field; `ERROR`
|
||||
carries an explicitly assigned 16-bit ID and the bounded `file:line` of the
|
||||
reporting point. Its message kind already identifies a reportable firmware
|
||||
error. Kaptan-native heartbeat and sensor publications remain separate from
|
||||
diagnostics.
|
||||
|
||||
See [Configuration](configuration.md) for the deployment matrix and GCS transaction
|
||||
contract, [Logs](logs.md) for the receiver contract, and [Errors](errors.md)
|
||||
See [Configuration](configuration.md) for KCFG and the file-transfer contract,
|
||||
[Logs](logs.md) for the receiver contract, and [Errors](errors.md)
|
||||
for derived-error and failure-reporting scope.
|
||||
|
||||
## Ownership rules
|
||||
|
||||
@@ -5,7 +5,7 @@ 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 board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU and
|
||||
Its board-local `UserConfig` factory selects endpoint `1/1`, IMU and
|
||||
heartbeat publication rates, and an enabled MAVLink diagnostic sink with an
|
||||
`Info` level filter. The web configurator may replace those
|
||||
target-advertised values in the journal. Range
|
||||
@@ -59,7 +59,7 @@ Then run:
|
||||
|
||||
```sh
|
||||
cargo run --locked -p kaptan-configurator -- \
|
||||
--serial /dev/serial/by-id/<adapter> --baud 115200
|
||||
--source-system 255 --serial /dev/serial/by-id/<adapter> --baud 115200
|
||||
```
|
||||
|
||||
Open `http://127.0.0.1:4861`, Save the discovered fields, and manually
|
||||
|
||||
@@ -5,7 +5,7 @@ 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 board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU, range,
|
||||
Its board-local `UserConfig` factory selects endpoint `1/1`, IMU, range,
|
||||
optical-flow and heartbeat publication rates, and an enabled MAVLink diagnostic
|
||||
sink with an `Info` level filter. The web configurator may replace those
|
||||
target-advertised values in the journal. Its `ImmutableConfig` keeps the
|
||||
@@ -64,7 +64,7 @@ Launch the target-described web UI:
|
||||
|
||||
```sh
|
||||
cargo run --locked -p kaptan-configurator -- \
|
||||
--serial /dev/serial/by-id/<adapter> --baud 115200
|
||||
--source-system 255 --serial /dev/serial/by-id/<adapter> --baud 115200
|
||||
```
|
||||
|
||||
Open `http://127.0.0.1:4861`, edit the discovered fields, press Save, and
|
||||
|
||||
+141
-177
@@ -1,18 +1,18 @@
|
||||
# Configuration
|
||||
|
||||
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.
|
||||
Kaptan has one generic configuration model in `kaptan-config`. Target schemas
|
||||
declare typed fields and validation once; derive code generates the stable
|
||||
field registry and schema fingerprint. Boards supply the sole erased-flash
|
||||
factory values. The browser contains no board, driver, sensor, schema, or
|
||||
parameter catalog.
|
||||
|
||||
## Current deployment matrix
|
||||
|
||||
| Deployment | Configuration consumed today | Remote writes |
|
||||
| --- | --- | --- |
|
||||
| `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. |
|
||||
| `kaptan-sitl serve --config FILE.cbor` | One validated Quad-X configuration at process construction. | No live file endpoint is attached yet. |
|
||||
| `kaptan-sitl serve` | The validated factory Quad-X configuration. | No persistent store. |
|
||||
| STM32F722 image | Board factory settings, or the newest valid flash-journal snapshot. | `/config/user.kcfg` on the directly wired local UART while motor pins remain inhibited. |
|
||||
|
||||
## Web configurator
|
||||
|
||||
@@ -21,208 +21,172 @@ USB-UART adapter, then run from `firmware`:
|
||||
|
||||
```sh
|
||||
cargo run --locked -p kaptan-configurator -- \
|
||||
--serial /dev/serial/by-id/<adapter> --baud 115200
|
||||
--source-system 255 --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.
|
||||
`--source-system` is the configurator's exact MAVLink source identity. Every
|
||||
simultaneously connected GCS must use a different nonzero system ID so transfer
|
||||
ownership and retries cannot alias another client.
|
||||
|
||||
Open `http://127.0.0.1:4861`. On discovery, the configurator downloads the
|
||||
complete `/config/user.kcfg` artifact, validates it, and renders the metadata
|
||||
and values contained in that file. Save produces one complete edited KCFG
|
||||
artifact and uploads it. The target validates the complete candidate before
|
||||
atomically persisting it. The boot-active runtime does not change; manually
|
||||
power-cycle the controller after a successful save when the UI reports that a
|
||||
restart is required.
|
||||
|
||||
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.
|
||||
controller is busy; the host gives the final close a separate five-second
|
||||
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 artifact carries generated field IDs, native scalar kinds, display keys,
|
||||
units, bounds, enum choices, factory values, committed values, schema identity,
|
||||
and the derived restart-required state. A new board or field therefore needs no
|
||||
configurator release. `u8`, `u16`, and enum-backed values retain their native
|
||||
width rather than being widened at the configuration boundary.
|
||||
|
||||
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 the `KAPTAN_ERROR` ID and reporting
|
||||
`file:line`. The
|
||||
configurator keeps only one latest value per bounded aggregate,
|
||||
rather than packet history, and clears it for every serial-link session.
|
||||
The Incoming MAVLink table groups live, CRC-valid Kaptan packets by source and
|
||||
message ID and shows receive frequency and total count. Selecting a message
|
||||
watches its latest decoded value. The separate Runtime logs view retains
|
||||
individual `LOG` and `ERROR` events in receive order, with local receive time,
|
||||
level, and readable text.
|
||||
|
||||
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 level, 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. A visible `TRUNCATED` badge marks bounded `KAPTAN_LOG`
|
||||
text. This
|
||||
event history is independent of the packet table's
|
||||
single latest-value projection and resets when the serial link changes.
|
||||
## Board ownership
|
||||
|
||||
Each F722 board owns the exact settings consumed by its compiled image. Both
|
||||
current boards advertise:
|
||||
Each F722 board declares one `UserConfig` root for the settings consumed by its
|
||||
compiled driver graph. The explicit `FACTORY_USER_CONFIG` literal is the sole
|
||||
erased-flash value. There is no `Default` implementation and no platform-wide
|
||||
union of board schemas.
|
||||
|
||||
- MAVLink system and component identity;
|
||||
- raw-IMU and heartbeat publication rates; and
|
||||
- the MAVLink diagnostic sink's Off/Error/Warn/Info/Debug/Trace level filter.
|
||||
Both current boards expose MAVLink identity, IMU and heartbeat publication
|
||||
rates, and the MAVLink log level filter. Kakute also exposes range and
|
||||
optical-flow rates because its immutable hardware manifest contains an MTF01.
|
||||
Those fields are absent from GEPRC rather than present-but-disabled.
|
||||
|
||||
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 adjacent `IMMUTABLE_CONFIG` literal remains the sole source of facts that
|
||||
cannot safely be edited as scalar configuration:
|
||||
|
||||
The UART baud is the immutable bootstrap link for this first configuration
|
||||
transport. Pass it explicitly to the host with `--baud`.
|
||||
- output-inhibit and status-LED routes;
|
||||
- IMU model, bus, interrupt route, mount, and driver setup;
|
||||
- MAVLink and optional vertical-sensor routes and bootstrap baud rates;
|
||||
- service-timer frequency; and
|
||||
- compiled image role.
|
||||
|
||||
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 stable semantic field IDs through the generic
|
||||
`Config::field_value` boundary. It does not know a board section, Rust field,
|
||||
or aggregate shape. Whole-candidate validation checks both generated local
|
||||
rules and relationships such as publication budget and immutable hardware
|
||||
capabilities.
|
||||
|
||||
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.
|
||||
## KCFG artifact
|
||||
|
||||
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.
|
||||
KCFG is the public, canonical import/export representation. It is independent
|
||||
of MAVLink and of the private storage format. A file contains:
|
||||
|
||||
The current SITL configuration has only settings consumed by its estimator,
|
||||
controller, safety supervisor, allocator envelope, or MAVLink diagnostic sink:
|
||||
- `KCFG` magic and one format version;
|
||||
- generated 16-byte schema identity and exact field count;
|
||||
- one canonical self-describing record for every field; and
|
||||
- a big-endian CRC-32C trailer covering the preceding artifact bytes.
|
||||
|
||||
- prearm dwell;
|
||||
- IMU, local-aiding, and command freshness/timing;
|
||||
- position/velocity aiding variance;
|
||||
- outer-loop gains and acceleration limits;
|
||||
- mass, collective-thrust, and tilt limits;
|
||||
- rate PID gains and limits;
|
||||
- actuator minimum, maximum, and slew limits; and
|
||||
- the restart-only MAVLink diagnostic-sink level filter.
|
||||
The trailer uses network byte order deliberately. The generic file dialect
|
||||
also calculates CRC-32C over every complete file byte; network-order storage
|
||||
keeps that independent transfer checksum content-specific instead of producing
|
||||
the fixed residue obtained by appending a reflected CRC in little-endian order.
|
||||
|
||||
The fixed Quad-X mixer is intentionally not configurable. It is reviewed
|
||||
capability data, not a user-editable array.
|
||||
An imported file must match the target-generated schema, descriptor metadata,
|
||||
factory values, field order, native scalar kinds, and exact length. Unknown,
|
||||
duplicate, missing, malformed, noncanonical, out-of-range, and relationally
|
||||
invalid values are rejected. The target stages only the typed candidate and a
|
||||
small parser state; it never buffers the complete public file. Exports are also
|
||||
generated by range directly from compiled metadata and current committed
|
||||
values. One small export plan containing the exact length and checksums is
|
||||
prepared when a read opens and reused for every requested range.
|
||||
|
||||
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.
|
||||
Schema identity is required because a complete file can otherwise be validly
|
||||
encoded while belonging to another firmware schema. It is generated from the
|
||||
schema and is not a hand-maintained board ID.
|
||||
|
||||
## Immutable hardware topology
|
||||
The artifact header's restart bit describes the committed values in an export.
|
||||
It is not an instruction accepted from an upload: after persistence the target
|
||||
derives restart state by comparing committed values with immutable boot-active
|
||||
values.
|
||||
|
||||
The checked-in F722 `ImmutableConfig` literals retain the facts that cannot
|
||||
safely be changed by a scalar transaction:
|
||||
## Generic file dialect
|
||||
|
||||
- IMU model and its fixed body mount (`BodyAligned` or `Yaw180`);
|
||||
- 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.
|
||||
Kaptan uses two custom messages rather than standard MAVLink FTP or a family of
|
||||
configuration-specific requests:
|
||||
|
||||
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.
|
||||
```text
|
||||
FILE_CONTROL
|
||||
FILE_DATA
|
||||
```
|
||||
|
||||
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.
|
||||
`FILE_CONTROL` opens, closes, aborts, and acknowledges a transfer. It
|
||||
carries a client-selected nonzero `u16` transfer ID, exact target, position,
|
||||
complete file size, CRC-32C, operation/status, and at most 64 bytes of path or
|
||||
result detail. A source does not reuse an ID during the ten-second replay lease.
|
||||
A new ID from the same source may supersede an open only before the first byte
|
||||
has advanced; a progressed abandoned transfer remains pinned until lease expiry.
|
||||
`FILE_DATA` uses the full MAVLink payload budget for a
|
||||
246-byte chunk. The logical final-chunk length follows from the opened file
|
||||
size, so no redundant length field is sent with every data packet. An upload
|
||||
request carries status `UNSPECIFIED`; a read-data response carries status `OK`.
|
||||
All failures remain typed `FILE_CONTROL` responses.
|
||||
|
||||
## Local persistence
|
||||
The service owns one bounded stop-and-wait transfer. Chunks are sequential;
|
||||
immediate retries are replay-safe, conflicting retries are rejected, and stale
|
||||
transfer IDs cannot mutate a later transfer. A receive fault or bounded lease
|
||||
expiry aborts staged provider state. The generic layer knows only paths, bytes,
|
||||
positions, checksums, ownership, and retry state. It does not parse KCFG or
|
||||
contain configuration policy.
|
||||
|
||||
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.
|
||||
The current provider exposes exactly `/config/user.kcfg`. A successful write
|
||||
close has generic status `OK` and content beginning with the authoritative
|
||||
seven-byte KCFG result prefix: restart flag, primary field, related field, and
|
||||
validation-rule code. Its exact layout is `flags:u8 | primary_field:u16 LE |
|
||||
related_field:u16 LE | validation_rule:u16 LE`; flag bit 0, when set, means a
|
||||
restart is required, and every other flag bit is reserved zero. The field
|
||||
sentinel is `0xffff`; rule zero means no rule.
|
||||
KCFG `CONTENT_REJECTED` responses use the same prefix and may append bounded
|
||||
UTF-8 detail. The configurator rejects a successful close with a missing,
|
||||
malformed, or failure-bearing prefix. The file layer passes these bytes through
|
||||
without interpreting them.
|
||||
|
||||
### SITL CBOR file
|
||||
The directly wired local UART is the initial transport. CRC validates framing
|
||||
integrity, not peer authenticity. Disconnect other transmitters from the board
|
||||
RX line. A shared or remote GCS still requires signing, source/key binding,
|
||||
persistent anti-replay state, and provisioning before this inbound service can
|
||||
be exposed safely.
|
||||
|
||||
SITL stores one raw, bounded CBOR configuration snapshot directly:
|
||||
## Private persistence
|
||||
|
||||
- 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.
|
||||
SITL and F722 use target-appropriate private persistence. Neither private
|
||||
format is the public KCFG artifact.
|
||||
|
||||
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.
|
||||
### SITL CBOR
|
||||
|
||||
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.
|
||||
SITL stores one bounded CBOR snapshot keyed by stable `FieldId`. Saving writes
|
||||
a same-directory temporary file, synchronizes it, and atomically renames it
|
||||
over the configured file. The exact map rejects unknown, duplicate, and missing
|
||||
fields, wrong schema or format, trailing input, invalid scalar encodings, and
|
||||
complete-model validation failures.
|
||||
|
||||
### 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.
|
||||
F722 stores a compact private `KCSP` scalar snapshot inside a two-slot journal.
|
||||
Each entry stores its stable field ID, scalar kind, and value at that kind's
|
||||
native width; an `u8` is one byte rather than a widened integer slot. Each
|
||||
journal record includes payload length, CRC-32C, commit marker, and a private
|
||||
monotonic sequence. Saving erases the inactive slot, programs and verifies the
|
||||
complete replacement, and writes the commit marker last. The previous valid
|
||||
slot remains recoverable across power loss until that point.
|
||||
|
||||
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.
|
||||
Only two complete records can exist: the old committed value and its
|
||||
replacement. Saves do not append history. The sequence is storage metadata used
|
||||
only to select the newer valid slot if both slots survive; it is never exported
|
||||
through KCFG or shown in the UI.
|
||||
|
||||
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`, 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. issue typed setters for changed fields;
|
||||
5. validate and commit; and
|
||||
6. treat `COMMITTED_RESTART_REQUIRED` as persistence only, never live
|
||||
activation.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
There is no migration path because no configuration version has shipped.
|
||||
+11
-10
@@ -53,30 +53,31 @@ backpressure, retry, and untrusted-input results remain unannotated. In
|
||||
particular, transient SPI/I²C `Busy` and unavailable range measurements stay
|
||||
inside their service retry/idle paths. In contrast, every logging
|
||||
macro—including `kaptan_log::error!`—produces only
|
||||
`KAPTAN_LOG`. Error reporting is not a replacement for safety state,
|
||||
`LOG`. Error reporting is not a replacement for safety state,
|
||||
actuator inhibit, or typed configuration results.
|
||||
|
||||
`kaptan-err-reportable` owns reportable-error identity and its independent
|
||||
one-slot ingress. A pending record contains only the compact ID and a static
|
||||
reference to the reporting point's `file:line`. The MAVLink adapter copies that
|
||||
location into its fixed field when constructing `KAPTAN_ERROR`. Producers never
|
||||
location into its fixed field when constructing `ERROR`. Producers never
|
||||
encode or transmit MAVLink themselves. Admission is bounded and lossy if a
|
||||
different reportable error is already pending.
|
||||
|
||||
## What the receiver sees
|
||||
|
||||
- Configuration writes receive authoritative structured failures through
|
||||
`KAPTAN_CONFIG_RESULT`: operation, lifecycle state, field IDs, validation
|
||||
rule, and protocol error code. A reportable persistence failure also emits
|
||||
the storage-only `CommitTransactionError::Store` ID once as
|
||||
`KAPTAN_ERROR`; replaying the cached command result does not repeat the error
|
||||
or the flash operation.
|
||||
- A rejected KCFG upload receives an authoritative `FILE_CONTROL`
|
||||
status and bounded readable detail. Invalid user content is not a firmware
|
||||
error. A durable-storage failure additionally emits one stable
|
||||
`PersistConfigurationError` ID that distinguishes journal geometry, model,
|
||||
sequence, flash-controller, bounds, unlock, and verification
|
||||
failures. Replaying the cached close result does not repeat the report or
|
||||
flash operation.
|
||||
- Reported `ReportableError` values reach the F722 MAVLink worker as a
|
||||
`KAPTAN_ERROR`, subject to bounded transport admission. The payload is
|
||||
`ERROR`, subject to bounded transport admission. The payload is
|
||||
`{ error_id, raised_at[96] }`. `raised_at` is a zero-padded UTF-8
|
||||
`file:line` prefix for the reporting point.
|
||||
The message kind itself identifies an error; no level is duplicated in the
|
||||
payload. Dynamic human-readable context belongs in `KAPTAN_LOG`, while
|
||||
payload. Dynamic human-readable context belongs in `LOG`, while
|
||||
structured protocol failures remain in their owning response message.
|
||||
- Control, navigation, safety, and simulator error types are derive-ready but
|
||||
their live owners are not yet attached to a MAVLink worker.
|
||||
|
||||
+24
-22
@@ -10,10 +10,10 @@ kaptan_log::error!("sensor transfer failed");
|
||||
kaptan_log::trace!("prediction step complete");
|
||||
```
|
||||
|
||||
All five macros emit `KAPTAN_LOG`; their level never selects a different wire
|
||||
All five macros emit `LOG`; their level never selects a different wire
|
||||
message. When a reportable firmware error escapes a reviewed
|
||||
`#[kaptan_err_reportable::propagate]` function, it makes one bounded admission attempt
|
||||
to the separate `KAPTAN_ERROR` ingress.
|
||||
to the separate `ERROR` ingress.
|
||||
|
||||
`kaptan-log` formats each event once into a fixed bounded buffer and never
|
||||
sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The
|
||||
@@ -29,31 +29,33 @@ Panic and hard-fault paths still do not attempt live telemetry.
|
||||
|
||||
## Receiver contract
|
||||
|
||||
`definitions/kaptan/log.xml` and `definitions/kaptan/error.xml` separate
|
||||
ordinary logs and reportable errors:
|
||||
`definitions/publish/log.xml` and `definitions/publish/error.xml` define the
|
||||
separate ordinary-log and reportable-error publications:
|
||||
|
||||
```text
|
||||
KAPTAN_LOG { level, flags, message_length, message[160] }
|
||||
KAPTAN_ERROR {
|
||||
LOG { level, flags, message_length, message[160] }
|
||||
ERROR {
|
||||
error_id, raised_at[96]
|
||||
}
|
||||
```
|
||||
|
||||
A GCS decoder generated from the same `kaptan.xml` revision must validate
|
||||
`message_length <= 160` for `KAPTAN_LOG`. `KAPTAN_ERROR.raised_at` is a
|
||||
`message_length <= 160` for `LOG`. `ERROR.raised_at` is a
|
||||
zero-padded UTF-8 `file:line` prefix; receivers use bytes before the first zero,
|
||||
or the complete field when no zero is present.
|
||||
`KAPTAN_LOG.level` accepts only Error (3), Warning (4), Info (6), and Debug
|
||||
(7); Trace is encoded as Debug (7) plus the `TRACE` flag. Other MAVLink
|
||||
severity numbers are not Kaptan log levels.
|
||||
The `KAPTAN_ERROR` message kind already means a reportable firmware error, so it has
|
||||
`LOG.level` is the typed severity-ordered Kaptan wire enum Trace (1), Debug
|
||||
(2), Info (3), Warn (4), or Error (5). Off (0) is a filter-only sentinel and
|
||||
is never emitted as a `LOG` event. `LOG.flags` currently owns only the
|
||||
Truncated bit (1).
|
||||
The `ERROR` message kind already means a reportable firmware error, so it has
|
||||
no redundant level or flags field.
|
||||
|
||||
`error_id` is the stable nonzero catalog number explicitly assigned to the
|
||||
Rust error variant. Renaming or reordering a variant does not change it.
|
||||
`raised_at` identifies the reporting point where the `Err` entered
|
||||
diagnostics. Error details requiring
|
||||
machine action stay in their owning protocol, notably `KAPTAN_CONFIG_RESULT`.
|
||||
diagnostics. Protocol failures remain in their owning response; for example, a
|
||||
rejected KCFG upload returns a `FILE_CONTROL` failure and readable
|
||||
bounded detail.
|
||||
Delivery is bounded and lossy under link pressure; heartbeat and safety
|
||||
telemetry use separate paths. Logs have no publication rate setting and are
|
||||
not periodic streams. A retained event leaves its MAVLink sink only once the
|
||||
@@ -62,10 +64,10 @@ event.
|
||||
|
||||
## Filtering
|
||||
|
||||
The single restart-only `mavlink.logging.level_filter` field uses the familiar
|
||||
Off, Error, Warn, Info, Debug, and Trace choices. `Info`, for example, accepts
|
||||
Error, Warn, and Info log events. `Off` suppresses `KAPTAN_LOG` on MAVLink
|
||||
without suppressing reportable `KAPTAN_ERROR` events or logs sent to another
|
||||
The single restart-only `mavlink.logging.level_filter` field uses Off (0),
|
||||
Trace (1), Debug (2), Info (3), Warn (4), and Error (5). `Info`, for example,
|
||||
accepts Info, Warn, and Error log events. `Off` suppresses `LOG` on MAVLink
|
||||
without suppressing reportable `ERROR` events or logs sent to another
|
||||
sink. There is no separate enable flag and no MAVLink-specific set of extra
|
||||
runtime log levels. F722 uses the validated filter recovered at boot, falling
|
||||
back to its board factory when the journal is empty or invalid.
|
||||
@@ -73,14 +75,14 @@ back to its board factory when the journal is empty or invalid.
|
||||
Events retain the compact typed `Level` and sink configuration retains the
|
||||
compact typed `LevelFilter`. Generic schema discovery exposes the filter's
|
||||
named choices to the configurator, so the UI carries no hardcoded field list.
|
||||
Only the MAVLink adapter converts the five event levels to MAVLink's numeric
|
||||
severity representation; Trace uses MAVLink Debug plus the Trace flag.
|
||||
Only the MAVLink adapter converts the five event levels to the typed Kaptan
|
||||
wire enum.
|
||||
|
||||
The log ingress is transport-neutral and unfiltered. The tested
|
||||
`SitlConfigRuntime` composition applies the configured MAVLink policy when
|
||||
fanning an event into that sink and proves `kaptan_log::info!` reaches a
|
||||
generated `KAPTAN_LOG` payload.
|
||||
`kaptan-sitl serve` does not yet attach a config/diagnostic MAVLink link. F722
|
||||
images accept only the unsigned configuration service on their directly wired
|
||||
generated `LOG` payload.
|
||||
`kaptan-sitl serve` does not yet attach a file/diagnostic MAVLink link. F722
|
||||
images accept only the unsigned Kaptan file service on their directly wired
|
||||
local UART; that direct-wire assumption does not extend to a shared or remote
|
||||
MAVLink network.
|
||||
+55
-23
@@ -1,33 +1,36 @@
|
||||
# MAVLink and telemetry
|
||||
|
||||
Kaptan emits telemetry using MAVLink 2 framing. Inbound processing is narrowly
|
||||
scoped:
|
||||
Kaptan uses MAVLink 2 framing exclusively with the generated Kaptan dialect.
|
||||
It neither emits nor accepts messages from `common`, `minimal`, or another
|
||||
dialect. 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.
|
||||
- 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.
|
||||
- CRC-valid unsigned MAVLink 2 frames are retained only when their message ID
|
||||
and extra CRC belong to the Kaptan dialect. Exact-target Kaptan file requests
|
||||
are the only inbound records with a current firmware consumer.
|
||||
|
||||
`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.
|
||||
Shared or remote inbound authority is deliberately unsupported. Enabling it
|
||||
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
|
||||
The local UART is Kaptan's initial operational file transport, not an
|
||||
authenticated remote-control channel. Any transmitter electrically connected
|
||||
to that RX line can issue configuration commands, so connect the USB-UART
|
||||
to that RX line can issue file requests, 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.
|
||||
The custom Kaptan file service admits one exact source principal for a bounded
|
||||
stop-and-wait transfer. A receive fault or lease expiry aborts its staged
|
||||
provider state. Completed control replies have a bounded replay path so a lost
|
||||
close response does not repeat a flash operation. This serialization 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.
|
||||
@@ -37,22 +40,51 @@ 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.
|
||||
fields, including the readable zero-padded `ERROR.raised_at` reporting
|
||||
location. 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, level, and
|
||||
`http://127.0.0.1:4861`. That view retains individual `LOG` and
|
||||
`ERROR` events in receive order with local receive time, level, 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`, and `kaptan/error.xml`.
|
||||
`KAPTAN_LOG` is an outbound human-readable four-field record. `KAPTAN_ERROR`
|
||||
one-message leaves grouped by interaction contract:
|
||||
|
||||
| Directory | Contract |
|
||||
| --- | --- |
|
||||
| `publish/` | Zero-reply records for any interested receiver. |
|
||||
| `exchange/` | Exact-endpoint requests with one terminal response; currently empty. |
|
||||
| `transfer/` | Exact-endpoint, bounded multi-message sessions. |
|
||||
|
||||
The root includes every message leaf directly; there are no redundant category
|
||||
index files or separate enum catalogs. Placement is a wire-contract
|
||||
classification, while bindgen still generates one flat `generated::kaptan`
|
||||
module. Bare message names are scoped by that sole dialect and must not be
|
||||
merged with another MAVLink dialect. `exchange/` gains its first XML only when
|
||||
an exchange has a current consumer.
|
||||
`LOG` is an outbound human-readable four-field record. `ERROR`
|
||||
is the separate bounded channel for reportable firmware errors, carrying a
|
||||
stable explicit ID plus the `file:line` of its reporting point, and needs no
|
||||
redundant level field. Configuration messages back the current target-described
|
||||
web configurator and the future signed GCS. See
|
||||
redundant level field. `FILE_CONTROL` and `FILE_DATA` implement
|
||||
Kaptan's generic virtual-file transport without standard MAVLink FTP
|
||||
compatibility. The current configurator reads and replaces
|
||||
`/config/user.kcfg`. See
|
||||
[Configuration](configuration.md), [Logs](logs.md), and [Errors](errors.md) for
|
||||
the exact contracts.
|
||||
|
||||
The current scheduled publications are deliberately native rather than
|
||||
projections into a broader dialect:
|
||||
|
||||
| Publication | Current payload |
|
||||
| --- | --- |
|
||||
| `HEARTBEAT` (51027) | The single current initialized/output-inhibited state. |
|
||||
| `IMU` (51028) | Monotonic microseconds, body acceleration in mg, angular rate in mrad/s, and temperature in cdegC. |
|
||||
| `RANGE` (51029) | Monotonic microseconds and downward distance in mm. |
|
||||
| `OPTICAL_FLOW` (51030) | Monotonic microseconds, integer ground-relative velocity in mm/s, distance in mm, and quality. |
|
||||
|
||||
These records preserve the firmware's bounded native values. They do not
|
||||
carry unused sensor IDs, repeated board topology, float projections, narrowed
|
||||
timestamps, or clamped measurements.
|
||||
+21
-8
@@ -5,14 +5,15 @@ This page collects stable limits and points to the detailed contracts.
|
||||
| Surface | Current contract |
|
||||
| --- | --- |
|
||||
| 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 macro-produced level/text; `KAPTAN_ERROR` (51021) for a bounded reportable `{ error_id, raised_at[96] }` firmware error. |
|
||||
| F722 configuration | Target-described fields and board factory defaults; the current local transport is a directly wired unsigned UART with motor outputs physically inhibited. |
|
||||
| F722 persistence | One bounded native-width scalar snapshot inside each slot of a power-loss-safe two-slot flash journal. |
|
||||
| Public config artifact | One canonical self-describing KCFG file containing generated metadata, factory values, and the complete committed candidate. |
|
||||
| File transfer | Custom `FILE_CONTROL` (51025) and `FILE_DATA` (51026), one owner-bound stop-and-wait transfer, 246-byte data chunks, CRC-32C. |
|
||||
| Diagnostics | `LOG` (51020) for macro-produced level/text; `ERROR` (51021) for a bounded reportable `{ error_id, raised_at[96] }` firmware error. |
|
||||
| Publications | Kaptan-native `HEARTBEAT` (51027), `IMU` (51028), `RANGE` (51029), and `OPTICAL_FLOW` (51030); exact integer units and monotonic `u64` microseconds. |
|
||||
| F722 configuration | `/config/user.kcfg`; target-described fields and board factory values over a directly wired unsigned UART with motor outputs physically inhibited. |
|
||||
|
||||
Read [Configuration](configuration.md) for the field/consumer matrix and GCS
|
||||
transaction sequence, [Logs](logs.md) for receiver decoding and filtering, and
|
||||
Read [Configuration](configuration.md) for configuration ownership, artifact,
|
||||
and file contracts, [Logs](logs.md) for receiver decoding and filtering, and
|
||||
[Errors](errors.md) for reportable errors and panic scope.
|
||||
|
||||
## Verification
|
||||
@@ -28,8 +29,20 @@ cargo clippy --workspace --all-targets \
|
||||
--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
|
||||
cargo build --release --locked --offline \
|
||||
-p kaptan-kakute-f7-mini-v3 -p kaptan-geprc-f722-v2 \
|
||||
--target thumbv7em-none-eabihf
|
||||
python3 -m unittest scripts/test-analyze-fw.py
|
||||
scripts/analyze-fw.py \
|
||||
target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3 \
|
||||
platforms/stm32f7/link/f722/memory.x
|
||||
scripts/analyze-fw.py \
|
||||
target/thumbv7em-none-eabihf/release/kaptan-geprc-f722-v2 \
|
||||
platforms/stm32f7/link/f722/memory.x
|
||||
```
|
||||
|
||||
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.
|
||||
an actuator path. The ELF checks prove that the flash-busy operation is linked
|
||||
into executable SRAM and reject compiler-outlined control flow or PC-relative
|
||||
literal loads outside that section.
|
||||
@@ -16,12 +16,12 @@ 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 is accepted only by the configuration service and has no
|
||||
actuator path;
|
||||
- a future verified arm command is still acknowledged as unsupported.
|
||||
- only CRC-valid Kaptan-dialect MAVLink input reaches the bounded virtual-file
|
||||
service, which has no actuator path;
|
||||
- no arm command is defined or admitted.
|
||||
|
||||
The protocol reference crate remains in the workspace only as a framing and
|
||||
arming-sequence reference. It does not grant hardware access or authority.
|
||||
The framing and file-transfer crates do not grant hardware access or actuator
|
||||
authority.
|
||||
|
||||
Run the structural guard after any platform or board change:
|
||||
|
||||
|
||||
+5
-5
@@ -36,8 +36,8 @@ Open <https://app.gazebosim.org/visualization>, connect to
|
||||
|
||||
## Quad-X profile
|
||||
|
||||
SITL starts through the same central `ConfigManager` composition used by the
|
||||
host protocol tests. Create and validate a private host profile file with:
|
||||
SITL starts through the central `ConfigManager` lifecycle. Create and validate
|
||||
a private host profile file with:
|
||||
|
||||
```sh
|
||||
kaptan-sitl config write-default kaptan-sitl.cbor
|
||||
@@ -49,9 +49,9 @@ The file selects the restart-only profile used to build the estimator,
|
||||
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 transaction contract
|
||||
and safety boundary.
|
||||
the central manager for that boot but does not yet open a MAVLink file/log
|
||||
endpoint; see [Configuration](configuration.md) for the KCFG, file-transfer,
|
||||
and safety boundaries.
|
||||
|
||||
## Limits
|
||||
|
||||
|
||||
Reference in new issue
Block a user