survive disconnect during BLE MTU lookup
This commit is contained in:
@@ -61,7 +61,17 @@ remains the nominal datasheet value. Mapped raw counts are stored directly, and
|
||||
sensor-native counts are reconstructed losslessly from the documented mapping.
|
||||
No software filtering or sensor fusion is performed yet.
|
||||
|
||||
The ESP32-C3 polls at exactly 100 Hz in a dedicated acquisition task, but each
|
||||
The BLE reconnect fixture measured scheduling jitter without drift: among 2,575
|
||||
contiguous sample intervals, 1,293 differed from exactly 10 ms; absolute timing
|
||||
deviation had a 4 us median, 160 us p95, 170 us p99, and 780 us maximum, while
|
||||
cumulative error was only 152 us over 25.75 seconds. Bluetooth tasks can preempt
|
||||
the polling task, but every record carries its actual acquisition timestamp.
|
||||
Future fusion, integration, and filtering must derive each `dt` from those
|
||||
timestamps rather than assume a uniform 10 ms interval. Sensor DRDY/FIFO
|
||||
acquisition remains the later refinement for reducing the jitter itself.
|
||||
|
||||
The ESP32-C3 schedules nominal 100 Hz polling in a dedicated acquisition task,
|
||||
but each
|
||||
sensor has an independent internal
|
||||
sample clock. The status registers are read immediately before each XYZ read so a
|
||||
consumer can distinguish a fresh sample from a repeated poll and identify gyro
|
||||
|
||||
@@ -100,7 +100,9 @@ cumulative uint32 counters:
|
||||
The header's cumulative dropped-sample count remains the sum of sensor read
|
||||
failures and queue overflows, preserving version-1 receiver compatibility while
|
||||
the status payload makes the causes independently observable. USB-specific BLE
|
||||
counters remain zero.
|
||||
counters remain zero. The rejected-ACK total can also include a harmless valid
|
||||
duplicate that arrives after its frame has already completed, so a nonzero value
|
||||
does not by itself prove corruption or a hostile receiver.
|
||||
|
||||
## Buffering
|
||||
|
||||
|
||||
@@ -50,10 +50,19 @@ therefore compare the sequence and raw bytes with their last persisted frame,
|
||||
avoid writing a duplicate, and ACK the replay again. The reference
|
||||
`tools/capture_ble.py` implements this ordering.
|
||||
|
||||
The rejected-ACK counter is diagnostic, not a pure corruption count. A valid
|
||||
duplicate ACK can arrive after the output task has already completed that frame
|
||||
and begun the next one; firmware then rejects and counts the now-stale write.
|
||||
|
||||
BLE notification success only means the fragment entered the stack. The `ACK1`
|
||||
write is the end-to-end boundary. It deliberately confirms application
|
||||
persistence rather than radio or ATT delivery alone.
|
||||
|
||||
Version 1 is an unauthenticated, single-connection prototype service. It does
|
||||
not yet provide pairing, authorization, or confidentiality against a nearby
|
||||
peer; those are separate from the loss/replay guarantees above.
|
||||
peer; those are separate from the loss/replay guarantees above. A nearby peer
|
||||
can also deny availability by subscribing and never acknowledging: firmware
|
||||
correctly retains and replays the owned frame, but the RAM queue eventually
|
||||
fills while the legitimate receiver remains excluded. Pairing and connection
|
||||
authorization are required before treating this as a hostile-environment
|
||||
logger.
|
||||
|
||||
@@ -340,6 +340,12 @@ static trikke_transport_status_t ble_poll_once(void *context)
|
||||
portEXIT_CRITICAL(&ble->lock);
|
||||
|
||||
const uint16_t mtu = ble_att_mtu(connection_handle);
|
||||
if (mtu == 0) {
|
||||
// The connection can disappear after the locked state snapshot above.
|
||||
// The GAP callback advances the delivery epoch; retain ownership and
|
||||
// let a later poll restart the frame after resubscription.
|
||||
return TRIKKE_TRANSPORT_PENDING;
|
||||
}
|
||||
if (mtu <= 3 + TRIKKE_BLE_FRAGMENT_HEADER_SIZE) {
|
||||
return TRIKKE_TRANSPORT_FATAL;
|
||||
}
|
||||
|
||||
Vendored
+5
@@ -63,6 +63,11 @@ removed before production firmware was built and flashed.
|
||||
final status records one disconnect and one deliberate frame replay, with
|
||||
zero notification failures or invalid ACKs. It validates that the 10.24-second
|
||||
queue covered the measured resubscription interval without permanent loss.
|
||||
Of its 2,575 contiguous sample intervals, 1,293 differ from exactly 10 ms.
|
||||
Absolute deviation has a 4 us median, 160 us p95, 170 us p99, and 780 us
|
||||
maximum; cumulative error is 152 us over 25.75 seconds. This records bounded
|
||||
BLE scheduling jitter without rate drift and requires timestamp-derived `dt`
|
||||
in future fusion work.
|
||||
|
||||
`tests/test_trikke_protocol.py` verifies the hashes, parses the captures in
|
||||
fragmented chunks, and asserts these signatures so the hardware evidence remains
|
||||
|
||||
Reference in New Issue
Block a user