diff --git a/cpu/native/socket_zep/socket_zep.c b/cpu/native/socket_zep/socket_zep.c index 00e269170401..32b884637958 100644 --- a/cpu/native/socket_zep/socket_zep.c +++ b/cpu/native/socket_zep/socket_zep.c @@ -516,9 +516,17 @@ static int _request_transmit(ieee802154_dev_t *dev) dev->cb(dev, IEEE802154_RADIO_INDICATION_TX_START); - /* delay transmission to simulate airtime */ - zepdev->ack_timer.callback = _send_frame; - ztimer_set(ZTIMER_USEC, &zepdev->ack_timer, time_tx); + /* native overhead prevents short timers from triggering in time, + send directly if delay is less than 200 µs */ + if (time_tx <= 200) { + _send_frame(zepdev->ack_timer.arg); + } + else { + time_tx -= 200; + /* delay transmission to simulate airtime */ + zepdev->ack_timer.callback = _send_frame; + ztimer_set(ZTIMER_USEC, &zepdev->ack_timer, time_tx); + } return 0; } diff --git a/cpu/nrf52/radio/nrf802154/nrf802154_radio.c b/cpu/nrf52/radio/nrf802154/nrf802154_radio.c index d9c148cdfa8f..387c509a3f71 100644 --- a/cpu/nrf52/radio/nrf802154/nrf802154_radio.c +++ b/cpu/nrf52/radio/nrf802154/nrf802154_radio.c @@ -60,7 +60,6 @@ RADIO_SHORTS_CCABUSY_DISABLE_Msk | \ RADIO_SHORTS_TXREADY_START_Msk) -#define MAC_TIMER_CHAN_ACK (0U) /**< MAC timer channel for transmitting an ACK frame */ #define MAC_TIMER_CHAN_IFS (1U) /**< MAC timer channel for handling IFS logic */ static uint8_t rxbuf[IEEE802154_FRAME_LEN_MAX + 3]; /* len PHR + PSDU + LQI */ @@ -69,7 +68,6 @@ static uint8_t txbuf[IEEE802154_FRAME_LEN_MAX + 3]; /* len PHR + PSDU + LQI */ typedef enum { STATE_IDLE, STATE_TX, - STATE_ACK, STATE_RX, STATE_CCA_CLEAR, STATE_CCA_BUSY, @@ -415,6 +413,15 @@ static void _set_ifs_timer(bool lifs) timer_start(NRF802154_TIMER); } +static void _timer_cb(void *arg, int chan) +{ + (void)arg; + if (chan == MAC_TIMER_CHAN_IFS) { + cfg.ifs = false; + } + timer_stop(NRF802154_TIMER); +} + /** * @brief Set radio into DISABLED state */ @@ -424,6 +431,12 @@ int nrf802154_init(void) /* reset buffer */ rxbuf[0] = 0; txbuf[0] = 0; + + int result = timer_init(NRF802154_TIMER, TIMER_FREQ, _timer_cb, NULL); + assert(result >= 0); + (void)result; + timer_stop(NRF802154_TIMER); + /* power off peripheral (but do not release the HFXO as we never requested * it so far) */ NRF_RADIO->POWER = 0; @@ -478,7 +491,6 @@ void isr_radio(void) break; case STATE_RX: if (NRF_RADIO->CRCSTATUS) { - bool l2filter_passed = _l2filter(rxbuf+1); bool is_ack = rxbuf[1] & IEEE802154_FCF_TYPE_ACK; /* If radio is in promiscuous mode, indicate packet and @@ -488,14 +500,6 @@ void isr_radio(void) _state = STATE_IDLE; dev->cb(dev, IEEE802154_RADIO_INDICATION_RX_DONE); } - /* If the L2 filter passes, device if the frame is indicated - * directly or if the driver should send an ACK frame before - * the indication */ - else if (l2filter_passed) { - DEBUG("[nrf802154] RX frame doesn't require ACK frame.\n"); - _state = STATE_IDLE; - dev->cb(dev, IEEE802154_RADIO_INDICATION_RX_DONE); - } /* In case the packet is an ACK and the ACK filter is disabled, * indicate the frame reception */ else if (is_ack && !cfg.ack_filter) { @@ -503,6 +507,12 @@ void isr_radio(void) _state = STATE_IDLE; dev->cb(dev, IEEE802154_RADIO_INDICATION_RX_DONE); } + /* If the L2 filter passes the frame is indicated directly */ + else if (_l2filter(rxbuf+1)) { + DEBUG("[nrf802154] RX data frame.\n"); + _state = STATE_IDLE; + dev->cb(dev, IEEE802154_RADIO_INDICATION_RX_DONE); + } /* If all failed, simply drop the frame and continue listening * to incoming frames */ else { @@ -515,16 +525,6 @@ void isr_radio(void) dev->cb(dev, IEEE802154_RADIO_INDICATION_CRC_ERROR); } break; - case STATE_ACK: - _state = STATE_IDLE; - - /* We disable the radio to avoid unwanted emissions (see ERRATA - * ID 204, "Switching between TX and RX causes unwanted emissions") - */ - _disable(); - DEBUG("[nrf52840] TX ACK done."); - _set_ifs_timer(false); - break; default: assert(false); } diff --git a/sys/net/link_layer/ieee802154/submac.c b/sys/net/link_layer/ieee802154/submac.c index a1c32bf04257..d5f5a9a2cad5 100644 --- a/sys/net/link_layer/ieee802154/submac.c +++ b/sys/net/link_layer/ieee802154/submac.c @@ -29,6 +29,17 @@ #define CSMA_SENDER_BACKOFF_PERIOD_UNIT_US (320U) #define ACK_TIMEOUT_US (864U) +/* 2.4 GHz, 250 kb/s, O-QPSK 62.5 ksymbols/s, 1 / 62 500 s = 16 µs */ +/* 12 symbols -> 12 * 16us = 192us */ +#define SIFS_PERIOD_US (192U) + +/* internal type for IEEE 802.15.4 frame control field */ +enum ieee802154_fcf { + _FCF_BEACON = IEEE802154_FCF_TYPE_BEACON, + _FCF_DATA = IEEE802154_FCF_TYPE_DATA, + _FCF_ACK = IEEE802154_FCF_TYPE_ACK, + _FCF_MACCMD = IEEE802154_FCF_TYPE_MACCMD +}; static char *str_states[IEEE802154_FSM_STATE_NUMOF] = { "INVALID", @@ -131,7 +142,8 @@ static int _handle_fsm_ev_request_tx(ieee802154_submac_t *submac) } static ieee802154_fsm_state_t _fsm_state_prepare(ieee802154_submac_t *submac, - ieee802154_fsm_ev_t ev); + ieee802154_fsm_ev_t ev, + enum ieee802154_fcf ftype); static ieee802154_fsm_state_t _fsm_state_tx(ieee802154_submac_t *submac, ieee802154_fsm_ev_t ev); @@ -149,7 +161,7 @@ static int _handle_fsm_ev_tx_ack(ieee802154_submac_t *submac) return res; } /* skip async Tx request */ - _fsm_state_prepare(submac, IEEE802154_FSM_EV_BH); + _fsm_state_prepare(submac, IEEE802154_FSM_EV_BH, IEEE802154_FCF_TYPE_ACK); /* wait for Tx done */ while (_fsm_state_tx(submac, IEEE802154_FSM_EV_TX_DONE) == IEEE802154_FSM_STATE_INVALID) { DEBUG("IEEE802154 submac: wait until ACK sent\n"); @@ -254,13 +266,15 @@ static ieee802154_fsm_state_t _fsm_state_idle(ieee802154_submac_t *submac, ieee8 } static ieee802154_fsm_state_t _fsm_state_prepare(ieee802154_submac_t *submac, - ieee802154_fsm_ev_t ev) + ieee802154_fsm_ev_t ev, + enum ieee802154_fcf ftype) { ieee802154_dev_t *dev = &submac->dev; switch (ev) { case IEEE802154_FSM_EV_BH: - if (!_does_handle_csma(dev)) { + if (ftype == IEEE802154_FCF_TYPE_DATA + && !_does_handle_csma(dev)) { /* delay for an adequate random backoff period */ uint32_t bp = (random_uint32() & submac->backoff_mask) * submac->csma_backoff_us; @@ -272,6 +286,10 @@ static ieee802154_fsm_state_t _fsm_state_prepare(ieee802154_submac_t *submac, submac->backoff_mask = (submac->backoff_mask << 1) | 1; } } + else if (ftype == IEEE802154_FCF_TYPE_ACK) { + /* no backoff for ACK frames but wait for SIFSPeriod */ + ztimer_sleep(ZTIMER_USEC, SIFS_PERIOD_US); + } while (ieee802154_radio_request_transmit(dev) == -EBUSY) {} return IEEE802154_FSM_STATE_TX; @@ -423,7 +441,7 @@ ieee802154_fsm_state_t ieee802154_submac_process_ev(ieee802154_submac_t *submac, break; case IEEE802154_FSM_STATE_PREPARE: DEBUG("IEEE802154 submac: ieee802154_submac_process_ev(): IEEE802154_FSM_STATE_PREPARE + %s\n", str_ev[ev]); - new_state = _fsm_state_prepare(submac, ev); + new_state = _fsm_state_prepare(submac, ev, IEEE802154_FCF_TYPE_DATA); break; case IEEE802154_FSM_STATE_TX: DEBUG("IEEE802154 submac: ieee802154_submac_process_ev(): IEEE802154_FSM_STATE_TX + %s\n", str_ev[ev]);