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.
|
sensor-native counts are reconstructed losslessly from the documented mapping.
|
||||||
No software filtering or sensor fusion is performed yet.
|
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
|
sensor has an independent internal
|
||||||
sample clock. The status registers are read immediately before each XYZ read so a
|
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
|
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
|
The header's cumulative dropped-sample count remains the sum of sensor read
|
||||||
failures and queue overflows, preserving version-1 receiver compatibility while
|
failures and queue overflows, preserving version-1 receiver compatibility while
|
||||||
the status payload makes the causes independently observable. USB-specific BLE
|
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
|
## 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
|
avoid writing a duplicate, and ACK the replay again. The reference
|
||||||
`tools/capture_ble.py` implements this ordering.
|
`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`
|
BLE notification success only means the fragment entered the stack. The `ACK1`
|
||||||
write is the end-to-end boundary. It deliberately confirms application
|
write is the end-to-end boundary. It deliberately confirms application
|
||||||
persistence rather than radio or ATT delivery alone.
|
persistence rather than radio or ATT delivery alone.
|
||||||
|
|
||||||
Version 1 is an unauthenticated, single-connection prototype service. It does
|
Version 1 is an unauthenticated, single-connection prototype service. It does
|
||||||
not yet provide pairing, authorization, or confidentiality against a nearby
|
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);
|
portEXIT_CRITICAL(&ble->lock);
|
||||||
|
|
||||||
const uint16_t mtu = ble_att_mtu(connection_handle);
|
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) {
|
if (mtu <= 3 + TRIKKE_BLE_FRAGMENT_HEADER_SIZE) {
|
||||||
return TRIKKE_TRANSPORT_FATAL;
|
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
|
final status records one disconnect and one deliberate frame replay, with
|
||||||
zero notification failures or invalid ACKs. It validates that the 10.24-second
|
zero notification failures or invalid ACKs. It validates that the 10.24-second
|
||||||
queue covered the measured resubscription interval without permanent loss.
|
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
|
`tests/test_trikke_protocol.py` verifies the hashes, parses the captures in
|
||||||
fragmented chunks, and asserts these signatures so the hardware evidence remains
|
fragmented chunks, and asserts these signatures so the hardware evidence remains
|
||||||
|
|||||||
Reference in New Issue
Block a user