Low level 802.15.4 transmit code

I am trying to make a simple MAC-layer transceiver using Arduino environment.  I have some code derived from this example: https://github.com/IoTS-P/nRF52-802154-Raw-Transmitter
and have discovered that it hangs after one to a few hundred transmissions.  I have gone over the datasheet for the 802.15.4 radio section and I do not see where the problem is.I am using a Zena receiver to monitor the transmissions.  I noticed that the CCA appears to take some tens-of-mS fairly often while the Zena does not show any other messages arrived during that time.  What am I doing wrong with the radio hardware?

<project files attached>

Parents
  • Hi DU_radio,

    The repo looks lt uses PlatformIO and the API is a unknow to me. It is hard for us to review something that is using external SDKs, too many unknows to properly give you a proper debugging direction. 

    Regarding the radio handling, I can say one thing that you did not seem to have handled failed CCA scenario properly, it is wise to do a cleanup, deinit and reinit in that case. Also there are a lot of hardcoded values in your code, not very pleasant to read or review. I suggest you take this question to a proper forum API you are using here to implement this.

  • Susheel,

        Thank you for your advice on CCA cleanup.  Does it need a full powerup init (and if so why?) or just the CCA threshold and clear events and re-enable the tasks? I ask because a full powerup init when CCA_IDLE was false did not help.

         The code has most of the constants from the original GIT repo (not my project), these are the register addresses in the nRFD52840 datasheet so I thought they would be more meaningfull to the Nordic hardware folks.  Also I was trying to avlod introducing more problems by incorrectly editing the register references.  Yes it is certainly ugly. Once it is working I will do a major code cleanup.

    Since this is a Nordic radio issue and not related to the platform it was built on, is there another forum that would be better suited to troubleshooting the radio?

    Darryl

  • Do you have perhaps, a detailed flowchart of how to configure and operate the radio? Or perhaps someone who could correct the rather simple low-level radio software that I attached?  Only radio.c access the hardware. The project can be build with Arduino 1.8 IDE, most college engineering students could handle that.  Or are you suggesting that Nordic has lost the tribal knowledge to run their own hardware?

  • I am no expert in this and also do not think that there is any flowchart readily available so I will try to write a template code for the suggestions I have provided below

    Can you please modify your radio_send_custom in your radio.cpp as below

    void radio_send_custom(uint8_t *pBuffer, uint8_t channel) {
    
      /* No shortcuts on disable. */
      NRF_RADIO->SHORTS = 0x0;
    
      /* Switch radio to TX. */
      radio_disable();
    
      for (size_t try_ = 0; try_ < MAX_RETRIES; try_++) 
      {
        /* Switch packet buffer to tx_buffer. */
        NRF_RADIO->PACKETPTR = (uint32_t)pBuffer;
        NRF_RADIO->INTENSET = (1 << RADIO_INTENSET_END_Pos);
        NVIC_ClearPendingIRQ(RADIO_IRQn);
        NVIC_EnableIRQ(RADIO_IRQn);
    
        NRF_RADIO->EVENTS_READY = 0;
        NRF_RADIO->TASKS_RXEN = 1;
        Serial.write("While 1 ");
        while (!NRF_RADIO->EVENTS_READY);
    
        NRF_RADIO->EVENTS_CCAIDLE = 0;
        NRF_RADIO->EVENTS_CCABUSY = 0;
        sig_ccabusy = false;
        NRF_RADIO->TASKS_CCASTART = 1;
    
        Serial.write("While 2 ");
        int timeout = 10000;
        while (!NRF_RADIO->EVENTS_CCAIDLE && !NRF_RADIO->EVENTS_CCABUSY && !sig_ccabusy && --timeout);
        Serial.write("While 3 ");
    
        if (timeout == 0 || sig_ccabusy || NRF_RADIO->EVENTS_CCABUSY) 
        {
          Serial.println("WARNING: retry for CCABUSY");
          sig_ccabusy = false;
          radio_disable();
          delay(100);
          continue;
        }
    
        NRF_RADIO->TXPOWER =
            (RADIO_TXPOWER_TXPOWER_Pos4dBm << RADIO_TXPOWER_TXPOWER_Pos);
        NRF_RADIO->FREQUENCY = channel_to_freq(channel);
    
        NRF_RADIO->EVENTS_DISABLED = 0;
        NRF_RADIO->TASKS_DISABLE = 1;
        while (!NRF_RADIO->EVENTS_DISABLED);
    
        NRF_RADIO->EVENTS_READY = 0;
        NRF_RADIO->TASKS_TXEN = 1;
        Serial.write("While 4\r\n");
        while (!NRF_RADIO->EVENTS_READY);
        NRF_RADIO->TASKS_START = 1;
        return;
      }
    
      Serial.println("ERROR: retry too many times");
    }
    

    Also ensure CCAIDLE and CCABUSY are cleared in the IRQ handler RADIO_IRQHandler

    if (NRF_RADIO->EVENTS_CCABUSY) {
      NRF_RADIO->EVENTS_CCABUSY = 0;
      NRF_RADIO->TASKS_DISABLE = 1;
      while (!NRF_RADIO->EVENTS_DISABLED);
      sig_ccabusy = true;
    }
    
    if (NRF_RADIO->EVENTS_CCAIDLE) {
      NRF_RADIO->EVENTS_CCAIDLE = 0;
      sig_ccabusy = false;
    }
    

  • Susheel,

         Thanks for the changes, they made a huge difference.  It runs for over 100K message, but then stops and fails the CCA forever after.  Is this a case where a full register-reload is needed?  I am testing that now.  Is it possible that some external event getting into the receiver, e.g. lightning, might flip a bit and require a register reload?

    Darryl

  • I suggest adding a --timeout check to every while(..); instead of just a few of those; on timeout reset RADIO and start again. For example all whiles of the form:

        while (!NRF_RADIO->EVENTS_READY);

    Most of us learn to adopt such defensive programming practices when dealing with hardware registers and devices which misbehave when least expected ..

  • In the4 second test it ran for 102,643 messages, then failed the CCA_busy.  I had it do a radio_set_sniff() which initializes all the radio registers the same as powerup, but that did not recover.  It does not hang, just always fails the CCA_busy.   

    while (!NRF_RADIO->EVENTS_CCAIDLE && !NRF_RADIO->EVENTS_CCABUSY && !sig_ccabusy && --timeout);
    Clearly the channel is not 100% busy for hours so is there another reset sequence that I should use?

Reply
  • In the4 second test it ran for 102,643 messages, then failed the CCA_busy.  I had it do a radio_set_sniff() which initializes all the radio registers the same as powerup, but that did not recover.  It does not hang, just always fails the CCA_busy.   

    while (!NRF_RADIO->EVENTS_CCAIDLE && !NRF_RADIO->EVENTS_CCABUSY && !sig_ccabusy && --timeout);
    Clearly the channel is not 100% busy for hours so is there another reset sequence that I should use?

Children
No Data
Related