diff --git a/drivers/at86rf2xx/at86rf2xx_getset.c b/drivers/at86rf2xx/at86rf2xx_getset.c index 8c70b1496dc323eb2f19244081a9069751689015..e93e5f74e966f384fbd53abd260df2512319590a 100644 --- a/drivers/at86rf2xx/at86rf2xx_getset.c +++ b/drivers/at86rf2xx/at86rf2xx_getset.c @@ -421,7 +421,16 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state) static inline void _set_state(at86rf2xx_t *dev, uint8_t state) { at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE, state); - while (at86rf2xx_get_status(dev) != state); + + /* To prevent a possible race condition when changing to + * RX_AACK_ON state the state doesn't get read back in that + * case. See discussion + * in https://github.com/RIOT-OS/RIOT/pull/5244 + */ + if (state != AT86RF2XX_STATE_RX_AACK_ON) { + while (at86rf2xx_get_status(dev) != state); + } + dev->state = state; } @@ -429,9 +438,6 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) { uint8_t old_state = at86rf2xx_get_status(dev); - if (state == old_state) { - return; - } /* make sure there is no ongoing transmission, or state transition already * in progress */ while (old_state == AT86RF2XX_STATE_BUSY_RX_AACK || @@ -440,6 +446,10 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) old_state = at86rf2xx_get_status(dev); } + if (state == old_state) { + return; + } + /* we need to go via PLL_ON if we are moving between RX_AACK_ON <-> TX_ARET_ON */ if ((old_state == AT86RF2XX_STATE_RX_AACK_ON && state == AT86RF2XX_STATE_TX_ARET_ON) ||