drivers/sx127x: Add RX Timeout support

This commit adds support to fix RX timeout for SX127x, it is done
leaving the RX mode, entering in stanby mode and returning to RX
mode. It is enough to fix the AFC and get communication working
again.

Signed-off-by: Alan C. Assis <acassis@gmail.com>
This commit is contained in:
Alan Carvalho de Assis
2026-01-04 11:10:50 -03:00
committed by Alan C. Assis
parent 667165db46
commit cce61ea287
2 changed files with 84 additions and 1 deletions

View File

@@ -50,6 +50,18 @@ config LPWAN_SX127X_RXFIFO_DATA_LEN
int "SX127X RX FIFO data length"
default 64
config LPWAN_SX127X_RX_TIMEOUT
int "SX127X RX Timeout in Milliseconds"
default 10000
---help---
If device stopped receiving data for more than
LPWAN_SX127X_RX_TIMEOUT milliseconds it means the
frequency drift is too high that AFC failed to fix
the reception frequency. So if we leave the RX mode,
entering in standby and returning will clear the
AFC and fix the communication again.
If you don't want to use RX timeout set it to -1.
endif #LPWAN_SX127X_RXSUPPORT
config LPWAN_SX127X_TXSUPPORT

View File

@@ -316,10 +316,12 @@ struct sx127x_dev_s
bool pa_force; /* Force PA BOOST pin select */
#endif
#ifdef CONFIG_LPWAN_SX127X_RXSUPPORT
uint32_t rx_timeout; /* RX timeout (not supported) */
uint32_t rx_timeout; /* RX timeout in milliseconds */
uint16_t rx_fifo_len; /* Number of bytes stored in fifo */
uint16_t nxt_read; /* Next read index */
uint16_t nxt_write; /* Next write index */
clock_t last_rx_tick; /* Ticks since last RX event to detect timeout */
struct work_s rx_watchdog; /* Watchdog to detect timeout */
/* Circular RX packet buffer */
@@ -1276,6 +1278,50 @@ errout:
#endif
}
/****************************************************************************
* Name: sx127x_rx_watchdog
*
* Description:
* Watchdog to detect SX127x RX communication stall
*
****************************************************************************/
#ifdef CONFIG_LPWAN_SX127X_RXSUPPORT
static void sx127x_rx_watchdog(FAR void *arg)
{
FAR struct sx127x_dev_s *dev = (FAR struct sx127x_dev_s *)arg;
clock_t now = clock_systime_ticks();
if (dev->opmode == SX127X_OPMODE_RX &&
(now - dev->last_rx_tick) > MSEC2TICK(dev->rx_timeout))
{
wlerr("RX stall detected, restarting RX\n");
/* Leave RX mode to clear AFC + bit sync */
sx127x_opmode_set(dev, SX127X_OPMODE_STANDBY);
/* datasheet-safe delay */
nxsched_usleep(100);
/* Re-enter RX */
sx127x_opmode_set(dev, SX127X_OPMODE_RX);
/* Avoid using old RX tick, otherwise it always will fail */
dev->last_rx_tick = now;
}
/* Reschedule watchdog */
work_queue(LPWORK, &dev->rx_watchdog,
sx127x_rx_watchdog, dev,
MSEC2TICK(dev->rx_timeout));
}
#endif
/****************************************************************************
* Name: sx127x_lora_isr0_process
*
@@ -1471,6 +1517,21 @@ static int sx127x_fskook_isr0_process(FAR struct sx127x_dev_s *dev)
ret = sx127x_fskook_rxhandle(dev);
if (ret > 0)
{
/* Should we take care of RX timeout? */
if (dev->rx_timeout > 0)
{
/* Keep a track of last RX time to detect timeout */
dev->last_rx_tick = clock_systime_ticks();
/* Prepare the work queue to take care of RX timeout */
work_queue(LPWORK, &dev->rx_watchdog,
sx127x_rx_watchdog, dev,
MSEC2TICK(dev->rx_timeout));
}
if (dev->pfd)
{
/* Data available for input */
@@ -4204,6 +4265,12 @@ static int sx127x_deinit(FAR struct sx127x_dev_s *dev)
{
wlinfo("Deinit sx127x dev\n");
#ifdef CONFIG_LPWAN_SX127X_RXSUPPORT
/* Cancel any running watchdog */
work_cancel(LPWORK, &dev->rx_watchdog);
#endif
/* Enter SLEEP mode */
sx127x_opmode_set(dev, SX127X_OPMODE_SLEEP);
@@ -4559,6 +4626,7 @@ static int sx127x_unregister(FAR struct sx127x_dev_s *dev)
nxsem_destroy(&dev->tx_sem);
#endif
#ifdef CONFIG_LPWAN_SX127X_RXSUPPORT
work_cancel(LPWORK, &dev->rx_watchdog);
nxsem_destroy(&dev->rx_sem);
nxmutex_destroy(&dev->rx_buffer_lock);
#endif
@@ -4614,6 +4682,9 @@ int sx127x_register(FAR struct spi_dev_s *spi,
dev->crcon = CONFIG_LPWAN_SX127X_CRCON;
#ifdef CONFIG_LPWAN_SX127X_FSKOOK
dev->fskook.fixlen = false;
# ifdef CONFIG_LPWAN_SX127X_RXSUPPORT
dev->rx_timeout = CONFIG_LPWAN_SX127X_RX_TIMEOUT;
# endif
#endif
#ifdef CONFIG_LPWAN_SX127X_LORA
dev->lora.invert_iq = false;