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.

CC1352P: CC1352P RF Receive Callback Executes With Unexpected RF_EventLastCmdDone Event Mask

Part Number: CC1352P

I'm experiencing a non-deterministic but ultimately repeatable issue with the CC1352P:


Use case:
- CC1352P enters RF receive after power up (and remains in an RF receive state until canceled using RF_cancelCmd())
    - all RF packets are processed by the CC1352P upon receipt when the callback function is called
- when the CC1352P has an RF packet to transmit the RF receive command is canceled using RF_cancelCmd()
    - when the CC1352P completes the RF transmit, the CC1352P reenters RF receive
- this process repeats in perpetuity


Problem statement:
At some non-predictable point during execution, some time after entering RF receive and while waiting for a RF packet to be received the callback is called unexpectedly. No RF packet is indicated by the RF event mask. Instead, the rfEvtMask variable is set to RF_EventLastCmdDone (indicating the RF receive command is done). Shortly thereafter the RF receive command is removed from the RF command queue by the RF core finite state machine.

At this point, every RF receive command posted ends with the same result: RF receive is entered in the command queue (with an allocated channel index returned), the command callback is called with RF_EventLastCmdDone as the event mask, and then the RF receive command is removed from the command queue. This process is not aborted or canceled by user firmware, and breakpoints and callback stack trace confirm that is true. No longer are RF packets received until the CC1352P is reset. Once the reset occurs, expected operation continues until the problem reemerges.

Why does this behavior happen? Is it documented somewhere in the RF core documentation? What can I do to cause intended execution?

  • Here is some other relevant build environment information:
    - CC Studio version 10.1.0.00010
    - toolchain compiler: TI v20.2.1.LTS
    - SimpleLink CC13x2 26x2 SDK version 4.10.0.78
    - TI RTOS for CC13XX and CC26XX version 2.21.1.08
    - XDCtools version 3.61.2.27_core

  • Hi Steven,

    In this case, what is the "status" of the RX command in question (the status field is part of the command structure)? If you could also share the RX command settings you use that  would be helpful. 

  • I have four radios connected to the computer (each with its own CCS instance). When operating as intended the RF_rxPropCmd.status field predominantly equals 0x0002 (2). Occasionally there is a switch to 0x3400 (13312), or 0x3405 (13317), and I suspect that is when the RF transmit is active (RF_txPropCmd.status equals 0x0002 when transmitting).

    When not operating as intended, the RF_rxPropCmd.status field equals 0x3801 (14337). It does not appear this status field changes value at this point.

    -----

    Here is the default RF_rxPropCmd as defined in Debug/ti_radio_config.c:

    // CMD_PROP_RX
    // Proprietary Mode Receive Command
    rfc_CMD_PROP_RX_t RF_cmdPropRx =
    {
        .commandNo = 0x3802,
        .status = 0x0000,
        .pNextOp = 0,
        .startTime = 0x00000000,
        .startTrigger.triggerType = 0x0,
        .startTrigger.bEnaCmd = 0x0,
        .startTrigger.triggerNo = 0x0,
        .startTrigger.pastTrig = 0x0,
        .condition.rule = 0x1,
        .condition.nSkip = 0x0,
        .pktConf.bFsOff = 0x0,
        .pktConf.bRepeatOk = 0x0,
        .pktConf.bRepeatNok = 0x0,
        .pktConf.bUseCrc = 0x1,
        .pktConf.bVarLen = 0x1,
        .pktConf.bChkAddress = 0x0,
        .pktConf.endType = 0x0,
        .pktConf.filterOp = 0x0,
        .rxConf.bAutoFlushIgnored = 0x0,
        .rxConf.bAutoFlushCrcErr = 0x0,
        .rxConf.bIncludeHdr = 0x1,
        .rxConf.bIncludeCrc = 0x0,
        .rxConf.bAppendRssi = 0x0,
        .rxConf.bAppendTimestamp = 0x0,
        .rxConf.bAppendStatus = 0x1,
        .syncWord = 0x930B51DE,
        .maxPktLen = 0xFF,
        .address0 = 0xAA,
        .address1 = 0xBB,
        .endTrigger.triggerType = 0x1,
        .endTrigger.bEnaCmd = 0x0,
        .endTrigger.triggerNo = 0x0,
        .endTrigger.pastTrig = 0x0,
        .endTime = 0x00000000,
        .pQueue = 0,
        .pOutput = 0
    };

    And here are the modifications made at runtime during initialization:

    void Task_InitializeRFReceive( void )
    {
        ...
        RF_cmdPropRx.pQueue = &rxDataQueue;                         /* set the Data Entity queue for received data */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;                  /* discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;                   /* discard packets with CRC error from Rx queue */
        RF_cmdPropRx.maxPktLen = RF_RECEIVE_PACKET_MAX_LENGTH;      /* implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.pktConf.bRepeatOk = 1;
        RF_cmdPropRx.pktConf.bRepeatNok = 1;
        ...
    }

    Finally, here is the call to enter RF receive:

    _rfRxCmd = RF_postCmd( _rfHandle,
                           (RF_Op*) &RF_cmdPropRx,
                           RF_PriorityNormal,
                           (RF_Callback) &_RFReceiveCallback,
                           (RF_EventMask) RF_EventRxEntryDone );

  • Hi Steven,

    The status "0x3801" is "PROP_ERROR_RXBUF". This would mean that you have started to receive a packet that could not fit into the available RX queue buffers. This could for example be if you receive an unexpected packet that contains more data then the buffers could fit (as you operate in variable length mode). 

    Have you considered if you could use "Address filtering" to maybe reduce the risk of "unexpected packets" (as these would be more likely to be filtered out)? Also, how are your RX queues setup, what is the lengths used, you got multiple entries?

  • Thank you for pointing towards the various PROP_ERROR_* defines. The explanation documentation for these critical showstopper errors is not great. Specifically, how does one gracefully recover from the PROP_ERROR_RXBUF error? Assume it's OK that it happens once in a while, how can the system immediately recover and continue normal operation (as if the error never happened in the first place)? As it stands now the receive after getting this error once the system is unable to return to normal function -- the error keeps occuring. What would the recommended recovery strategy be?

    The RF receive queue is initialized as follows:

    /* initialize the RF queue */
    uint8_t result = RFQueue_defineQueue( &rxDataQueue,
                                          rxDataEntryBuffer,
                                          sizeof( rxDataEntryBuffer ),
                                          RX_NUM_DATA_ENTRIES,
                                          ( RF_RECEIVE_PACKET_MAX_LENGTH + RF_RECEIVE_PACKET_NUM_APPENDED_BYTES ) );

    The datatypes of the command parameters is as follows:

    static dataQueue_t rxDataQueue;
    #pragma DATA_ALIGN ( rxDataEntryBuffer, 4 );
        static uint8_t rxDataEntryBuffer[ RF_QUEUE_DATA_ENTRY_BUFFER_SIZE( RX_NUM_DATA_ENTRIES,
                                                                           RF_RECEIVE_PACKET_MAX_LENGTH,
                                                                           RF_RECEIVE_PACKET_NUM_APPENDED_BYTES ) ];
    #define RX_NUM_DATA_ENTRIES    ( 2 )
    #define RF_RECEIVE_PACKET_MAX_LENGTH             ( 255 )
    #define RF_RECEIVE_PACKET_NUM_APPENDED_BYTES     ( 2 )

    Address filtering is not a workable strategy at scale (dozens or hundreds of radios in the vicinity). It's preferable to minimize the chance of this error occurring by increasing the buffer size, and to detect when this error condition exists and return to normal operating conditions (even if that means losing received data). In any case the uptime and availability is paramount. Please help me find how to do that in the best way possible.

  • Hi Steven,

    You would need to reset your RX queue to be able to re-start the RX again. With that I mean resetting the status field of the entry to idle:

    readEntry->status = DATA_ENTRY_PENDING;
    If you do not reset the status, you would likely just run into the same issue again as the radio would check for somewhere to put the message but can't find any idle entries.