diff --git a/zephcore/patches/zephyr/0003-lora-sx126x-native.patch b/zephcore/patches/zephyr/0003-lora-sx126x-native.patch index dd59c8c..49bfa38 100644 --- a/zephcore/patches/zephyr/0003-lora-sx126x-native.patch +++ b/zephcore/patches/zephyr/0003-lora-sx126x-native.patch @@ -68,7 +68,7 @@ index 17689720dd2..09982dc2e70 100644 return -EINVAL; } diff --git a/drivers/lora/native/sx126x/sx126x.c b/drivers/lora/native/sx126x/sx126x.c -index 30243ba5dc7..0cec01d84a9 100644 +index 30243ba5dc7..d2339ee8780 100644 --- a/drivers/lora/native/sx126x/sx126x.c +++ b/drivers/lora/native/sx126x/sx126x.c @@ -6,14 +6,21 @@ @@ -223,7 +223,7 @@ index 30243ba5dc7..0cec01d84a9 100644 /* Set packet type to LoRa */ ret = sx126x_set_packet_type(dev, SX126X_PACKET_TYPE_LORA); if (ret < 0) { -@@ -374,10 +465,19 @@ static int sx126x_chip_init(const struct device *dev) +@@ -374,10 +465,23 @@ static int sx126x_chip_init(const struct device *dev) return ret; } @@ -240,13 +240,17 @@ index 30243ba5dc7..0cec01d84a9 100644 - ret = sx126x_set_dio_irq_params(dev, irq_mask, irq_mask, 0, 0); + SX126X_IRQ_RX_TX_TIMEOUT | SX126X_IRQ_CRC_ERR | + SX126X_IRQ_CAD_DONE | SX126X_IRQ_CAD_ACTIVITY_DETECTED | -+ SX126X_IRQ_PREAMBLE_DETECTED | SX126X_IRQ_HEADER_VALID; -+ uint16_t dio1_mask = irq_mask & ~SX126X_IRQ_PREAMBLE_DETECTED; ++ SX126X_IRQ_PREAMBLE_DETECTED | SX126X_IRQ_HEADER_VALID | ++ SX126X_IRQ_HEADER_ERR; ++ /* HEADER_ERR is unmasked (so it latches and is readable in the RX_DONE ++ * snapshot) but excluded from DIO1 -- like PREAMBLE_DETECTED, it fires ++ * on noise/foreign traffic and must not wake the work queue on its own. */ ++ uint16_t dio1_mask = irq_mask & ~(SX126X_IRQ_PREAMBLE_DETECTED | SX126X_IRQ_HEADER_ERR); + ret = sx126x_set_dio_irq_params(dev, irq_mask, dio1_mask, 0, 0); if (ret < 0) { LOG_ERR("Set IRQ params failed: %d", ret); return ret; -@@ -398,7 +498,7 @@ static void sx126x_dio1_callback(const struct device *dev) +@@ -398,7 +502,7 @@ static void sx126x_dio1_callback(const struct device *dev) { struct sx126x_data *data = dev->data; @@ -255,7 +259,7 @@ index 30243ba5dc7..0cec01d84a9 100644 } static void sx126x_set_rf_path(const struct device *dev, bool enable, bool tx) -@@ -406,7 +506,20 @@ static void sx126x_set_rf_path(const struct device *dev, bool enable, bool tx) +@@ -406,7 +510,20 @@ static void sx126x_set_rf_path(const struct device *dev, bool enable, bool tx) const struct sx126x_hal_config *config = dev->config; sx126x_hal_set_antenna_enable(dev, enable); @@ -277,7 +281,7 @@ index 30243ba5dc7..0cec01d84a9 100644 sx126x_hal_set_rf_switch(dev, enable, tx); } } -@@ -455,6 +568,98 @@ static int sx126x_reconnect_rf_gpios(const struct device *dev) +@@ -455,6 +572,98 @@ static int sx126x_reconnect_rf_gpios(const struct device *dev) } #endif /* CONFIG_PM_DEVICE */ @@ -376,7 +380,7 @@ index 30243ba5dc7..0cec01d84a9 100644 static int sx126x_set_sleep(const struct device *dev) { struct sx126x_data *data = dev->data; -@@ -533,8 +738,16 @@ static void sx126x_handle_irq_rx_done(const struct device *dev, uint16_t irq_sta +@@ -533,8 +742,16 @@ static void sx126x_handle_irq_rx_done(const struct device *dev, uint16_t irq_sta struct sx126x_data *data = dev->data; struct sx126x_rx_result result = { 0 }; uint8_t payload_len = 0, offset = 0; @@ -393,7 +397,37 @@ index 30243ba5dc7..0cec01d84a9 100644 /* Get received packet info */ ret = sx126x_get_rx_buffer_status(dev, &payload_len, &offset); if (ret < 0) { -@@ -564,20 +777,34 @@ static void sx126x_handle_irq_rx_done(const struct device *dev, uint16_t irq_sta +@@ -544,9 +761,26 @@ static void sx126x_handle_irq_rx_done(const struct device *dev, uint16_t irq_sta + /* Get signal quality */ + sx126x_get_packet_status(dev, &result.rssi, &result.snr); + +- /* Check for CRC error */ +- if (irq_status & SX126X_IRQ_CRC_ERR) { +- LOG_WRN("CRC error"); ++ /* Reject CRC errors AND header errors. A header error with no ++ * valid header means no payload was written to the FIFO, so ++ * GetRxBufferStatus still points at the PREVIOUS packet -- reading ++ * it re-delivers a stale "zombie" packet with a fresh (noise) SNR. ++ * Mirrors RadioLib SX126x::readData() and the LR11xx/LR20xx ++ * drivers. The !HEADER_VALID term keeps a normal ++ * valid-header-then-CRC-fail packet on the CRC_ERR path. */ ++ if ((irq_status & SX126X_IRQ_CRC_ERR) || ++ ((irq_status & SX126X_IRQ_HEADER_ERR) && ++ !(irq_status & SX126X_IRQ_HEADER_VALID))) { ++ LOG_WRN("RX rejected: CRC=%d HDR=%d", ++ (irq_status & SX126X_IRQ_CRC_ERR) ? 1 : 0, ++ (irq_status & SX126X_IRQ_HEADER_ERR) ? 1 : 0); ++ result.status = -EIO; ++ } else if (payload_len == 0) { ++ /* Clean RX_DONE but the reported payload length is 0 -- ++ * nothing to deliver. Route to the error path so it is ++ * counted; otherwise result.status stays 0 and falls ++ * through both delivery arms below (silent drop). */ ++ LOG_DBG("RX done: zero-length payload"); + result.status = -EIO; + } else { + /* Read payload into shared buffer */ +@@ -564,20 +798,34 @@ static void sx126x_handle_irq_rx_done(const struct device *dev, uint16_t irq_sta } } @@ -440,7 +474,7 @@ index 30243ba5dc7..0cec01d84a9 100644 } } else { /* Sync mode */ -@@ -589,8 +816,69 @@ static void sx126x_handle_irq_rx_done(const struct device *dev, uint16_t irq_sta +@@ -589,8 +837,69 @@ static void sx126x_handle_irq_rx_done(const struct device *dev, uint16_t irq_sta static void sx126x_handle_irq_timeout(const struct device *dev) { struct sx126x_data *data = dev->data; @@ -510,7 +544,7 @@ index 30243ba5dc7..0cec01d84a9 100644 sx126x_set_sleep(dev); if (data->tx_async_signal != NULL) { -@@ -633,10 +921,46 @@ static void sx126x_irq_work_handler(struct k_work *work) +@@ -633,10 +942,46 @@ static void sx126x_irq_work_handler(struct k_work *work) sx126x_handle_irq_rx_done(dev, irq_status); } @@ -557,7 +591,7 @@ index 30243ba5dc7..0cec01d84a9 100644 /* Re-enable the DIO1 interrupt for the next event (unless sleeping) */ if (atomic_get(&data->state) != SX126X_REST_STATE) { sx126x_hal_dio1_irq_enable(dev); -@@ -682,7 +1006,7 @@ static int sx126x_lora_config(const struct device *dev, +@@ -682,7 +1027,7 @@ static int sx126x_lora_config(const struct device *dev, /* Configure PA and TX power based on chip variant and frequency */ ret = sx126x_hal_configure_tx_params(dev, config->tx_power, config->frequency, @@ -566,7 +600,7 @@ index 30243ba5dc7..0cec01d84a9 100644 if (ret < 0) { goto out; } -@@ -698,6 +1022,29 @@ static int sx126x_lora_config(const struct device *dev, +@@ -698,6 +1043,29 @@ static int sx126x_lora_config(const struct device *dev, goto out; } @@ -596,7 +630,7 @@ index 30243ba5dc7..0cec01d84a9 100644 /* Set sync word */ ret = sx126x_set_sync_word(dev, config->public_network); if (ret < 0) { -@@ -721,6 +1068,8 @@ out: +@@ -721,6 +1089,8 @@ out: return ret; } @@ -605,7 +639,7 @@ index 30243ba5dc7..0cec01d84a9 100644 static int sx126x_lora_send_async(const struct device *dev, uint8_t *data_buf, uint32_t data_len, struct k_poll_signal *async) -@@ -738,11 +1087,27 @@ static int sx126x_lora_send_async(const struct device *dev, +@@ -738,11 +1108,27 @@ static int sx126x_lora_send_async(const struct device *dev, return -EINVAL; } @@ -635,7 +669,7 @@ index 30243ba5dc7..0cec01d84a9 100644 k_mutex_lock(&data->lock, K_FOREVER); ret = sx126x_ensure_ready(dev); -@@ -752,6 +1117,58 @@ static int sx126x_lora_send_async(const struct device *dev, +@@ -752,6 +1138,58 @@ static int sx126x_lora_send_async(const struct device *dev, return ret; } @@ -694,7 +728,7 @@ index 30243ba5dc7..0cec01d84a9 100644 data->tx_async_signal = async; k_msgq_purge(&data->tx_msgq); -@@ -777,6 +1194,29 @@ static int sx126x_lora_send_async(const struct device *dev, +@@ -777,6 +1215,29 @@ static int sx126x_lora_send_async(const struct device *dev, /* Enable antenna and set TX path */ sx126x_set_rf_path(dev, true, true); @@ -724,7 +758,7 @@ index 30243ba5dc7..0cec01d84a9 100644 /* Start transmission with 10 second timeout */ ret = sx126x_set_tx(dev, 10000); if (ret < 0) { -@@ -847,6 +1287,8 @@ static int sx126x_lora_recv(const struct device *dev, uint8_t *data_buf, +@@ -847,6 +1308,8 @@ static int sx126x_lora_recv(const struct device *dev, uint8_t *data_buf, } data->rx_cb = NULL; @@ -733,7 +767,7 @@ index 30243ba5dc7..0cec01d84a9 100644 k_msgq_purge(&data->rx_msgq); /* Set packet parameters for variable length reception */ -@@ -918,6 +1360,8 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -918,6 +1381,8 @@ static int sx126x_lora_recv_async(const struct device *dev, /* Stop async reception */ data->rx_cb = NULL; data->rx_cb_user_data = NULL; @@ -742,7 +776,7 @@ index 30243ba5dc7..0cec01d84a9 100644 if (atomic_cas(&data->state, SX126X_STATE_RX, SX126X_STATE_IDLE)) { sx126x_set_standby(dev, SX126X_STANDBY_RC); sx126x_set_sleep(dev); -@@ -932,6 +1376,19 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -932,6 +1397,19 @@ static int sx126x_lora_recv_async(const struct device *dev, return -EINVAL; } @@ -762,7 +796,7 @@ index 30243ba5dc7..0cec01d84a9 100644 if (!atomic_cas(&data->state, SX126X_REST_STATE, SX126X_STATE_RX)) { LOG_ERR("Busy"); k_mutex_unlock(&data->lock); -@@ -945,8 +1402,18 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -945,8 +1423,18 @@ static int sx126x_lora_recv_async(const struct device *dev, return ret; } @@ -781,7 +815,7 @@ index 30243ba5dc7..0cec01d84a9 100644 /* Set packet parameters */ ret = sx126x_set_packet_params(dev, -@@ -959,6 +1426,7 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -959,6 +1447,7 @@ static int sx126x_lora_recv_async(const struct device *dev, SX126X_LORA_IQ_INVERTED : SX126X_LORA_IQ_STANDARD); if (ret < 0) { data->rx_cb = NULL; @@ -789,7 +823,7 @@ index 30243ba5dc7..0cec01d84a9 100644 sx126x_set_sleep(dev); k_mutex_unlock(&data->lock); return ret; -@@ -971,11 +1439,21 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -971,11 +1460,21 @@ static int sx126x_lora_recv_async(const struct device *dev, ret = sx126x_set_rx(dev, 0); if (ret < 0) { data->rx_cb = NULL; @@ -811,7 +845,7 @@ index 30243ba5dc7..0cec01d84a9 100644 k_mutex_unlock(&data->lock); return 0; } -@@ -1051,7 +1529,7 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency, +@@ -1051,7 +1550,7 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency, /* Set PA config and TX power */ ret = sx126x_hal_configure_tx_params(dev, tx_power, frequency, @@ -820,7 +854,7 @@ index 30243ba5dc7..0cec01d84a9 100644 if (ret < 0) { sx126x_set_sleep(dev); k_mutex_unlock(&data->lock); -@@ -1083,14 +1561,602 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency, +@@ -1083,14 +1582,602 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency, return 0; } @@ -1430,7 +1464,7 @@ index 30243ba5dc7..0cec01d84a9 100644 }; #ifdef CONFIG_PM_DEVICE -@@ -1112,6 +2178,7 @@ static int sx126x_pm_action(const struct device *dev, +@@ -1112,6 +2199,7 @@ static int sx126x_pm_action(const struct device *dev, static int sx126x_init(const struct device *dev) { struct sx126x_data *data = dev->data; @@ -1438,7 +1472,7 @@ index 30243ba5dc7..0cec01d84a9 100644 int ret; /* Initialize data structures */ -@@ -1121,9 +2188,26 @@ static int sx126x_init(const struct device *dev) +@@ -1121,9 +2209,26 @@ static int sx126x_init(const struct device *dev) k_msgq_init(&data->rx_msgq, (char *)&data->rx_result, sizeof(struct sx126x_rx_result), 1); k_work_init(&data->irq_work, sx126x_irq_work_handler);