This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LAUNCHXL-CC1352R1: How to check for received RF message

Part Number: LAUNCHXL-CC1352R1

I am trying to write a program that handles messages between two devices that may send a message at any time. I am trying to understand how to check & know if my CC1352R1 TI board has received an RF message from the other TI board. Usually, I have the board sit in RF receive mode using this function call: RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone); but then I cannot do anything until an RF message comes in.

I would like to be able to check the RF queue status or to have some way to know that an RF message was received. Is this possible? Does the RF core have an internal buffer or data structure that holds received RF messages even if the RF_runCMD() function is not called with the RF_cmdPropRx command?

In the same vein, is there a way to do the same thing with the UART2 receive buffer? In other words, to know when data is received on the UART2 buffer?

EDIT:

I am using SDK version CC13xx_CC26xx_6_10_00_29

  • with the rfPacketRX example, you will enter the callback every ime a packet is received. 

    The example stays in RX forever, and RF_runCmd is blocking, meaning that you will not get past this function before RX is terminated. 

    Since RF_cmdPropRx.pktConf.bRepeatOk = 1, RX will not terminate unless you get an error of some sort (overflow etc.)

    Instead of using the blocking RF_runCmd, you can use RF_postCmd (non-blocking). You can also set RF_cmdPropRx.pktConf.bRepeatOk = 0;

    Then you can do something like this:

    static bool packetReceived = false;
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, pinTable);
        if (ledPinHandle == NULL)
        {
            while(1);
        }
    
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
    
        /* Modify CMD_PROP_RX command for application needs */
        /* Set the Data Entity queue for received data */
        RF_cmdPropRx.pQueue = &dataQueue;
        /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
        /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;
        RF_cmdPropRx.pktConf.bRepeatOk = 0; // Turn off repeat mode so that RX will end when a packet is received
        RF_cmdPropRx.pktConf.bRepeatNok = 1;
    
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        while (1)
        {
            RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
            // Do other stuff until a packet has been received
            while (!packetReceived)
            {
    
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, !PIN_getOutputValue(Board_PIN_LED1));
                CPUdelay(5000000);
            }
            packetReceived = false;
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            /* Toggle pin to indicate RX */
            PIN_setOutputValue(ledPinHandle, Board_PIN_LED2,
                               !PIN_getOutputValue(Board_PIN_LED2));
    
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* Handle the packet data, located at &currentDataEntry->data:
             * - Length is the first byte with the current configuration
             * - Data starts from the second byte */
            packetLength      = *(uint8_t*)(&currentDataEntry->data);
            packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet, packetDataPointer, (packetLength + 1));
    
            RFQueue_nextEntry();
    
            packetReceived = true;
        }
    }

    The code above will enter RX mode and then start toggling a LED until a packet is received.

    It will then re-enter RX and repeat.

    The UART driver can be used in both blocking mode and callback mode (you get an interrupt when something is received).

    Take a look at the UART2 driver documentation for more details.

    UART2.h File Reference (ti.com)

    Siri

  • Thanks Siri, that is very helpful. The non blocking commands seem to be a good path forward. Do you know typically how long it takes between the core receiving an RF message and the callback running?

    Also, is it possible to miss an RF message running in this mode? Does the RF core store all received messages in the queue created in your code? What happens if this queue is filled and a new message is received? I assume this should be handled in the code by the user.

  • To determine the time form the radio exit RX to you get a callback, you can output the CPE_GPO0 signal on a pin, and measure the time from this pin is de-asserted until the Board_PIN_LED2 toggles. 

    How to output this signal is described here:

    Routing RF Core Signals to Physical Pins — SimpleLinkTm CC13XX/CC26XX SDK Proprietary RF User's Guide 5.20.00 documentation

    First of all, it is always possible to miss RF packets, as you have no control over which interferers will be on the air while a packet is being sent to your :-)

    the code I posted are not using repeat mode (RF_cmdPropRx.pktConf.bRepeatOk = 0) so the radio exit RX when a packet is sent, and then it enters RX again.

    You can enable repeat mode again (like in the original example), but use post instead of run. The radio will stay in RX after a packet is received, so with this approach you need to make sure that  you are handling the RF queue fast enough to void any overflow situations.

    This could typically happen if the radio received several packets in a row, and the MCU is occupied with higher priority tasks so that it fails to handle the RX callbacks.

    Siri