This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Radio test in 802.15.4 -mode

I'm running the SDK 17 radio test example on two nRF52840 DKs. My goal is to do a PER measurement in 802.15.4 -mode.

I configure the boards to use ieee802154_250Kbit mode, the same channel and same payload pattern for both boards.

I can get the reception to work for a little while. If I tell the sender to send 100 packets, I usually get 100 received packets. But for anything longer the reception seems to stop at some point.

For instance if I set the transmitter to send 10000 packets (start_tx_modulated_carrier 10000) and monitor the reception by issuing "print_rx"-commands on the receiver, the packet count initially increments but stops at some point. Usually at a few hundred packets. Now if I issue a new "start_rx"-command the packet count again starts to increment from zero (as expected), but again stops at some lowish value.

I also tried a lower packet rate by setting the transmitter to duty cycle modulation. If I do "start_duty_cycle_modulated_tx 10", ie 10% duty cycle, it is even easier to monitor the received packet count as it increments slower. But again the count stops incrementing fairly soon. And restarting the rx makes the reception work again for a while.

If I redo all of the above using ble_1Mbit -mode it all works. I can send 10000 packets and receive 10000 packets. So it seems to be related to the 802.15.4-mode.

All testing so far has been done at my desk, with the DKs a few centimeters apart.

Any ideas on how to make this work would be appreciated.

Parents
  • Ok, I think I may have a hardware revision issue. One of my DKs is actually a Preview DK. PCA10056 v0.9.2

    I used this PDK as the receiver in the tests I did earlier. Now I tried to reverse the roles, and this unit hangs when trying to start transmitting.

    Is this expected? I need to check the HW revisions but was there an issue like this on some earlier revision?

    I don't have a third DK at the moment to test.

  • Based on the date code I probably have an Engineering A version.... I didn't even remember I had a DK this early.

    And the Errata 110 would explain what I'm seeing:

    Consequences

    Might lose packets in BLE LR or 802.15.4 mode. Might lose some sensitivity in BLE and proprietary mode.

    Workaround

    Always disable the radio after having received a packet (using TASK_DISABLE).

    Ugh. I have ordered a few more DKs.

  • If you set the other PCNF1 fields (balen, endian, whiteen) to zero in 802.15.4-mode, the reception works again. That makes PCNF1 equal to the way it was in SDK 15.3. I'm not sure if everything is correct after that, or if there is something else needed also.

    I did also notice that the received packets counter occasionally ends up higher than the number of packets I sent. The rx counter increments every time a CRCOK event occurs. So I'm guessing that in 802.15.4-mode the receiver counts every valid packet, even those sent to other devices? I have not checked this further though.

  • Hi Markku

    Thanks a lot for the update. I made the same changes myself and verified that this made the example work. 

    I didn't notice the counter issues you experienced though, I get the right number of packets on the RX side depending on how many packets I send from the TX. How often do you see this occur?

    Did you ever see any packets come in if you don't enable the TX at all?

    Best regards
    Torbjørn

  • Did you ever see any packets come in if you don't enable the TX at all?

    I think I did. I'll need to recheck.

    We have things here in the office that use a proprietary 802.15.4-based protocol to communicate, so that seemed the most plausible explanation.

    Now that I think about it.. The address matching is done in software, right? I recall struggling with it when we first implemented support for our protocol for the nRF52840. The radio driver needed to do quite a bit of work filtering packets intended for other recipients.

    And since the radio test code is very simple, there is no software address matching. So this is probably the cause.

  • Hi 

    I don't have a lot of experience with 802.15.4-based protocols, but based on the product specification it seems you are correct. 

    Any packet matching the synchronization header field (consisting of 4 bytes of preamble and 1 byte SHR) will be accepted by the radio, assuming the CRC is OK. 

    Then the destination address will have to be decoded from the packet by the software. 

    Best regards
    Torbjørn

  • Reality is sinking in slowly... All this time I've had it on my mind that we're dealing with MAC level packets. With addresses and crcs and all that. But the radio test has none of that. I've looked at the code quite a while, even traced some of the register values, but it wasn't until I started adding some filtering that it dawned on me that we're dealing with bare PHY packets.

    So all we have is the synchronization header, a length byte (PHR), and a payload full of fixed values. No addresses, not even a crc. I guess it might be possible to add the crc calculation even if there is no actual MPDU, but I'm not sure.

    What I'm going to do is simply check that the payload matches the expected fixed pattern, that'll be good enough in my case.

Reply
  • Reality is sinking in slowly... All this time I've had it on my mind that we're dealing with MAC level packets. With addresses and crcs and all that. But the radio test has none of that. I've looked at the code quite a while, even traced some of the register values, but it wasn't until I started adding some filtering that it dawned on me that we're dealing with bare PHY packets.

    So all we have is the synchronization header, a length byte (PHR), and a payload full of fixed values. No addresses, not even a crc. I guess it might be possible to add the crc calculation even if there is no actual MPDU, but I'm not sure.

    What I'm going to do is simply check that the payload matches the expected fixed pattern, that'll be good enough in my case.

Children
  • Hi

    Correct, the radio_test example is very simple, and doesn't use any protocol per se. 

    For basic RF testing this is not really required. 

    Best regards
    Torbjørn

  • /**
     * @brief Function for generating an 8-bit random number with the internal random generator.
     */
    static uint32_t _rnd8(void)
    {
        NRF_RNG->EVENTS_VALRDY = 0;
    
        while (NRF_RNG->EVENTS_VALRDY == 0)
        {
            // Do nothing.
        }
        return NRF_RNG->VALUE;
    }
    
    
    /**
     * @brief Function for generating a 32-bit random number with the internal random generator.
     */
    static uint32_t _rnd32(void)
    {
        uint8_t  i;
        uint32_t val = 0;
    
        for (i = 0; i < 4; i++)
        {
            val <<= 8;
            val  |= rnd8();
        }
        return val;
    }
    
    
    /**@brief Function for configuring the radio in every possible mode.
     *
     * @param[in] mode    Radio mode.
     * @param[in] pattern Radio transmission pattern.
     */
    static void radio_config(nrf_radio_mode_t mode, transmit_pattern_t pattern)
    {
        // Reset Radio ramp-up time.
        NRF_RADIO->MODECNF0 &= (~RADIO_MODECNF0_RU_Msk);
    
        // Packet configuration:
        // Bit 25: 1 Whitening enabled
        // Bit 24: 1 Big endian,
        // 4-byte base address length (5-byte full address length),
        // 0-byte static length, max 255-byte payload .
        NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) |
                           (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
                           (4UL << RADIO_PCNF1_BALEN_Pos) |
                           (0UL << RADIO_PCNF1_STATLEN_Pos) |
                           ((sizeof(m_tx_packet) - 1) << RADIO_PCNF1_MAXLEN_Pos);
        NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Disabled << RADIO_CRCCNF_LEN_Pos);
    
        NRF_RADIO->TXADDRESS   = 0x00UL; // Set the device address 0 to use when transmitting
        NRF_RADIO->RXADDRESSES = 0x01UL; // Enable the device address 0 to use to select which addresses to receive
    
        // Set the address according to the transmission pattern.
        switch (pattern)
        {
            case TRANSMIT_PATTERN_RANDOM:
                NRF_RADIO->PREFIX0 = _rnd8();
                NRF_RADIO->BASE0   = _rnd32();
                break;
    
            case TRANSMIT_PATTERN_11001100:
                NRF_RADIO->PREFIX0 = 0xCC;
                NRF_RADIO->BASE0   = 0xCCCCCCCC;
                break;
    
            case TRANSMIT_PATTERN_11110000:
                NRF_RADIO->PREFIX0 = 0xF0;
                NRF_RADIO->BASE0   = 0xF0F0F0F0;
                break;
    
            default:
                return;
        }
    
    
        switch (mode)
        {
         #ifdef NRF52840_XXAA
            case RADIO_MODE_MODE_Ieee802154_250Kbit:
            {
                // Packet configuration:
                // S1 size = 0 bits, S0 size = 0 bytes, payload length size = 8 bits, 32-bit preamble.
                NRF_RADIO->PCNF0 = (RADIO_LENGTH_LENGTH_FIELD << RADIO_PCNF0_LFLEN_Pos) |
                                   (RADIO_PCNF0_PLEN_32bitZero << RADIO_PCNF0_PLEN_Pos) |
                                   (RADIO_PCNF0_CRCINC_Exclude << RADIO_PCNF0_CRCINC_Pos);
                NRF_RADIO->PCNF1 = (IEEE_MAX_PAYLOAD_LEN << RADIO_PCNF1_MAXLEN_Pos);
    
                NRF_RADIO->MODECNF0    |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos);
            } break;
    
            case RADIO_MODE_MODE_Ble_LR500Kbit:
            case RADIO_MODE_MODE_Ble_LR125Kbit:
            {
                // Packet configuration:
                // S1 size = 0 bits, S0 size = 0 bytes, payload length size = 8 bits, 10-bit preamble.
                NRF_RADIO->PCNF0 = (0UL << RADIO_PCNF0_S1LEN_Pos) |
                                   (0UL << RADIO_PCNF0_S0LEN_Pos) |
                                   (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) |
                                   (2UL << RADIO_PCNF0_CILEN_Pos) |
                                   (3UL << RADIO_PCNF0_TERMLEN_Pos) |
                                   (RADIO_PCNF0_CRCINC_Exclude << RADIO_PCNF0_CRCINC_Pos) |
                                   (RADIO_LENGTH_LENGTH_FIELD << RADIO_PCNF0_LFLEN_Pos);
                NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) |
                                   (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) |
                                   (3UL << RADIO_PCNF1_BALEN_Pos) |
                                   (0UL << RADIO_PCNF1_STATLEN_Pos) |
                                   ((sizeof(m_tx_packet) - 1) << RADIO_PCNF1_MAXLEN_Pos);
    
                // Set fast ramp-up time.
                NRF_RADIO->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos);
    
                // Set CRC length; CRC calculation does not include the address field.
                NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |
                                    (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos);
            } break;
         #endif // NRF52840_XXAA
    
            case RADIO_MODE_MODE_Ble_2Mbit:
            {
                // Packet configuration:
                // S1 size = 0 bits, S0 size = 0 bytes, payload length size = 8 bits, 16-bit preamble.
                NRF_RADIO->PCNF0 = (0UL << RADIO_PCNF0_S1LEN_Pos) |
                                   (0UL << RADIO_PCNF0_S0LEN_Pos) |
                                   (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos) |
                                   (RADIO_LENGTH_LENGTH_FIELD << RADIO_PCNF0_LFLEN_Pos);
            } break;
    
            default:
            {
                // Packet configuration:
                // S1 size = 0 bits, S0 size = 0 bytes, payload length size = 8 bits, 8 -bit preamble.
                NRF_RADIO->PCNF0 = (0UL << RADIO_PCNF0_S1LEN_Pos) |
                                   (0UL << RADIO_PCNF0_S0LEN_Pos) |
                                   (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos) |
                                   (RADIO_LENGTH_LENGTH_FIELD << RADIO_PCNF0_LFLEN_Pos);
            } break;
        }
    }

    It should be worked.

  • Hi

    Please open a new ticket for these kind of requests, rather than add a new question to an old case. 

    In your case it seems you are not writing to the START task of the RNG?
    If you don't do this no random number generation will be started. 

    Best regards
    Torbjørn

Related