diff --git a/drivers/at86rf2xx/at86rf2xx_getset.c b/drivers/at86rf2xx/at86rf2xx_getset.c index e93e5f74e966f384fbd53abd260df2512319590a..761f9782520292836c2163d7b8067a1e6c8624e5 100644 --- a/drivers/at86rf2xx/at86rf2xx_getset.c +++ b/drivers/at86rf2xx/at86rf2xx_getset.c @@ -418,9 +418,19 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state) } } -static inline void _set_state(at86rf2xx_t *dev, uint8_t state) +/** + * @brief Internal function to change state + * @details For all cases but AT86RF2XX_STATE_FORCE_TRX_OFF state and + * cmd parameter are the same. + * + * @param dev device to operate on + * @param state target state + * @param cmd command to initiate state transition + */ + +static inline void _set_state(at86rf2xx_t *dev, uint8_t state, uint8_t cmd) { - at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE, state); + at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE, cmd); /* To prevent a possible race condition when changing to * RX_AACK_ON state the state doesn't get read back in that @@ -438,6 +448,15 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) { uint8_t old_state = at86rf2xx_get_status(dev); + if (state == old_state) { + return; + } + + if (state == AT86RF2XX_STATE_FORCE_TRX_OFF) { + _set_state(dev, AT86RF2XX_STATE_TRX_OFF, state); + return; + } + /* make sure there is no ongoing transmission, or state transition already * in progress */ while (old_state == AT86RF2XX_STATE_BUSY_RX_AACK || @@ -455,7 +474,7 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) state == AT86RF2XX_STATE_TX_ARET_ON) || (old_state == AT86RF2XX_STATE_TX_ARET_ON && state == AT86RF2XX_STATE_RX_AACK_ON)) { - _set_state(dev, AT86RF2XX_STATE_PLL_ON); + _set_state(dev, AT86RF2XX_STATE_PLL_ON, AT86RF2XX_STATE_PLL_ON); } /* check if we need to wake up from sleep mode */ else if (old_state == AT86RF2XX_STATE_SLEEP) { @@ -465,14 +484,14 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) if (state == AT86RF2XX_STATE_SLEEP) { /* First go to TRX_OFF */ - at86rf2xx_force_trx_off(dev); + at86rf2xx_set_state(dev, AT86RF2XX_STATE_FORCE_TRX_OFF); /* Discard all IRQ flags, framebuffer is lost anyway */ at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); /* Go to SLEEP mode from TRX_OFF */ gpio_set(dev->params.sleep_pin); dev->state = state; } else { - _set_state(dev, state); + _set_state(dev, state, state); } } @@ -487,5 +506,5 @@ void at86rf2xx_reset_state_machine(at86rf2xx_t *dev) old_state = at86rf2xx_get_status(dev); } while (old_state == AT86RF2XX_STATE_IN_PROGRESS); - at86rf2xx_force_trx_off(dev); + at86rf2xx_set_state(dev, AT86RF2XX_STATE_FORCE_TRX_OFF); } diff --git a/drivers/at86rf2xx/at86rf2xx_internal.c b/drivers/at86rf2xx/at86rf2xx_internal.c index 1ae45270ca330415ea63681f41a7f8a13d80ff3a..2c5a436aa58e6d91cb4a334aa372353219a6ed37 100644 --- a/drivers/at86rf2xx/at86rf2xx_internal.c +++ b/drivers/at86rf2xx/at86rf2xx_internal.c @@ -146,19 +146,10 @@ void at86rf2xx_hardware_reset(at86rf2xx_t *dev) void at86rf2xx_configure_phy(at86rf2xx_t *dev) { - /* make sure device is not sleeping */ - at86rf2xx_assert_awake(dev); - - uint8_t state; - - /* make sure ongoing transmissions are finished */ - do { - state = at86rf2xx_get_status(dev); - } - while ((state == AT86RF2XX_STATE_BUSY_TX_ARET) || (state == AT86RF2XX_STATE_BUSY_RX_AACK)); + uint8_t state = at86rf2xx_get_status(dev); /* we must be in TRX_OFF before changing the PHY configuration */ - at86rf2xx_force_trx_off(dev); + at86rf2xx_set_state(dev, AT86RF2XX_STATE_TRX_OFF); #ifdef MODULE_AT86RF212B /* The TX power register must be updated after changing the channel if diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c index dd5cfbc00e17172ab000366c0e90ae1057581801..56c6d9376c7c94a55298ff1c3129a22db20bc807 100644 --- a/drivers/at86rf2xx/at86rf2xx_netdev.c +++ b/drivers/at86rf2xx/at86rf2xx_netdev.c @@ -234,24 +234,18 @@ static int _get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len) /* getting these options doesn't require the transceiver to be responsive */ switch (opt) { case NETOPT_CHANNEL_PAGE: - if (max_len < sizeof(uint16_t)) { - return -EOVERFLOW; - } + assert(max_len >= sizeof(uint16_t)); ((uint8_t *)val)[1] = 0; ((uint8_t *)val)[0] = at86rf2xx_get_page(dev); return sizeof(uint16_t); case NETOPT_MAX_PACKET_SIZE: - if (max_len < sizeof(int16_t)) { - return -EOVERFLOW; - } + assert(max_len >= sizeof(int16_t)); *((uint16_t *)val) = AT86RF2XX_MAX_PKT_LENGTH - _MAX_MHR_OVERHEAD; return sizeof(uint16_t); case NETOPT_STATE: - if (max_len < sizeof(netopt_state_t)) { - return -EOVERFLOW; - } + assert(max_len >= sizeof(netopt_state_t)); *((netopt_state_t *)val) = _get_state(dev); return sizeof(netopt_state_t); @@ -321,43 +315,27 @@ static int _get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len) /* these options require the transceiver to be not sleeping*/ switch (opt) { case NETOPT_TX_POWER: - if (max_len < sizeof(int16_t)) { - res = -EOVERFLOW; - } - else { - *((uint16_t *)val) = at86rf2xx_get_txpower(dev); - res = sizeof(uint16_t); - } + assert(max_len >= sizeof(int16_t)); + *((uint16_t *)val) = at86rf2xx_get_txpower(dev); + res = sizeof(uint16_t); break; case NETOPT_RETRANS: - if (max_len < sizeof(uint8_t)) { - res = -EOVERFLOW; - } - else { - *((uint8_t *)val) = at86rf2xx_get_max_retries(dev); - res = sizeof(uint8_t); - } + assert(max_len >= sizeof(uint8_t)); + *((uint8_t *)val) = at86rf2xx_get_max_retries(dev); + res = sizeof(uint8_t); break; case NETOPT_CSMA_RETRIES: - if (max_len < sizeof(uint8_t)) { - res = -EOVERFLOW; - } - else { - *((uint8_t *)val) = at86rf2xx_get_csma_max_retries(dev); - res = sizeof(uint8_t); - } + assert(max_len >= sizeof(uint8_t)); + *((uint8_t *)val) = at86rf2xx_get_csma_max_retries(dev); + res = sizeof(uint8_t); break; case NETOPT_CCA_THRESHOLD: - if (max_len < sizeof(int8_t)) { - res = -EOVERFLOW; - } - else { - *((int8_t *)val) = at86rf2xx_get_cca_threshold(dev); - res = sizeof(int8_t); - } + assert(max_len >= sizeof(int8_t)); + *((int8_t *)val) = at86rf2xx_get_cca_threshold(dev); + res = sizeof(int8_t); break; default: @@ -389,94 +367,63 @@ static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len) switch (opt) { case NETOPT_ADDRESS: - if (len > sizeof(uint16_t)) { - res = -EOVERFLOW; - } - else { - at86rf2xx_set_addr_short(dev, *((uint16_t *)val)); - /* don't set res to set netdev2_ieee802154_t::short_addr */ - } + assert(len <= sizeof(uint16_t)); + at86rf2xx_set_addr_short(dev, *((uint16_t *)val)); + /* don't set res to set netdev2_ieee802154_t::short_addr */ break; - case NETOPT_ADDRESS_LONG: - if (len > sizeof(uint64_t)) { - res = -EOVERFLOW; - } - else { - at86rf2xx_set_addr_long(dev, *((uint64_t *)val)); - /* don't set res to set netdev2_ieee802154_t::long_addr */ - } + assert(len <= sizeof(uint64_t)); + at86rf2xx_set_addr_long(dev, *((uint64_t *)val)); + /* don't set res to set netdev2_ieee802154_t::long_addr */ break; - case NETOPT_NID: - if (len > sizeof(uint16_t)) { - res = -EOVERFLOW; - } - else { - at86rf2xx_set_pan(dev, *((uint16_t *)val)); - /* don't set res to set netdev2_ieee802154_t::pan */ - } + assert(len <= sizeof(uint16_t)); + at86rf2xx_set_pan(dev, *((uint16_t *)val)); + /* don't set res to set netdev2_ieee802154_t::pan */ break; - case NETOPT_CHANNEL: - if (len != sizeof(uint16_t)) { + assert(len != sizeof(uint8_t)); + uint8_t chan = ((uint8_t *)val)[0]; + if (chan < AT86RF2XX_MIN_CHANNEL || + chan > AT86RF2XX_MAX_CHANNEL) { res = -EINVAL; + break; } - else { - uint8_t chan = ((uint8_t *)val)[0]; - if ((chan < AT86RF2XX_MIN_CHANNEL) || - (chan > AT86RF2XX_MAX_CHANNEL)) { - res = -EINVAL; - break; - } - at86rf2xx_set_chan(dev, chan); - /* don't set res to set netdev2_ieee802154_t::chan */ - } + at86rf2xx_set_chan(dev, chan); + /* don't set res to set netdev2_ieee802154_t::chan */ break; case NETOPT_CHANNEL_PAGE: - if (len != sizeof(uint16_t)) { + assert(len != sizeof(uint8_t)); + uint8_t page = ((uint8_t *)val)[0]; +#ifdef MODULE_AT86RF212B + if ((page != 0) && (page != 2)) { res = -EINVAL; } else { - uint8_t page = ((uint8_t *)val)[0]; -#ifdef MODULE_AT86RF212B - if ((page != 0) && (page != 2)) { - res = -EINVAL; - } - else { - at86rf2xx_set_page(dev, page); - res = sizeof(uint16_t); - } + at86rf2xx_set_page(dev, page); + res = sizeof(uint8_t); + } #else - /* rf23x only supports page 0, no need to configure anything in the driver. */ - if (page != 0) { - res = -EINVAL; - } - else { - res = sizeof(uint16_t); - } -#endif + /* rf23x only supports page 0, no need to configure anything in the driver. */ + if (page != 0) { + res = -EINVAL; } + else { + res = sizeof(uint8_t); + } +#endif break; case NETOPT_TX_POWER: - if (len > sizeof(int16_t)) { - res = -EOVERFLOW; - } - else { - at86rf2xx_set_txpower(dev, *((int16_t *)val)); - res = sizeof(uint16_t); - } + assert(len <= sizeof(int16_t)); + at86rf2xx_set_txpower(dev, *((int16_t *)val)); + res = sizeof(uint16_t); break; case NETOPT_STATE: - if (len > sizeof(netopt_state_t)) { - res = -EOVERFLOW; - } - else { - res = _set_state(dev, *((netopt_state_t *)val)); - } + assert(len <= sizeof(netopt_state_t)); + res = _set_state(dev, *((netopt_state_t *)val)); break; case NETOPT_AUTOACK: @@ -486,13 +433,9 @@ static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len) break; case NETOPT_RETRANS: - if (len > sizeof(uint8_t)) { - res = -EOVERFLOW; - } - else { - at86rf2xx_set_max_retries(dev, *((uint8_t *)val)); - res = sizeof(uint8_t); - } + assert(len <= sizeof(uint8_t)); + at86rf2xx_set_max_retries(dev, *((uint8_t *)val)); + res = sizeof(uint8_t); break; case NETOPT_PRELOADING: @@ -538,25 +481,22 @@ static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len) break; case NETOPT_CSMA_RETRIES: - if ((len > sizeof(uint8_t)) || - (*((uint8_t *)val) > 5)) { - res = -EOVERFLOW; + assert(len <= sizeof(uint8_t)); + if( !(dev->netdev.flags & AT86RF2XX_OPT_CSMA || + (*((uint8_t *)val) > 5)) ) { + /* If CSMA is disabled, don't allow setting retries */ + res = -EINVAL; } - else if (dev->netdev.flags & AT86RF2XX_OPT_CSMA) { - /* only set if CSMA is enabled */ + else { at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val)); res = sizeof(uint8_t); } break; case NETOPT_CCA_THRESHOLD: - if (len > sizeof(int8_t)) { - res = -EOVERFLOW; - } - else { - at86rf2xx_set_cca_threshold(dev, *((int8_t *)val)); - res = sizeof(int8_t); - } + assert(len <= sizeof(int8_t)); + at86rf2xx_set_cca_threshold(dev, *((int8_t *)val)); + res = sizeof(int8_t); break; default: diff --git a/drivers/at86rf2xx/include/at86rf2xx_internal.h b/drivers/at86rf2xx/include/at86rf2xx_internal.h index ef65570c4911802ca9105415f9db202e8cdbeae8..0979285c07de352f57956ba58134102f7b85d535 100644 --- a/drivers/at86rf2xx/include/at86rf2xx_internal.h +++ b/drivers/at86rf2xx/include/at86rf2xx_internal.h @@ -125,13 +125,6 @@ void at86rf2xx_fb_read(const at86rf2xx_t *dev, */ void at86rf2xx_fb_stop(const at86rf2xx_t *dev); -/** - * @brief Cancel ongoing transactions and switch to TRX_OFF state - * - * @param[in] dev device to manipulate - */ -void at86rf2xx_force_trx_off(const at86rf2xx_t *dev); - /** * @brief Convenience function for reading the status of the given device * diff --git a/drivers/include/at86rf2xx.h b/drivers/include/at86rf2xx.h index 2f2696fd6d66ae8292c33b703af3727156341d10..627e7d636807f765242414a007575a0f741d7f53 100644 --- a/drivers/include/at86rf2xx.h +++ b/drivers/include/at86rf2xx.h @@ -95,14 +95,15 @@ extern "C" { * @brief Flags for device internal states (see datasheet) * @{ */ -#define AT86RF2XX_STATE_TRX_OFF (0x08) /**< idle */ -#define AT86RF2XX_STATE_PLL_ON (0x09) /**< ready to transmit */ -#define AT86RF2XX_STATE_SLEEP (0x0f) /**< sleep mode */ -#define AT86RF2XX_STATE_BUSY_RX_AACK (0x11) /**< busy receiving data */ -#define AT86RF2XX_STATE_BUSY_TX_ARET (0x12) /**< busy transmitting data */ -#define AT86RF2XX_STATE_RX_AACK_ON (0x16) /**< wait for incoming data */ -#define AT86RF2XX_STATE_TX_ARET_ON (0x19) /**< ready for sending data */ -#define AT86RF2XX_STATE_IN_PROGRESS (0x1f) /**< ongoing state conversion */ +#define AT86RF2XX_STATE_FORCE_TRX_OFF (0x03) /**< force transition to idle */ +#define AT86RF2XX_STATE_TRX_OFF (0x08) /**< idle */ +#define AT86RF2XX_STATE_PLL_ON (0x09) /**< ready to transmit */ +#define AT86RF2XX_STATE_SLEEP (0x0f) /**< sleep mode */ +#define AT86RF2XX_STATE_BUSY_RX_AACK (0x11) /**< busy receiving data */ +#define AT86RF2XX_STATE_BUSY_TX_ARET (0x12) /**< busy transmitting data */ +#define AT86RF2XX_STATE_RX_AACK_ON (0x16) /**< wait for incoming data */ +#define AT86RF2XX_STATE_TX_ARET_ON (0x19) /**< ready for sending data */ +#define AT86RF2XX_STATE_IN_PROGRESS (0x1f) /**< ongoing state conversion */ /** @} */ /**