[riot-notifications] [RIOT-OS/RIOT] nrfmin can get stuck and never reach RX (while TX works) (#10878)

pystub notifications at github.com
Thu Apr 18 22:23:30 CEST 2019


I ran some tests with 4 boards sending announcements at 0.1s intervals. I tried to incrementally add changes to in the nrfmin.c file. With the now merged interrupt bugfix applied, **`state` still can be eventually prevented from going into `STATE_RX`**. Line where this happens: https://github.com/RIOT-OS/RIOT/blob/3e6336ce89d64d58ab07764ef7f65fc86800cb85/cpu/nrf5x_common/radio/nrfmin/nrfmin.c#L160
Using gdb I was able to verify that `rx_buf.pkt.hdr.len` is non-zero.

Also, while comparing files of my current working directory I found some other previously unmentioned changes. I'm attaching the full patch file.

[nrfmin-changes.txt](https://github.com/RIOT-OS/RIOT/files/3096028/nrfmin-changes.txt)

```diff
diff --git a/cpu/nrf5x_common/radio/nrfmin/nrfmin.c b/cpu/nrf5x_common/radio/nrfmin/nrfmin.c
index 02d713208..02208dda9 100644
--- a/cpu/nrf5x_common/radio/nrfmin/nrfmin.c
+++ b/cpu/nrf5x_common/radio/nrfmin/nrfmin.c
@@ -163,7 +163,9 @@ static void goto_target_state(void)
         NRF_RADIO->PACKETPTR = (uint32_t)(&rx_buf);
         NRF_RADIO->BASE0 = (CONF_ADDR_BASE | my_addr);
         /* goto RX mode */
+        NRF_RADIO->EVENTS_READY = 0;
         NRF_RADIO->TASKS_RXEN = 1;
+        while (NRF_RADIO->EVENTS_READY == 0) {}
         state = STATE_RX;
     }
 
@@ -269,6 +271,12 @@ int nrfmin_set_state(netopt_state_t val)
     /* make sure radio is turned on and no transmission is in progress */
     NRF_RADIO->POWER = 1;
 
+    DEBUG(
+        "[nrfmin] state: from %d to %d\n"
+        "         mem state %d\n"
+        "         reg STATE %lu\n"
+        "         pkt.hdr.len %u\n", target_state, val, state, NRF_RADIO->STATE, rx_buf.pkt.hdr.len);
+
     switch (val) {
         case NETOPT_STATE_OFF:
             target_state = STATE_OFF;
@@ -297,17 +305,20 @@ void isr_radio(void)
     if (NRF_RADIO->EVENTS_END == 1) {
         NRF_RADIO->EVENTS_END = 0;
         /* did we just send or receive something? */
-        if (state == STATE_RX) {
+        /* HACK: if we have a packet, trigger a callback anyway */
+        state_t orig_state = state;
+        if (orig_state == STATE_RX || rx_buf.pkt.hdr.len > 0) {
             /* drop packet on invalid CRC */
             if ((NRF_RADIO->CRCSTATUS != 1) || !(nrfmin_dev.event_callback)) {
                 rx_buf.pkt.hdr.len = 0;
                 NRF_RADIO->TASKS_START = 1;
-                return;
+                // return;
+            } else {
+                rx_lock = 0;
+                nrfmin_dev.event_callback(&nrfmin_dev, NETDEV_EVENT_ISR);
             }
-            rx_lock = 0;
-            nrfmin_dev.event_callback(&nrfmin_dev, NETDEV_EVENT_ISR);
         }
-        else if (state == STATE_TX) {
+        if (orig_state == STATE_TX) {
             goto_target_state();
         }
     }
@@ -319,10 +330,11 @@ static int nrfmin_send(netdev_t *dev, const iolist_t *iolist)
 {
     (void)dev;
 
-    assert((iolist) && (state != STATE_OFF));
+    assert((iolist) && (((NRF_RADIO->POWER & RADIO_POWER_POWER_Msk) >> RADIO_POWER_POWER_Pos) == RADIO_POWER_POWER_Enabled));
 
     /* wait for any ongoing transmission to finish and go into idle state */
     while (state == STATE_TX) {}
+    // while (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled && NRF_RADIO->STATE != RADIO_STATE_STATE_Rx) {}
     go_idle();
 
     /* copy packet data into the transmit buffer */
@@ -344,7 +356,9 @@ static int nrfmin_send(netdev_t *dev, const iolist_t *iolist)
     /* trigger the actual transmission */
     DEBUG("[nrfmin] send: putting %i byte into the ether\n", (int)hdr->len);
     state = STATE_TX;
+    NRF_RADIO->EVENTS_READY = 0;
     NRF_RADIO->TASKS_TXEN = 1;
+    while (NRF_RADIO->EVENTS_READY == 0) {}
 
     return (int)pos;
 }
@@ -354,7 +368,7 @@ static int nrfmin_recv(netdev_t *dev, void *buf, size_t len, void *info)
     (void)dev;
     (void)info;
 
-    assert(state != STATE_OFF);
+    assert(((NRF_RADIO->POWER & RADIO_POWER_POWER_Msk) >> RADIO_POWER_POWER_Pos) == RADIO_POWER_POWER_Enabled);
 
     unsigned pktlen = rx_buf.pkt.hdr.len;
 
```

>From my testing I'm suspecting that the key to having functional sending is zeroing out `rx_buf.pkt.hdr.len`.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/RIOT-OS/RIOT/issues/10878#issuecomment-484676433
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.riot-os.org/pipermail/notifications/attachments/20190418/318d7807/attachment.html>


More information about the notifications mailing list