mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 06:23:53 +01:00
Merge pull request #12728 from bergzand/pr/at86rf2xx/fix_recv_before_send
at86rf2xx: fix receive before send detection
This commit is contained in:
commit
16ab89bf28
@ -627,6 +627,51 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void _isr_send_complete(at86rf2xx_t *dev, uint8_t trac_status)
|
||||
{
|
||||
netdev_t *netdev = &dev->netdev.netdev;
|
||||
/* Only radios with the XAH_CTRL_2 register support frame retry reporting */
|
||||
#if AT86RF2XX_HAVE_RETRIES
|
||||
dev->tx_retries = (at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_2)
|
||||
& AT86RF2XX_XAH_CTRL_2__ARET_FRAME_RETRIES_MASK) >>
|
||||
AT86RF2XX_XAH_CTRL_2__ARET_FRAME_RETRIES_OFFSET;
|
||||
#endif
|
||||
|
||||
DEBUG("[at86rf2xx] EVT - TX_END\n");
|
||||
|
||||
if (netdev->event_callback && (dev->flags & AT86RF2XX_OPT_TELL_TX_END)) {
|
||||
switch (trac_status) {
|
||||
#ifdef MODULE_OPENTHREAD
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
|
||||
DEBUG("[at86rf2xx] TX SUCCESS\n");
|
||||
break;
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE_DATA_PENDING);
|
||||
DEBUG("[at86rf2xx] TX SUCCESS DATA PENDING\n");
|
||||
break;
|
||||
#else
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS:
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
|
||||
DEBUG("[at86rf2xx] TX SUCCESS\n");
|
||||
break;
|
||||
#endif
|
||||
case AT86RF2XX_TRX_STATE__TRAC_NO_ACK:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_NOACK);
|
||||
DEBUG("[at86rf2xx] TX NO_ACK\n");
|
||||
break;
|
||||
case AT86RF2XX_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_MEDIUM_BUSY);
|
||||
DEBUG("[at86rf2xx] TX_CHANNEL_ACCESS_FAILURE\n");
|
||||
break;
|
||||
default:
|
||||
DEBUG("[at86rf2xx] Unhandled TRAC_STATUS: %d\n",
|
||||
trac_status >> 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _isr(netdev_t *netdev)
|
||||
{
|
||||
at86rf2xx_t *dev = (at86rf2xx_t *) netdev;
|
||||
@ -667,54 +712,28 @@ static void _isr(netdev_t *netdev)
|
||||
}
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
|
||||
}
|
||||
else if ((state == AT86RF2XX_STATE_TX_ARET_ON)
|
||||
|| (state == AT86RF2XX_STATE_BUSY_TX_ARET)) {
|
||||
else if (state == AT86RF2XX_STATE_TX_ARET_ON) {
|
||||
/* check for more pending TX calls and return to idle state if
|
||||
* there are none */
|
||||
assert(dev->pending_tx != 0);
|
||||
if ((--dev->pending_tx) == 0) {
|
||||
at86rf2xx_set_state(dev, dev->idle_state);
|
||||
DEBUG("[at86rf2xx] return to idle state 0x%x\n", dev->idle_state);
|
||||
}
|
||||
/* Only radios with the XAH_CTRL_2 register support frame retry reporting */
|
||||
#if AT86RF2XX_HAVE_RETRIES
|
||||
dev->tx_retries = (at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_2)
|
||||
& AT86RF2XX_XAH_CTRL_2__ARET_FRAME_RETRIES_MASK) >>
|
||||
AT86RF2XX_XAH_CTRL_2__ARET_FRAME_RETRIES_OFFSET;
|
||||
#endif
|
||||
|
||||
DEBUG("[at86rf2xx] EVT - TX_END\n");
|
||||
|
||||
if (netdev->event_callback && (dev->flags & AT86RF2XX_OPT_TELL_TX_END)) {
|
||||
switch (trac_status) {
|
||||
#ifdef MODULE_OPENTHREAD
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
|
||||
DEBUG("[at86rf2xx] TX SUCCESS\n");
|
||||
break;
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE_DATA_PENDING);
|
||||
DEBUG("[at86rf2xx] TX SUCCESS DATA PENDING\n");
|
||||
break;
|
||||
#else
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS:
|
||||
case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
|
||||
DEBUG("[at86rf2xx] TX SUCCESS\n");
|
||||
break;
|
||||
#endif
|
||||
case AT86RF2XX_TRX_STATE__TRAC_NO_ACK:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_NOACK);
|
||||
DEBUG("[at86rf2xx] TX NO_ACK\n");
|
||||
break;
|
||||
case AT86RF2XX_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_MEDIUM_BUSY);
|
||||
DEBUG("[at86rf2xx] TX_CHANNEL_ACCESS_FAILURE\n");
|
||||
break;
|
||||
default:
|
||||
DEBUG("[at86rf2xx] Unhandled TRAC_STATUS: %d\n",
|
||||
trac_status >> 5);
|
||||
}
|
||||
/* Radio is idle, any TX transaction is done */
|
||||
dev->pending_tx = 0;
|
||||
at86rf2xx_set_state(dev, dev->idle_state);
|
||||
DEBUG("[at86rf2xx] return to idle state 0x%x\n", dev->idle_state);
|
||||
_isr_send_complete(dev, trac_status);
|
||||
}
|
||||
/* Only the case when an interrupt was received and the radio is busy
|
||||
* with a next PDU transmission when _isr is called.
|
||||
* dev->pending == 1 means a receive and immediately a send happened.
|
||||
* The receive is discarded as the send already overwrote the internal
|
||||
* buffer.
|
||||
* dev->pending == 2 means two transmits occurred and this is the isr for
|
||||
* the first.
|
||||
*/
|
||||
else if (state == AT86RF2XX_STATE_BUSY_TX_ARET) {
|
||||
if (dev->pending_tx > 1) {
|
||||
dev->pending_tx--;
|
||||
_isr_send_complete(dev, trac_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user