1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge pull request #3434 from gebart/pr/ng_at86rf2xx-fixes-1

ng_at86rf2xx: Clean up state transitions and netdev implementation
This commit is contained in:
Thomas Eichinger 2015-07-22 17:55:58 +02:00
commit d10631adec
4 changed files with 108 additions and 66 deletions

View File

@ -346,14 +346,6 @@ void ng_at86rf2xx_set_max_retries(ng_at86rf2xx_t *dev, uint8_t max);
*/
void ng_at86rf2xx_set_option(ng_at86rf2xx_t *dev, uint16_t option, bool state);
/**
* @brief Get the given devices current internal state
*
* @param[in] dev device to get state of
* @return the current state of the given device
*/
uint8_t ng_at86rf2xx_get_state(ng_at86rf2xx_t *dev);
/**
* @brief Set the state of the given device (trigger a state change)
*
@ -362,6 +354,17 @@ uint8_t ng_at86rf2xx_get_state(ng_at86rf2xx_t *dev);
*/
void ng_at86rf2xx_set_state(ng_at86rf2xx_t *dev, uint8_t state);
/**
* @brief Reset the internal state machine to TRX_OFF mode.
*
* This will force a transition to TRX_OFF regardless of whether the transceiver
* is currently busy sending or receiving. This function is used to get back to
* a known state during driver initialization.
*
* @param[in] dev device to operate on
*/
void ng_at86rf2xx_reset_state_machine(ng_at86rf2xx_t *dev);
/**
* @brief Convenience function for simply sending data
*

View File

@ -61,6 +61,7 @@ int ng_at86rf2xx_init(ng_at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed,
dev->int_pin = int_pin;
dev->sleep_pin = sleep_pin;
dev->reset_pin = reset_pin;
dev->idle_state = NG_AT86RF2XX_STATE_TRX_OFF;
/* initialise SPI */
spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, spi_speed);
@ -92,10 +93,16 @@ void ng_at86rf2xx_reset(ng_at86rf2xx_t *dev)
eui64_t addr_long;
#endif
/* wake from sleep in case radio is sleeping */
gpio_clear(dev->sleep_pin);
/* trigger hardware reset */
gpio_clear(dev->reset_pin);
hwtimer_wait(HWTIMER_TICKS(RESET_DELAY));
gpio_set(dev->reset_pin);
/* Reset state machine to ensure a known state */
ng_at86rf2xx_reset_state_machine(dev);
/* reset options and sequence number */
dev->seq_nr = 0;
dev->options = 0;
@ -206,10 +213,13 @@ void ng_at86rf2xx_tx_prepare(ng_at86rf2xx_t *dev)
/* make sure ongoing transmissions are finished */
do {
state = ng_at86rf2xx_get_state(dev);
state = ng_at86rf2xx_get_status(dev);
}
while (state == NG_AT86RF2XX_STATE_BUSY_RX_AACK ||
state == NG_AT86RF2XX_STATE_BUSY_TX_ARET);
if (state != NG_AT86RF2XX_STATE_TX_ARET_ON) {
dev->idle_state = state;
}
while (state == NG_AT86RF2XX_STATE_BUSY_RX_AACK);
dev->idle_state = state;
ng_at86rf2xx_set_state(dev, NG_AT86RF2XX_STATE_TX_ARET_ON);
dev->frame_len = NG_IEEE802154_FCS_LEN;
}

View File

@ -138,38 +138,38 @@ ng_at86rf2xx_freq_t ng_at86rf2xx_get_freq(ng_at86rf2xx_t *dev)
void ng_at86rf2xx_set_freq(ng_at86rf2xx_t *dev, ng_at86rf2xx_freq_t freq)
{
uint8_t tmp1 = 0, tmp2 = 0;
tmp1 = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__TRX_CTRL_2);
tmp1 &= ~(NG_AT86RF2XX_TRX_CTRL_2_MASK__FREQ_MODE);
tmp2 = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__RF_CTRL_0);
uint8_t trx_ctrl2 = 0, rf_ctrl0 = 0;
trx_ctrl2 = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__TRX_CTRL_2);
trx_ctrl2 &= ~(NG_AT86RF2XX_TRX_CTRL_2_MASK__FREQ_MODE);
rf_ctrl0 = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__RF_CTRL_0);
/* Erase previous conf for GC_TX_OFFS */
tmp2 &= ~NG_AT86RF2XX_RF_CTRL_0_MASK__GC_TX_OFFS;
rf_ctrl0 &= ~NG_AT86RF2XX_RF_CTRL_0_MASK__GC_TX_OFFS;
if (freq == NG_AT86RF2XX_FREQ_915MHZ) {
dev->freq = NG_AT86RF2XX_FREQ_915MHZ;
/* settings used by Linux 4.0rc at86rf212b driver - BPSK-40*/
tmp1 |= NG_AT86RF2XX_TRX_CTRL_2_MASK__SUB_MODE
| NG_AT86RF2XX_TRX_CTRL_2_MASK__OQPSK_SCRAM_EN;
tmp2 |= NG_AT86RF2XX_RF_CTRL_0_GC_TX_OFFS__2DB;
trx_ctrl2 |= NG_AT86RF2XX_TRX_CTRL_2_MASK__SUB_MODE;
rf_ctrl0 |= NG_AT86RF2XX_RF_CTRL_0_GC_TX_OFFS__2DB;
if (dev->chan == 0) {
ng_at86rf2xx_set_chan(dev,NG_AT86RF2XX_DEFAULT_CHANNEL);
} else {
ng_at86rf2xx_set_chan(dev,dev->chan);
}
} else if (freq == NG_AT86RF2XX_FREQ_868MHZ) {
dev->freq = NG_AT86RF2XX_FREQ_868MHZ;
/* OQPSK-SIN-RC-100 IEEE802.15.4 for 868,3MHz */
tmp1 |= NG_AT86RF2XX_TRX_CTRL_2_MASK__BPSK_OQPSK;
tmp2 |= NG_AT86RF2XX_RF_CTRL_0_GC_TX_OFFS__1DB;
switch(freq) {
case NG_AT86RF2XX_FREQ_915MHZ:
if (dev->chan == 0) {
ng_at86rf2xx_set_chan(dev,NG_AT86RF2XX_DEFAULT_CHANNEL);
} else {
ng_at86rf2xx_set_chan(dev,dev->chan);
}
break;
/* Channel = 0 for 868MHz means 868.3MHz, only one available */
ng_at86rf2xx_set_chan(dev,0x00);
} else {
return;
case NG_AT86RF2XX_FREQ_868MHZ:
/* Channel = 0 for 868MHz means 868.3MHz, only one available */
ng_at86rf2xx_set_chan(dev,0x00);
break;
default:
DEBUG("ng_at86rf2xx: Trying to set unknown frequency 0x%lx\n",
(unsigned long) freq);
return;
}
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__TRX_CTRL_2, tmp1);
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__RF_CTRL_0, tmp2);
dev->freq = freq;
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__TRX_CTRL_2, trx_ctrl2);
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__RF_CTRL_0, rf_ctrl0);
}
#endif
@ -334,43 +334,68 @@ void ng_at86rf2xx_set_option(ng_at86rf2xx_t *dev, uint16_t option, bool state)
}
}
uint8_t ng_at86rf2xx_get_state(ng_at86rf2xx_t *dev)
{
uint8_t status = ng_at86rf2xx_get_status(dev);
return (status & 0x1f);
}
static inline void _set_state(ng_at86rf2xx_t *dev, uint8_t state)
{
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__TRX_STATE, state);
while (ng_at86rf2xx_get_state(dev) != state);
while (ng_at86rf2xx_get_status(dev) != state);
}
static inline void _force_trx_off(ng_at86rf2xx_t *dev)
{
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__TRX_STATE, NG_AT86RF2XX_TRX_STATE__FORCE_TRX_OFF);
while (ng_at86rf2xx_get_status(dev) != NG_AT86RF2XX_STATE_TRX_OFF);
}
void ng_at86rf2xx_set_state(ng_at86rf2xx_t *dev, uint8_t state)
{
uint8_t old_state = ng_at86rf2xx_get_state(dev);
uint8_t old_state = ng_at86rf2xx_get_status(dev);
if (state == old_state) {
return;
}
/* make sure there is no ongoing transmission */
/* make sure there is no ongoing transmission, or state transition already
* in progress */
while (old_state == NG_AT86RF2XX_STATE_BUSY_RX_AACK ||
old_state == NG_AT86RF2XX_STATE_BUSY_TX_ARET) {
old_state = ng_at86rf2xx_get_state(dev);
old_state == NG_AT86RF2XX_STATE_BUSY_TX_ARET ||
old_state == NG_AT86RF2XX_STATE_IN_PROGRESS) {
old_state = ng_at86rf2xx_get_status(dev);
}
/* we need to go via PLL_ON if we are moving between RX_AACK_ON <-> TX_ARET_ON */
if ((old_state == NG_AT86RF2XX_STATE_RX_AACK_ON &&
state == NG_AT86RF2XX_STATE_TX_ARET_ON) ||
(old_state == NG_AT86RF2XX_STATE_TX_ARET_ON &&
state == NG_AT86RF2XX_STATE_RX_AACK_ON)) {
_set_state(dev, NG_AT86RF2XX_STATE_PLL_ON);
}
/* check if we need to wake up from sleep mode */
if (old_state == NG_AT86RF2XX_STATE_SLEEP) {
else if (old_state == NG_AT86RF2XX_STATE_SLEEP) {
DEBUG("at86rf2xx: waking up from sleep mode\n");
gpio_clear(dev->sleep_pin);
while (ng_at86rf2xx_get_state(dev) != NG_AT86RF2XX_STATE_TRX_OFF);
while (ng_at86rf2xx_get_status(dev) != NG_AT86RF2XX_STATE_TRX_OFF);
}
/* go to neutral TRX_OFF state */
_set_state(dev, NG_AT86RF2XX_STATE_TRX_OFF);
if (state == NG_AT86RF2XX_STATE_RX_AACK_ON ||
state == NG_AT86RF2XX_STATE_TX_ARET_ON) {
_set_state(dev, state);
} else if (state == NG_AT86RF2XX_STATE_SLEEP) {
if (state == NG_AT86RF2XX_STATE_SLEEP) {
/* First go to TRX_OFF */
_force_trx_off(dev);
/* Go to SLEEP mode from TRX_OFF */
gpio_set(dev->sleep_pin);
while (ng_at86rf2xx_get_state(dev) != NG_AT86RF2XX_STATE_SLEEP);
} else {
_set_state(dev, state);
}
}
void ng_at86rf2xx_reset_state_machine(ng_at86rf2xx_t *dev)
{
uint8_t old_state;
/* Wake up */
gpio_clear(dev->sleep_pin);
/* Wait for any state transitions to complete before forcing TRX_OFF */
do {
old_state = ng_at86rf2xx_get_status(dev);
} while (old_state == NG_AT86RF2XX_STATE_IN_PROGRESS);
_force_trx_off(dev);
}

View File

@ -38,7 +38,7 @@ static size_t _make_data_frame_hdr(ng_at86rf2xx_t *dev, uint8_t *buf,
/* we are building a data frame here */
buf[0] = NG_IEEE802154_FCF_TYPE_DATA;
buf[1] = 0x88; /* use short src and dst addresses as starting point */
buf[1] = NG_IEEE802154_FCF_VERS_V1;
/* if AUTOACK is enabled, then we also expect ACKs for this packet */
if (!(hdr->flags & NG_NETIF_HDR_FLAGS_BROADCAST) &&
@ -55,16 +55,18 @@ static size_t _make_data_frame_hdr(ng_at86rf2xx_t *dev, uint8_t *buf,
/* fill in destination address */
if (hdr->flags &
(NG_NETIF_HDR_FLAGS_BROADCAST | NG_NETIF_HDR_FLAGS_MULTICAST)) {
buf[1] |= NG_IEEE802154_FCF_DST_ADDR_SHORT;
buf[pos++] = 0xff;
buf[pos++] = 0xff;
}
else if (hdr->dst_l2addr_len == 2) {
uint8_t *dst_addr = ng_netif_hdr_get_dst_addr(hdr);
buf[1] |= NG_IEEE802154_FCF_DST_ADDR_SHORT;
buf[pos++] = dst_addr[1];
buf[pos++] = dst_addr[0];
}
else if (hdr->dst_l2addr_len == 8) {
buf[1] |= 0x04;
buf[1] |= NG_IEEE802154_FCF_DST_ADDR_LONG;
uint8_t *dst_addr = ng_netif_hdr_get_dst_addr(hdr);
for (int i = 7; i >= 0; i--) {
buf[pos++] = dst_addr[i];
@ -85,11 +87,12 @@ static size_t _make_data_frame_hdr(ng_at86rf2xx_t *dev, uint8_t *buf,
/* fill in source address */
if (dev->options & NG_AT86RF2XX_OPT_SRC_ADDR_LONG) {
buf[1] |= 0x40;
buf[1] |= NG_IEEE802154_FCF_SRC_ADDR_LONG;
memcpy(&(buf[pos]), dev->addr_long, 8);
pos += 8;
}
else {
buf[1] |= NG_IEEE802154_FCF_SRC_ADDR_SHORT;
buf[pos++] = dev->addr_short[0];
buf[pos++] = dev->addr_short[1];
}
@ -153,7 +156,7 @@ static ng_pktsnip_t *_make_netif_hdr(uint8_t *mhr)
else if (tmp == NG_IEEE802154_FCF_SRC_ADDR_LONG) {
src_len = 8;
}
else if (tmp == 0) {
else if (tmp == NG_IEEE802154_FCF_SRC_ADDR_VOID) {
src_len = 0;
}
else {
@ -166,7 +169,7 @@ static ng_pktsnip_t *_make_netif_hdr(uint8_t *mhr)
else if (tmp == NG_IEEE802154_FCF_DST_ADDR_LONG) {
dst_len = 8;
}
else if (tmp == 0) {
else if (tmp == NG_IEEE802154_FCF_DST_ADDR_VOID) {
dst_len = 0;
}
else {
@ -337,7 +340,7 @@ static int _set_state(ng_at86rf2xx_t *dev, ng_netconf_state_t state)
ng_netconf_state_t _get_state(ng_at86rf2xx_t *dev)
{
switch (ng_at86rf2xx_get_state(dev)) {
switch (ng_at86rf2xx_get_status(dev)) {
case NG_AT86RF2XX_STATE_SLEEP:
return NETCONF_STATE_SLEEP;
case NG_AT86RF2XX_STATE_BUSY_RX_AACK:
@ -691,7 +694,8 @@ static void _isr_event(ng_netdev_t *device, uint32_t event_type)
/* read (consume) device status */
irq_mask = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__IRQ_STATUS);
state = ng_at86rf2xx_get_state(dev);
state = ng_at86rf2xx_get_status(dev);
if (irq_mask & NG_AT86RF2XX_IRQ_STATUS_MASK__RX_START) {
dev->event_cb(NETDEV_EVENT_RX_STARTED, NULL);
@ -706,11 +710,11 @@ static void _isr_event(ng_netdev_t *device, uint32_t event_type)
_receive_data(dev);
}
else if (state == NG_AT86RF2XX_STATE_TX_ARET_ON) {
ng_at86rf2xx_set_state(dev, dev->idle_state);
if (dev->event_cb && (dev->options & NG_AT86RF2XX_OPT_TELL_TX_END)) {
dev->event_cb(NETDEV_EVENT_TX_COMPLETE, NULL);
}
DEBUG("[ng_at86rf2xx] EVT - TX_END\n");
ng_at86rf2xx_set_state(dev, dev->idle_state);
}
}
}