drivers/at86rf215: fix reset after deep sleep

When the radio is in DEEP SLEEP, reading the state register will return 0.
This makes the reset routine abort early even though the device is connected
and still waking up.

Instead, just add a timeout to the polling of the WAKEUP IRQ bit.
In practise it has shown that the loop will be taken two times on 'normal'
reset and four times when the radio was in DEEP SLEEP.

Polling 255 times sure does not hurt.

To reproduce the issue, put both interfaces into SLEEP mode,
then reboot the module:

    ifconfig 7 set state sleep
    ifconfig 8 set state sleep
    reboot
This commit is contained in:
Benjamin Valentin 2020-03-29 19:44:40 +02:00
parent 7e85081ddc
commit 611f4161d6

View File

@ -53,22 +53,22 @@ int at86rf215_hardware_reset(at86rf215_t *dev)
gpio_set(dev->params.reset_pin); gpio_set(dev->params.reset_pin);
xtimer_usleep(AT86RF215_RESET_DELAY_US); xtimer_usleep(AT86RF215_RESET_DELAY_US);
uint8_t state = _get_reg_with_lock(dev, dev->RF->RG_STATE) & STATE_STATE_MASK;
if (state != RF_STATE_TRXOFF && state != RF_STATE_RESET) {
spi_release(SPIDEV);
return -ENODEV;
}
/* While the device is in RESET / DEEP SLEEP, all registers /* While the device is in RESET / DEEP SLEEP, all registers
but STATE will read 0xFF. but STATE will read 0xFF.
WAKEUP IRQ signals that the device is ready. */ WAKEUP IRQ signals that the device is ready. */
state = 0; uint8_t state = 0;
while (state == 0xFF || !(state & IRQS_WAKEUP_MASK)) { uint8_t tries = 255;
while (--tries && (state == 0xFF || !(state & IRQS_WAKEUP_MASK))) {
state = _get_reg_with_lock(dev, dev->RF->RG_IRQS); state = _get_reg_with_lock(dev, dev->RF->RG_IRQS);
} }
spi_release(SPIDEV); spi_release(SPIDEV);
/* no device connected */
if (!tries) {
return -ENODEV;
}
/* clear interrupts */ /* clear interrupts */
at86rf215_reg_read(dev, RG_RF09_IRQS); at86rf215_reg_read(dev, RG_RF09_IRQS);
at86rf215_reg_read(dev, RG_RF24_IRQS); at86rf215_reg_read(dev, RG_RF24_IRQS);