fix lr1110 CRC bug

This commit is contained in:
liquidraver
2026-07-09 21:55:42 +02:00
parent 8e4ca50747
commit ce69a95e00
2 changed files with 61 additions and 18 deletions
@@ -429,8 +429,19 @@ static void lr11xx_dio1_work_handler(struct k_work *work)
data->dio1_stuck_count = 0;
}
/* ── RX done ── */
if (irq & LR11XX_SYSTEM_IRQ_RX_DONE) {
/* ── RX done ──
* Gated on no error bits: a CRC-failed packet asserts RX_DONE and
* CRC_ERROR together on this chip family (same as SX126x — see the
* sx126x patch's "they co-fire here"; LBM's radio_planner likewise
* checks errors before RX_DONE), so an ungated done-first read
* would deliver corrupted payloads as valid. A good packet
* coalesced with an earlier HEADER_ERROR in the same handler
* window is dropped too — the header error may have shifted the
* RX buffer pointer (errata handling below), making the read
* suspect. The error branch below owns the window instead. */
if ((irq & LR11XX_SYSTEM_IRQ_RX_DONE) &&
!(irq & (LR11XX_SYSTEM_IRQ_CRC_ERROR |
LR11XX_SYSTEM_IRQ_HEADER_ERROR))) {
lr11xx_radio_rx_buffer_status_t rx_stat;
lr11xx_radio_get_rx_buffer_status(ctx, &rx_stat);
@@ -525,21 +536,34 @@ static void lr11xx_dio1_work_handler(struct k_work *work)
}
}
/* ── CRC / Header error ── */
if (irq & LR11XX_SYSTEM_IRQ_CRC_ERROR ||
((irq & LR11XX_SYSTEM_IRQ_HEADER_ERROR) &&
!(irq & LR11XX_SYSTEM_IRQ_SYNC_WORD_HEADER_VALID))) {
LOG_DBG("RX error: CRC=%d HDR=%d",
/* ── CRC / Header error ──
* Plain `CRC || HDR` — no SYNC_WORD_HEADER_VALID gate (RadioLib
* readData's false-alarm filter). IRQ status is bulk-cleared on
* every handler entry, so a set HEADER_ERROR always belongs to
* this window; a SYNC_VALID bit latched by another packet in the
* same window must not suppress the errata standby below. */
if (irq & (LR11XX_SYSTEM_IRQ_CRC_ERROR |
LR11XX_SYSTEM_IRQ_HEADER_ERROR)) {
LOG_DBG("RX error: CRC=%d HDR=%d RXDONE=%d",
(irq & LR11XX_SYSTEM_IRQ_CRC_ERROR) ? 1 : 0,
(irq & LR11XX_SYSTEM_IRQ_HEADER_ERROR) ? 1 : 0);
(irq & LR11XX_SYSTEM_IRQ_HEADER_ERROR) ? 1 : 0,
(irq & LR11XX_SYSTEM_IRQ_RX_DONE) ? 1 : 0);
/* LR1110 errata: header error can shift the RX buffer
* pointer by 4 bytes. Standby clears the shift. */
/* LR1110 errata: a header error makes the chip's reported
* buffer_start_pointer stale by +4 for every subsequent
* packet (stacking) until a standby resets the shift.
* Arduino MeshCore's CustomLR1110 calls standby() on every
* header error unconditionally — mirror that. */
if (irq & LR11XX_SYSTEM_IRQ_HEADER_ERROR) {
lr11xx_system_set_standby(ctx,
LR11XX_SYSTEM_STANDBY_CFG_RC);
}
/* Drop whatever the failed (or coalesced) packet left in
* the RX buffer — RadioLib clears it on the CRC-error read
* path too. */
lr11xx_regmem_clear_rxbuffer(ctx);
if (!data->tx_active) {
lr11xx_restart_rx(data);
rx_restarted = true;
@@ -601,8 +601,17 @@ static void lr20xx_dio1_work_handler(struct k_work *work)
data->dio1_stuck_count = 0;
}
/* ── RX done ── */
if (irq & LR20XX_SYSTEM_IRQ_RX_DONE) {
/* ── RX done ──
* Gated on no error bits: a CRC-failed packet asserts RX_DONE and
* CRC_ERROR together on this chip family (same as SX126x/LR11xx),
* so an ungated done-first read would deliver corrupted payloads
* as valid. A good packet coalesced with an earlier header error
* in the same handler window is dropped too — the aborted packet
* may have left bytes in the RX FIFO, misaligning the read. The
* error branch below owns the window instead. */
if ((irq & LR20XX_SYSTEM_IRQ_RX_DONE) &&
!(irq & (LR20XX_SYSTEM_IRQ_CRC_ERROR |
LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR))) {
uint16_t pkt_len = 0;
lr20xx_radio_common_get_rx_packet_length(ctx, &pkt_len);
@@ -688,13 +697,23 @@ static void lr20xx_dio1_work_handler(struct k_work *work)
}
}
/* ── CRC / Header error ── */
if (irq & LR20XX_SYSTEM_IRQ_CRC_ERROR ||
((irq & LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR) &&
!(irq & LR20XX_SYSTEM_IRQ_SYNC_WORD_HEADER_VALID))) {
LOG_WRN("RX error: CRC=%d HDR=%d",
/* ── CRC / Header error ──
* Plain `CRC || HDR` — no SYNC_WORD_HEADER_VALID gate. IRQ status
* is bulk-cleared on every handler entry, so a set header error
* always belongs to this window; a SYNC_VALID bit latched by
* another packet in the same window must not suppress it. */
if (irq & (LR20XX_SYSTEM_IRQ_CRC_ERROR |
LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR)) {
LOG_WRN("RX error: CRC=%d HDR=%d RXDONE=%d",
(irq & LR20XX_SYSTEM_IRQ_CRC_ERROR) ? 1 : 0,
(irq & LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR) ? 1 : 0);
(irq & LR20XX_SYSTEM_IRQ_LORA_HEADER_ERROR) ? 1 : 0,
(irq & LR20XX_SYSTEM_IRQ_RX_DONE) ? 1 : 0);
/* Drop whatever the failed (or coalesced) packet left in
* the RX FIFO so the next packet's read starts aligned —
* lr20xx_restart_rx does not clear it (only full start_rx
* does). */
lr20xx_radio_fifo_clear_rx(ctx);
if (!data->tx_active) {
lr20xx_restart_rx(data);