[riot-notifications] [RIOT-OS/RIOT] nrf802154: Fix IFS timings (#11146)

Koen Zandberg notifications at github.com
Fri Mar 8 21:11:38 CET 2019

### Contribution description

This PR fixes two issues with the IFS timing in the nrf802154 radio driver.

 I've used the following patch to measure timings of the radio IFS timer:
diff --git a/cpu/nrf52/radio/nrf802154/nrf802154.c b/cpu/nrf52/radio/nrf802154/nrf802154.c
index 1a57a8799..9ce87eaa1 100644
--- a/cpu/nrf52/radio/nrf802154/nrf802154.c
+++ b/cpu/nrf52/radio/nrf802154/nrf802154.c
@@ -24,6 +24,7 @@
 #include <errno.h>

 #include "cpu.h"
+#include "periph/gpio.h"
 #include "luid.h"
 #include "mutex.h"

@@ -184,6 +185,7 @@ static void _timer_cb(void *arg, int chan)
+    gpio_clear(GPIO_PIN(1,9));
     timer_clear(NRF802154_TIMER, 0);
@@ -193,6 +195,7 @@ static int _init(netdev_t *dev)

+    gpio_init(GPIO_PIN(1, 9), GPIO_OUT);
     int result = timer_init(NRF802154_TIMER, TIMER_FREQ, _timer_cb, NULL);
     assert(result >= 0);
@@ -415,6 +418,7 @@ void isr_radio(void)
             case RADIO_STATE_STATE_Tx:
             case RADIO_STATE_STATE_TxIdle:
             case RADIO_STATE_STATE_TxDisable:
+                gpio_set(GPIO_PIN(1, 9));
                 DEBUG("[nrf802154] TX state: %x\n", (uint8_t)NRF_RADIO->STATE);
                 _state |= TX_COMPLETE;
The GPIO is set before the timer is started and cleared in the interrupt.

Using this at the current master results in the following timing (LIFS value):

measured on the nrf52840 using `examples/gnrc_networking` with
ping6 fe80::7b67:1860:420c:f43a -c 100  -i 250 -s 200
The payload size of 200B is the most important as it causes the packet to be split into multiple frames.

The correct timing for the LIFS should be: 
 - LIFS: 40 symbols (IEEE 802.15.4-2011: *macLIFSPeriod* – 40 symbols)
 - Symbol rate: 62.5Ksymbol/s ((IEEE 802.15.4-2011 table 66, 2450 DSSS)
giving us 40 symbols / 62.5Ksymbol/s = 640μs.

This doesn't match the current measured timeout value.

### Fix

The fix here is twofold. The first commit is modifies the `TIMER_FREQ` to match the symbol rate as specified in the ieee 802.15.4 specification. With this a timer tick and an ieee 802.15.4 symbol are equal in duration. The `SIFS` and `LIFS` defines then also match their durations in symbols.

The second issue is caused by timer_clear function. It doesn't clear the hardware timer counter, but
is designed to clear the allocation of the channel. The consequence is that the IFS timer here is not set to zero in the callback, but only stopped at the current value. When the timer is started again, it has to
count the full timer range until it matches the timeout value again. With the timer never reset to zero, it doesn't count the `LIFS`/`SIFS` duration but the timer range * `TIMER_FREQ` duration (1024 μs in the intial measurement).

Measuring again with the same setup as above gives:

Matching the calculated LIFS value from the spec.

### Testing procedure

I won't blame anyone for not reproducing my measurement with their own logic analyzer. Testing that ping with large payloads (multiple L2 frames) still work should IMHO be enough. Ping response timings should decrease slightly (121ms vs 117ms average for 1000B payload).

### Issues/PRs references

You can view, comment on, or merge this pull request online at:


-- Commit Summary --

  * nrf802154: Change timer frequency to match symbols rate
  * nrf802154: Fix timer behaviour of the IFS timer

-- File Changes --

    M cpu/nrf52/radio/nrf802154/nrf802154.c (5)

-- Patch Links --


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.riot-os.org/pipermail/notifications/attachments/20190308/5d0e3e6a/attachment-0001.html>

More information about the notifications mailing list