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.

RTOS/CC1310: Rx timeout status inconsistent

Part Number: CC1310


Tool/software: TI-RTOS

Hi,

I need to receive a packet within a window. I have modified rx.c in the IAR\CC1310DK_7XD\rfPacketErrorRate example and have included the code in its entirety below. My changes are marked with the ADD_MY_CHANGES macro. Essentially I post an Rx command with:

RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &rx_callback, RF_EventRxEntryDone);



The parameters are set so the command times out after 50.5ms, but would normally expect a packet every 50ms (from another board running tx.c). I am observing the status returned by:

((volatile RF_Op*)&RF_cmdPropRx)->status;


The behaviour I am seeing is:
1) if I start the board then run Rx with no packets being received, then the timeout is 92ms and status = 13313 (= 0x3401 = PROP_DONE_RXTIMEOUT)
2) if I then turn on the other board to Tx packets, the packets are received every 50ms and status = 13312 (= 0x3400 = PROP_DONE_OK)
3) after almost no time at all to few seconds (the time can vary) packets are received every 50ms and status = 2
4) if I then stop the Tx, the timeout is 50.6ms and status = 1

after leaving state 2 the board will be in either state 3 (Rx) or 4 (no Rx) and not return to either state 1 or 2. Diagramatically I'm seeing this:



I am using the IAR IDE and tirtos_cc13xx_cc26xx_2_21_00_06

Does anyone have any ideas why I am seeing this behaviour please?

/*
 * Copyright (c) 2016, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define ADD_MY_CHANGES

/***** Includes *****/

/* XDCtools Header files */
#include <xdc/runtime/Assert.h>
#include <xdc/runtime/System.h>
#include <xdc/std.h>

#ifdef ADD_MY_CHANGES
/* BIOS module headers */
#include <ti/sysbios/knl/Semaphore.h>
#endif

/* TI-RTOS Header files */
#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>

/* Board Header files */
#include "Board.h"

/* Application specific Header files */
#include "menu.h"
#include "RFQueue.h"
#include "smartrf_settings/smartrf_settings.h"
#include "smartrf_settings/smartrf_settings_predefined.h"

#if (defined __CC2650EM_7ID_H__) || (defined __CC2650_LAUNCHXL_BOARD_H__) || (defined __CC1350_LAUNCHXL_BOARD_H__) || (defined __CC1350STK_SENSORTAG_BOARD_H__)
#include "smartrf_settings/smartrf_settings_ble.h"
#endif

#ifdef ADD_MY_CHANGES
#include "driverlib/rf_prop_mailbox.h"
#endif

/***** Defines *****/
#define DATA_ENTRY_HEADER_SIZE  8   /* Constant header size of a Generic Data Entry */
#define MAX_LENGTH              125 /* Max length byte the radio will accept */
#define NUM_DATA_ENTRIES        2   /* NOTE: Only two data entries supported at the moment */
#define NUM_APPENDED_BYTES      2   /* RF_cmdRxHS.rxConf.bIncludeLen = 1: Include the received length
                                    * field (2 bytes) in the stored packet  */

#ifdef ADD_MY_CHANGES
/* Pin driver handle */
static PIN_Handle ledPinHandle;
static PIN_State ledPinState;

/*
 * Application LED pin configuration table:
 *   - All LEDs board LEDs are off.
 */
PIN_Config ledPinTable[] = {
    Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, // LED 4
    Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, // LED 1
    Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, // LED 2
    Board_LED3 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, // LED 3
    PIN_TERMINATE
};
#endif                                  
                                    
/***** Prototypes *****/
static void rx_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);


/***** Variable declarations *****/
static uint8_t packetReceived = false;
static uint16_t* crcOk;
static int8_t* rssi;
#ifdef ADD_MY_CHANGES
static uint16_t ret, status = 0;
#endif

static RF_Object rfObject;
static RF_Handle rfHandle;
static RF_CmdHandle rxCmdHndl = NULL; /* Handle needed to abot the RX command */

#ifdef ADD_MY_CHANGES
/* for semaphore */
Semaphore_Struct semStruct;
Semaphore_Handle semHandle;
#endif

/* Buffer which contains all Data Entries for receiving data.
 * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
#if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
        static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                 MAX_LENGTH,
                                                                 NUM_APPENDED_BYTES)];
#elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
        static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                 MAX_LENGTH,
                                                                 NUM_APPENDED_BYTES)];
#elif defined(__GNUC__)
        static uint8_t rxDataEntryBuffer [RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
            MAX_LENGTH, NUM_APPENDED_BYTES)] __attribute__ ((aligned (4)));
#else
    #error This compiler is not supported.
#endif


static dataQueue_t dataQueue;                    /* Receive queue for the RF Code to fill in data */
rfc_dataEntryGeneral_t* currentDataEntry;        /* General data entry structure (type = 0) */

#if !(defined __CC2650EM_7ID_H__) && !(defined __CC2650_LAUNCHXL_BOARD_H__)
rfc_hsRxOutput_t rxStatistics_hs;                /* Output structure for CMD_HS_RX */
#endif

#if (defined __CC2650EM_7ID_H__) || (defined __CC2650_LAUNCHXL_BOARD_H__) || (defined __CC1350_LAUNCHXL_BOARD_H__) || (defined __CC1350STK_SENSORTAG_BOARD_H__)
rfc_bleGenericRxOutput_t rxStatistics_ble;                /* Output structure for RF_ble_cmdBleGenericRx */
#endif

rfc_propRxOutput_t rxStatistics_prop;            /* Output structure for CMD_PROP_RX */


/*
Runs the receiving part of the test application and returns a result.
 */
TestResult rx_runRxTest(const ApplicationConfig* config)
{
#ifdef ADD_MY_CHANGES
    Semaphore_Params semParams;

    /* Construct Semaphore object, inital count 0 */
    Semaphore_Params_init(&semParams);
    semParams.mode = Semaphore_Mode_BINARY;
    Semaphore_construct(&semStruct, 0, &semParams);

    /* Obtain instance handle */
    semHandle = Semaphore_handle(&semStruct);

    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, ledPinTable);
    if(!ledPinHandle) {
        System_abort("Error initializing board LED pins\n");
    }
#endif
    Assert_isTrue(config != NULL, NULL);

    RF_Params rfParams;
    RF_Params_init(&rfParams);

    if( RFQueue_defineQueue(&dataQueue,
                            rxDataEntryBuffer,
                            sizeof(rxDataEntryBuffer),
                            NUM_DATA_ENTRIES,
                            MAX_LENGTH + NUM_APPENDED_BYTES))
    {
        /* Failed to allocate space for all data entries */
        while(true);
    }

#ifndef ADD_MY_CHANGES
    RF_cmdPropRx.pQueue = &dataQueue;
    RF_cmdPropRx.pOutput = (uint8_t*)&rxStatistics_prop;
    RF_cmdPropRx.maxPktLen = MAX_LENGTH;
    RF_cmdPropRx.pktConf.bRepeatOk = 1;
    RF_cmdPropRx.pktConf.bRepeatNok = 1;
    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
#else
    RF_cmdPropRx.pQueue = &dataQueue;
    RF_cmdPropRx.pOutput = (uint8_t*)&rxStatistics_prop;
    RF_cmdPropRx.maxPktLen = MAX_LENGTH;
    RF_cmdPropRx.pktConf.bRepeatOk = 0;
    RF_cmdPropRx.pktConf.bRepeatNok = 0;
    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
    
    RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
    //RF_cmdPropRx.endTrigger.bEnaCmd = ;
    //RF_cmdPropRx.endTrigger.triggerNo = ;
    RF_cmdPropRx.endTrigger.pastTrig = 1;
    RF_cmdPropRx.endTrigger.endTime = (uint32_t)(4*50500);  // 50.5ms timeout
#endif

#if !(defined __CC2650EM_7ID_H__) && !(defined __CC2650_LAUNCHXL_BOARD_H__)
    RF_pCmdRxHS->pOutput = &rxStatistics_hs;
    RF_pCmdRxHS->pQueue = &dataQueue;
    RF_pCmdRxHS->maxPktLen = MAX_LENGTH;
    RF_pCmdRxHS->pktConf.bRepeatOk = 1;
    RF_pCmdRxHS->pktConf.bRepeatNok = 1;
    RF_pCmdRxHS->rxConf.bAutoFlushCrcErr = 1;
#endif

#if (defined __CC2650EM_7ID_H__) || (defined __CC2650_LAUNCHXL_BOARD_H__) || (defined __CC1350_LAUNCHXL_BOARD_H__) || (defined __CC1350STK_SENSORTAG_BOARD_H__)
    RF_ble_pCmdBleGenericRx->pOutput = &rxStatistics_ble;
    RF_ble_pCmdBleGenericRx->pParams->pRxQ = &dataQueue;
    RF_ble_pCmdBleGenericRx->pParams->bRepeat = 1;
    RF_ble_pCmdBleGenericRx->pParams->rxConfig.bAutoFlushCrcErr = 1;
    RF_ble_pCmdBleGenericRx->channel = 0xFF;
    RF_ble_pCmdBleGenericRx->whitening.bOverride = 1;
    RF_ble_pCmdBleGenericRx->whitening.init = config->frequencyTable[config->frequency].whitening;

#endif


    /* Request access to the radio based on test case */
    switch (config->rfSetup)
    {

        case RfSetup_Custom:

            rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
            break;

        case RfSetup_Fsk:
#if !(defined __CC2650EM_7ID_H__) && !(defined __CC2650_LAUNCHXL_BOARD_H__)
            RF_pCmdPropRadioDivSetup_fsk->centerFreq = config->frequencyTable[config->frequency].frequency;
            rfHandle = RF_open(&rfObject, RF_pProp_fsk, (RF_RadioSetup*)RF_pCmdPropRadioDivSetup_fsk, &rfParams);
#else
            rfHandle = RF_open(&rfObject, RF_pProp_2_4G_fsk, (RF_RadioSetup*)RF_pCmdPropRadioSetup_2_4G_fsk, &rfParams);
#endif
            break;
#if !(defined __CC2650EM_7ID_H__) && !(defined __CC2650_LAUNCHXL_BOARD_H__)
        case RfSetup_Lrm:

            RF_pCmdPropRadioDivSetup_lrm->centerFreq = config->frequencyTable[config->frequency].frequency;
            rfHandle = RF_open(&rfObject, RF_pProp_lrm, (RF_RadioSetup*)RF_pCmdPropRadioDivSetup_lrm, &rfParams);
            break;

        case RfSetup_Ook:

            RF_pCmdPropRadioDivSetup_ook->centerFreq = config->frequencyTable[config->frequency].frequency;
            rfHandle = RF_open(&rfObject, RF_pProp_ook, (RF_RadioSetup*)RF_pCmdPropRadioDivSetup_ook, &rfParams);
            break;

        case RfSetup_Hsm:

            rfHandle = RF_open(&rfObject, RF_pProp_hsm, (RF_RadioSetup*)RF_pCmdRadioSetup_hsm, &rfParams);
            break;
#endif
#if (defined __CC2650EM_7ID_H__) || (defined __CC2650_LAUNCHXL_BOARD_H__) || (defined __CC1350_LAUNCHXL_BOARD_H__) || (defined __CC1350STK_SENSORTAG_BOARD_H__)
        case RfSetup_Ble:

            rfHandle = RF_open(&rfObject, RF_pModeBle, (RF_RadioSetup*)RF_ble_pCmdRadioSetup, &rfParams);
            break;
#endif
        default:
            break;
    }

    /* Set the frequency */
    if(config->rfSetup == RfSetup_Custom)
    {
        //Custom settings exported from SmartRf studio shall use the exported frequency
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    }
#if (defined __CC2650EM_7ID_H__) || (defined __CC2650_LAUNCHXL_BOARD_H__) || (defined __CC1350_LAUNCHXL_BOARD_H__) || (defined __CC1350STK_SENSORTAG_BOARD_H__)
    else if(config->rfSetup == RfSetup_Ble)
    {
        RF_ble_pCmdFs->frequency = config->frequencyTable[config->frequency].frequency;
        RF_ble_pCmdFs->fractFreq = config->frequencyTable[config->frequency].fractFreq;
        RF_runCmd(rfHandle, (RF_Op*)RF_ble_pCmdFs, RF_PriorityNormal, NULL, 0);
    }
#endif
    else
    {
        RF_pCmdFs_preDef->frequency = config->frequencyTable[config->frequency].frequency;
        RF_pCmdFs_preDef->fractFreq = config->frequencyTable[config->frequency].fractFreq;
        RF_runCmd(rfHandle, (RF_Op*)RF_pCmdFs_preDef, RF_PriorityNormal, NULL, 0);
    }

    /* Enter RX mode and stay forever in RX */
    switch (config->rfSetup)
    {
#if !(defined __CC2650EM_7ID_H__) && !(defined __CC2650_LAUNCHXL_BOARD_H__)
        case RfSetup_Hsm:

            rxCmdHndl = RF_postCmd(rfHandle, (RF_Op*)RF_pCmdRxHS, RF_PriorityNormal, &rx_callback, RF_EventRxEntryDone);
            crcOk = &rxStatistics_hs.nRxOk;
            rssi = &rxStatistics_hs.lastRssi;
            break;
#endif
#if (defined __CC2650EM_7ID_H__) || (defined __CC2650_LAUNCHXL_BOARD_H__) || (defined __CC1350_LAUNCHXL_BOARD_H__) || (defined __CC1350STK_SENSORTAG_BOARD_H__)
        case RfSetup_Ble:

            rxCmdHndl = RF_postCmd(rfHandle, (RF_Op*)RF_ble_pCmdBleGenericRx, RF_PriorityNormal, &rx_callback, RF_EventRxEntryDone);
            crcOk = &rxStatistics_ble.nRxOk;
            rssi = &rxStatistics_ble.lastRssi;
            break;
#endif
        default:
#ifndef ADD_MY_CHANGES
            rxCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &rx_callback, RF_EventRxEntryDone);
#endif
            crcOk = &rxStatistics_prop.nRxOk;
            rssi = &rxStatistics_prop.lastRssi;
            break;
    }

    *crcOk = 0;
    *rssi = 0;
    while(true)
    {
#ifndef ADD_MY_CHANGES
        if(packetReceived)
        {
            packetReceived = false;
            menu_updateRxScreen(*crcOk, *rssi);
        }

        if (menu_isButtonPressed())
        {
            /* force abort gracefully */
            RF_cancelCmd(rfHandle, rxCmdHndl, 0);
            RF_pendCmd(rfHandle, rxCmdHndl, RF_EventRxEntryDone);
            RF_close(rfHandle);
            return TestResult_Aborted;
        }
    }
#else
        rxCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &rx_callback, RF_EventRxEntryDone);
        Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
        ret = ((volatile RF_Op*)&RF_cmdPropRx)->status;
        switch(ret)
        {
        case PROP_DONE_OK:
            PIN_setOutputValue(ledPinHandle, Board_LED1, 1); // led on
            CPUdelay((uint32_t)(12000*1)); /* 1ms */
            PIN_setOutputValue(ledPinHandle, Board_LED1, 0); // led off
            status = ret;
            break;
        case PROP_DONE_RXTIMEOUT:
            PIN_setOutputValue(ledPinHandle, Board_LED2, 1); // led on
            CPUdelay((uint32_t)(12000*1)); /* 1ms */
            PIN_setOutputValue(ledPinHandle, Board_LED2, 0); // led off
            status = ret;
            break;
        default:
            PIN_setOutputValue(ledPinHandle, Board_LED3, 1); // led on
            CPUdelay((uint32_t)(12000*1)); /* 1ms */
            PIN_setOutputValue(ledPinHandle, Board_LED3, 0); // led off
            status = ret;
            break;
        }
        menu_updateRxScreen(status, *rssi);
    }
#endif
}

void rx_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
    if (e & RF_EventRxEntryDone)
    {
        /* Get current unhandled data entry */
        currentDataEntry = RFQueue_getDataEntry();

        /* For TC_HSM, the packet length and a pointer to the first byte in the payload can be found as follows:
         *
         * uint8_t packetLength      = ((*(uint8_t*)(&currentDataEntry->data + 1)) << 8) | (*(uint8_t*)(&currentDataEntry->data));
         * uint8_t* packetDataPointer = (uint8_t*)(&currentDataEntry->data + 2);
         *
         * For the other test cases (TC_LRM, TC_OOK and TC_FSK), the packet length and first payload byte is found here:
         *
         * uint8_t packetLength      = *(uint8_t*)(&currentDataEntry->data);
         * uint8_t* packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
         */
        packetReceived = true;
        RFQueue_nextEntry();
    }
#ifdef ADD_MY_CHANGES
    Semaphore_post(semHandle);
#endif
}

  • Hi,

    can you repeat your test using RF_runCmd() for the RX command instead of RF_postCmd() and not using the semaphore? I just want to be 100% sure that the command has really finished. Could you please also test whether you get another unwanted callback by modifying the rx_callback() function? In that case, the semaphore would be posted more often. 

    #include <assert.h>
    
    void rx_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* For TC_HSM, the packet length and a pointer to the first byte in the payload can be found as follows:
             *
             * uint8_t packetLength      = ((*(uint8_t*)(&currentDataEntry->data + 1)) << 8) | (*(uint8_t*)(&currentDataEntry->data));
             * uint8_t* packetDataPointer = (uint8_t*)(&currentDataEntry->data + 2);
             *
             * For the other test cases (TC_LRM, TC_OOK and TC_FSK), the packet length and first payload byte is found here:
             *
             * uint8_t packetLength      = *(uint8_t*)(&currentDataEntry->data);
             * uint8_t* packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
             */
            packetReceived = true;
            RFQueue_nextEntry();
        } else {
    // Stop when getting unwanted callback events assert(false); } #ifdef ADD_MY_CHANGES Semaphore_post(semHandle); #endif }

    Thanks

  • Hi,

    I have done those tests and also added some code to show the event value on the LCD in the case of !(e & RF_EventRxEntryDone)

    Repeating the test using RF_runCmd() instead of RF_postCmd() and not using the semaphore:

    Both Rx and timeout worked relaibly with the Rx period being 50ms but the timeout being 92ms.

    Modifying the callback function as per your code:

    (1) with RF_runCmd() and:

       (a) assert() in place:

           Rx - runs for a short time then asserts

           no Rx - asserts immediately

       (b) changing assert() for (a uint64_t type) event = e:

           the 'other' Rx callback value is 2 (although it could be preceded by another value quicky)

    (2) with RF_postCmd() and:

       (a) assert() in place:

           as above

       (b) changing assert() for (a uint64_t type) event = e:

           as above but when going from state 2 to 3 the status value goes breifly to 1 before going to 2

    Regards,

    David.