diff --git a/zephcore/patches/zephyr/0003-lora-sx126x-native.patch b/zephcore/patches/zephyr/0003-lora-sx126x-native.patch index bfeb033..99298a9 100644 --- a/zephcore/patches/zephyr/0003-lora-sx126x-native.patch +++ b/zephcore/patches/zephyr/0003-lora-sx126x-native.patch @@ -577,7 +577,7 @@ Regenerate with: appended to this preamble. diff --git a/drivers/lora/native/sx126x/sx126x.c b/drivers/lora/native/sx126x/sx126x.c -index 30243ba5dc7..a2c57493caf 100644 +index 30243ba5dc7..d512fb59afc 100644 --- a/drivers/lora/native/sx126x/sx126x.c +++ b/drivers/lora/native/sx126x/sx126x.c @@ -6,72 +6,236 @@ @@ -1787,7 +1787,7 @@ index 30243ba5dc7..a2c57493caf 100644 sx126x_set_sleep(dev); if (data->tx_async_signal != NULL) { -@@ -630,13 +1548,80 @@ static void sx126x_irq_work_handler(struct k_work *work) +@@ -630,13 +1548,97 @@ static void sx126x_irq_work_handler(struct k_work *work) } if (irq_status & SX126X_IRQ_RX_DONE) { @@ -1817,7 +1817,24 @@ index 30243ba5dc7..a2c57493caf 100644 + * negative CAD_RX exits to STDBY_RC exactly like CAD_ONLY, so + * there is nothing to track. */ + if (data->cad_exit_rx && detected) { ++ /* CAD_ONLY has left the chip in STDBY_RC (DS 13.1.8), so ++ * arm the follow-on Rx ourselves with an explicit ++ * SetRx(timeout). That re-invokes and re-programs the RTC, ++ * which is exactly what cadTimeout fails to do after ++ * SetRxDutyCycle -- so the terminal IRQ (RX_DONE, CRC_ERR or ++ * RX_TX_TIMEOUT) is genuinely guaranteed here, duty cycle or ++ * not. Bound is max-length-packet airtime +25% +100 ms, the ++ * same figure cadTimeout used, so a real packet still ++ * completes inside it. Cost is the ~1 ms of SPI between ++ * CAD_DONE and Rx, well inside the (P-8)-symbol preamble ++ * budget the probe already spends. */ ++ uint8_t rxbuf[3]; ++ uint32_t tmo = SX126X_MS_TO_TIMEOUT( ++ sx126x_max_payload_ms(data)); ++ ++ sys_put_be24(tmo & 0xFFFFFFU, rxbuf); + atomic_set(&data->cad_rx_state, SX126X_CAD_RX_ARMED); ++ sx126x_hal_write_cmd(dev, SX126X_CMD_SET_RX, rxbuf, 3); + } + + if (data->cad_cb) { @@ -1868,7 +1885,7 @@ index 30243ba5dc7..a2c57493caf 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); -@@ -648,6 +1633,7 @@ static int sx126x_lora_config(const struct device *dev, +@@ -648,6 +1650,7 @@ static int sx126x_lora_config(const struct device *dev, { struct sx126x_data *data = dev->data; const struct sx126x_hal_config *hal_config = dev->config; @@ -1876,11 +1893,14 @@ index 30243ba5dc7..a2c57493caf 100644 bool ldro; int ret; -@@ -679,25 +1665,45 @@ static int sx126x_lora_config(const struct device *dev, +@@ -679,25 +1682,45 @@ static int sx126x_lora_config(const struct device *dev, goto out; } - /* Configure PA and TX power based on chip variant and frequency */ +- ret = sx126x_hal_configure_tx_params(dev, config->tx_power, +- config->frequency, +- SX126X_RAMP_200_US); + /* Install the band's RSSI/AGC calibration (DS Sec 6.1.6) before the + * RX gain write below, which consumes the AgcSensiAdjust this caches. + * Re-run on every config so a runtime frequency change switches bands @@ -1891,9 +1911,8 @@ index 30243ba5dc7..a2c57493caf 100644 + } + + /* Configure PA and TX power based on chip variant and frequency */ - ret = sx126x_hal_configure_tx_params(dev, config->tx_power, - config->frequency, -- SX126X_RAMP_200_US); ++ ret = sx126x_hal_configure_tx_params(dev, config->tx_power, ++ config->frequency, + SX126X_TX_RAMP_TIME); if (ret < 0) { goto out; @@ -1925,7 +1944,7 @@ index 30243ba5dc7..a2c57493caf 100644 /* Set sync word */ ret = sx126x_set_sync_word(dev, config->public_network); if (ret < 0) { -@@ -721,6 +1727,10 @@ out: +@@ -721,6 +1744,10 @@ out: return ret; } @@ -1936,7 +1955,7 @@ index 30243ba5dc7..a2c57493caf 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 +1748,27 @@ static int sx126x_lora_send_async(const struct device *dev, +@@ -738,11 +1765,27 @@ static int sx126x_lora_send_async(const struct device *dev, return -EINVAL; } @@ -1966,7 +1985,7 @@ index 30243ba5dc7..a2c57493caf 100644 k_mutex_lock(&data->lock, K_FOREVER); ret = sx126x_ensure_ready(dev); -@@ -752,6 +1778,59 @@ static int sx126x_lora_send_async(const struct device *dev, +@@ -752,6 +1795,59 @@ static int sx126x_lora_send_async(const struct device *dev, return ret; } @@ -2026,7 +2045,7 @@ index 30243ba5dc7..a2c57493caf 100644 data->tx_async_signal = async; k_msgq_purge(&data->tx_msgq); -@@ -777,8 +1856,99 @@ static int sx126x_lora_send_async(const struct device *dev, +@@ -777,8 +1873,99 @@ static int sx126x_lora_send_async(const struct device *dev, /* Enable antenna and set TX path */ sx126x_set_rf_path(dev, true, true); @@ -2128,7 +2147,7 @@ index 30243ba5dc7..a2c57493caf 100644 if (ret < 0) { goto out_error; } -@@ -847,6 +2017,8 @@ static int sx126x_lora_recv(const struct device *dev, uint8_t *data_buf, +@@ -847,6 +2034,8 @@ static int sx126x_lora_recv(const struct device *dev, uint8_t *data_buf, } data->rx_cb = NULL; @@ -2137,7 +2156,7 @@ index 30243ba5dc7..a2c57493caf 100644 k_msgq_purge(&data->rx_msgq); /* Set packet parameters for variable length reception */ -@@ -918,6 +2090,8 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -918,6 +2107,8 @@ static int sx126x_lora_recv_async(const struct device *dev, /* Stop async reception */ data->rx_cb = NULL; data->rx_cb_user_data = NULL; @@ -2146,7 +2165,7 @@ index 30243ba5dc7..a2c57493caf 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 +2106,19 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -932,6 +2123,19 @@ static int sx126x_lora_recv_async(const struct device *dev, return -EINVAL; } @@ -2166,7 +2185,7 @@ index 30243ba5dc7..a2c57493caf 100644 if (!atomic_cas(&data->state, SX126X_REST_STATE, SX126X_STATE_RX)) { LOG_ERR("Busy"); k_mutex_unlock(&data->lock); -@@ -945,8 +2132,18 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -945,8 +2149,18 @@ static int sx126x_lora_recv_async(const struct device *dev, return ret; } @@ -2185,7 +2204,7 @@ index 30243ba5dc7..a2c57493caf 100644 /* Set packet parameters */ ret = sx126x_set_packet_params(dev, -@@ -959,6 +2156,7 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -959,6 +2173,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; @@ -2193,7 +2212,7 @@ index 30243ba5dc7..a2c57493caf 100644 sx126x_set_sleep(dev); k_mutex_unlock(&data->lock); return ret; -@@ -971,11 +2169,21 @@ static int sx126x_lora_recv_async(const struct device *dev, +@@ -971,11 +2186,21 @@ static int sx126x_lora_recv_async(const struct device *dev, ret = sx126x_set_rx(dev, 0); if (ret < 0) { data->rx_cb = NULL; @@ -2215,7 +2234,7 @@ index 30243ba5dc7..a2c57493caf 100644 k_mutex_unlock(&data->lock); return 0; } -@@ -993,7 +2201,9 @@ static uint32_t sx126x_lora_airtime(const struct device *dev, uint32_t data_len) +@@ -993,7 +2218,9 @@ static uint32_t sx126x_lora_airtime(const struct device *dev, uint32_t data_len) } /* Calculate symbol time in microseconds */ @@ -2226,7 +2245,7 @@ index 30243ba5dc7..a2c57493caf 100644 sf = data->config.datarate; /* Symbol time = 2^SF / BW (seconds) */ -@@ -1051,7 +2261,7 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency, +@@ -1051,7 +2278,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, @@ -2235,7 +2254,7 @@ index 30243ba5dc7..a2c57493caf 100644 if (ret < 0) { sx126x_set_sleep(dev); k_mutex_unlock(&data->lock); -@@ -1083,14 +2293,1067 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency, +@@ -1083,14 +2310,1076 @@ static int sx126x_lora_test_cw(const struct device *dev, uint32_t frequency, return 0; } @@ -2837,13 +2856,22 @@ index 30243ba5dc7..a2c57493caf 100644 + * It is a chip-side deadline that always raises RX_TX_TIMEOUT, which is + * what lets the outcome be *observed* rather than polled for. */ + uint8_t buf[7]; -+ uint32_t cad_timeout = data->cad_exit_rx -+ ? SX126X_MS_TO_TIMEOUT(sx126x_max_payload_ms(data)) : 0U; ++ /* Always CAD_ONLY on the wire. cadTimeout is NOT honoured once ++ * SetRxDutyCycle has run -- the DS command table says that command ++ * "stores values of RTC setup for listen mode", and errata 15.3 notes a ++ * stale RTC misbehaves in "any subsequent mode where the RTC isn't ++ * re-invoked, and therefore reset and re-programmed". A CAD_RX exit ++ * does not re-program it, so on a duty-cycled node the chip entered Rx ++ * unbounded and no terminal IRQ ever arrived (measured: GetStatus 0x52 ++ * = RX, IRQ register 0x0000, long past even a 500 ms cadTimeout). ++ * The probe therefore arms its Rx explicitly after CAD_DONE instead -- ++ * see the cad_exit_rx branch in the DIO1 work handler. */ ++ uint32_t cad_timeout = 0U; + + buf[0] = symb_nb; + buf[1] = detect_peak; + buf[2] = mc->cad.detection_minimum ? mc->cad.detection_minimum : 10; -+ buf[3] = data->cad_exit_rx ? 0x01 : 0x00; /* CAD_RX : CAD_ONLY */ ++ buf[3] = 0x00; /* CAD_ONLY -- see the cad_timeout note above */ + sys_put_be24(cad_timeout & 0xFFFFFFU, &buf[4]); + + ret = sx126x_hal_write_cmd(dev, SX126X_CMD_SET_CAD_PARAMS, buf, 7); @@ -3310,7 +3338,7 @@ index 30243ba5dc7..a2c57493caf 100644 }; #ifdef CONFIG_PM_DEVICE -@@ -1112,6 +3375,7 @@ static int sx126x_pm_action(const struct device *dev, +@@ -1112,6 +3401,7 @@ static int sx126x_pm_action(const struct device *dev, static int sx126x_init(const struct device *dev) { struct sx126x_data *data = dev->data; @@ -3318,7 +3346,7 @@ index 30243ba5dc7..a2c57493caf 100644 int ret; /* Initialize data structures */ -@@ -1121,9 +3385,33 @@ static int sx126x_init(const struct device *dev) +@@ -1121,9 +3411,33 @@ 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); @@ -3352,7 +3380,7 @@ index 30243ba5dc7..a2c57493caf 100644 /* Initialize HAL */ ret = sx126x_hal_init(dev); -@@ -1185,6 +3473,8 @@ static int sx126x_init(const struct device *dev) +@@ -1185,6 +3499,8 @@ static int sx126x_init(const struct device *dev) {0}), \ .rx_enable = GPIO_DT_SPEC_INST_GET_OR(inst, rx_enable_gpios, \ {0}), \ @@ -3361,7 +3389,7 @@ index 30243ba5dc7..a2c57493caf 100644 .dio2_tx_enable = DT_INST_PROP(inst, dio2_tx_enable), \ .dio3_tcxo_enable = DT_INST_NODE_HAS_PROP(inst, dio3_tcxo_voltage), \ .dio3_tcxo_voltage = DT_INST_PROP_OR(inst, dio3_tcxo_voltage, 0), \ -@@ -1239,6 +3529,8 @@ DT_INST_FOREACH_STATUS_OKAY_VARGS(SX126X_INIT, true) +@@ -1239,6 +3555,8 @@ DT_INST_FOREACH_STATUS_OKAY_VARGS(SX126X_INIT, true) {0}), \ .rx_enable = GPIO_DT_SPEC_INST_GET_OR(inst, rx_enable_gpios, \ {0}), \