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:
commit
d10631adec
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user