lora: detect failed transmissions

Detect failed transmissions using `lora_send` by only waiting for some
multiple of the actual on-air time before giving up.

We use this instead of the inbuilt TxTimeout functionality because the
value of this timeout is set by `lora_configure`, and therefore doesn't
change with different packet lengths. This is a limitation of the
underlying `RadioSend` function, not the Zephyr driver.

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
Jordan Yates 2021-06-30 13:40:17 +10:00 committed by Christopher Friedt
parent 93b4dbcc19
commit 3cec3ac2a4
1 changed files with 36 additions and 7 deletions

View File

@ -32,6 +32,7 @@ struct sx12xx_rx_params {
static struct sx12xx_data {
struct k_poll_signal *operation_done;
RadioEvents_t events;
struct lora_modem_config tx_cfg;
atomic_t modem_usage;
struct sx12xx_rx_params rx_params;
} dev_data;
@ -144,11 +145,11 @@ static void sx12xx_ev_tx_done(void)
{
struct k_poll_signal *sig = dev_data.operation_done;
modem_release(&dev_data);
/* Raise signal if provided */
if (sig) {
k_poll_signal_raise(sig, 0);
if (modem_release(&dev_data)) {
/* Raise signal if provided */
if (sig) {
k_poll_signal_raise(sig, 0);
}
}
}
@ -160,16 +161,41 @@ int sx12xx_lora_send(const struct device *dev, uint8_t *data,
K_POLL_TYPE_SIGNAL,
K_POLL_MODE_NOTIFY_ONLY,
&done);
uint32_t air_time;
int ret;
/* Validate that we have a TX configuration */
if (!dev_data.tx_cfg.frequency) {
return -EINVAL;
}
ret = sx12xx_lora_send_async(dev, data, data_len, &done);
if (ret < 0) {
return ret;
}
/* Wait for transmission to complete */
k_poll(&evt, 1, K_FOREVER);
/* Calculate expected airtime of the packet */
air_time = Radio.TimeOnAir(MODEM_LORA,
dev_data.tx_cfg.bandwidth,
dev_data.tx_cfg.datarate,
dev_data.tx_cfg.coding_rate,
dev_data.tx_cfg.preamble_len,
0, data_len, true);
LOG_DBG("Expected air time of %d bytes = %dms", data_len, air_time);
/* Wait for the packet to finish transmitting.
* Use twice the tx duration to ensure that we are actually detecting
* a failed transmission, and not some minor timing variation between
* modem and driver.
*/
ret = k_poll(&evt, 1, K_MSEC(2 * air_time));
if (ret < 0) {
LOG_ERR("Packet transmission failed!");
if (!modem_release(&dev_data)) {
/* TX done interrupt is currently running */
k_poll(&evt, 1, K_FOREVER);
}
}
return 0;
}
@ -247,6 +273,9 @@ int sx12xx_lora_config(const struct device *dev,
Radio.SetChannel(config->frequency);
if (config->tx) {
/* Store TX config locally for airtime calculations */
memcpy(&dev_data.tx_cfg, config, sizeof(dev_data.tx_cfg));
/* Configure radio driver */
Radio.SetTxConfig(MODEM_LORA, config->tx_power, 0,
config->bandwidth, config->datarate,
config->coding_rate, config->preamble_len,