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-CC1310: How to use non blocking Radio Transmit command

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310, CC1350

Hello,

I am using CC1310 Launchpad and CCS to program it. I am building noRTOS application.

I wanted to use a non-blocking Radio Transmit command i.e. RF_postcmd(). I wanted to know how to use it as there are no built-in examples on it in CCS.

Also how to check its status?

Thanks 

  • Hi Gopal, 

    To test the post command I would suggest you to do the following.
    In the rfPacketTx example replace the following lines

            /* Send packet */
            RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx,
                                                       RF_PriorityNormal, NULL, 0);
    
            switch(terminationReason)
            {
                case RF_EventLastCmdDone:
                    // A stand-alone radio operation command or the last radio
                    // operation command in a chain finished.
                    break;
                case RF_EventCmdCancelled:
                    // Command cancelled before it was started; it can be caused
                // by RF_cancelCmd() or RF_flushCmd().
                    break;
                case RF_EventCmdAborted:
                    // Abrupt command termination caused by RF_cancelCmd() or
                    // RF_flushCmd().
                    break;
                case RF_EventCmdStopped:
                    // Graceful command termination caused by RF_cancelCmd() or
                    // RF_flushCmd().
                    break;
                default:
                    // Uncaught error event
                    while(1);
            }

     with 

            RF_CmdHandle cmdhandle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
            RF_pendCmd(rfHandle, cmdhandle, 0);

    Here the postCmd is non blocking, but we are waiting for the command to execute with the RF_pendCmd() with the command handle returned by the RF_postCmd. 

    We are blocking here using the pendCmd() just to maintain the same behavior as the example. You need not pend and are able to do other activities after posting the TX command. 

    The status of the Tx command is a part of the RF_cmdPropTx command structure. So the part of the code  where status is read, can remain as it is.

    You can find the rfPacketTx example in the link below.

    https://dev.ti.com/tirex/explore/node?node=AKVED0I7bXHR.CdCmaDvBA__eCfARaV__LATEST

    Regards,

    Sid

  • I don't want to block it using RF_pendCmd() rather I wanted to know if there is an interrupt that can be used to know when RF_postCmd() gets executed successfully.

  • You can use callbacks for that. Take a look at the rfEchoTx example, there a callback has been used with runCmd. Similarly, you can use postCmd with the callbacks. 

    dev.ti.com/.../node

  • I am generating RTC periodic wake-up and GPIO interrupt wake-up from the standby mode. I declared an array of type int and size 4. when a gpio button interrupts occurs data gets stored into the array. When the array gets completely filled or when RTC wakes up the MCU and at least one data entry is there in the array data will get transmitted. I am using RF_postcmd() to transmit the data
    But the problem is data is not transmitting rest all the functionality is working fine.

    I am using a callback function in RF_postcmd() but this callback function is never called.
    How to resolve this problem. here is the snippet of my code

    /* Standard C Libraries */
    #include <stdlib.h>
    #include <unistd.h>
    #include <stddef.h>
    #include <stdint.h>

    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/devices/cc13x0/driverlib/aon_rtc.h>
    #include <ti/devices/cc13x0/driverlib/aon_event.h>
    #include <ti/devices/cc13x0/driverlib/interrupt.h>
    #include <ti/devices/cc13x0/driverlib/cpu.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <ti/devices/cc13x0/inc/hw_device.h>
    #include DeviceFamily_constructPath(inc/hw_prcm.h)
    #include DeviceFamily_constructPath(driverlib/sys_ctrl.h)
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    #include "Board.h"
    #include "smartrf_settings/smartrf_settings.h"

    /* Packet TX Configuration */
    #define PAYLOAD_LENGTH 6
    #define SIZE 4 // Size of DATA_BUFFER Array

    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;

    /* Pin driver handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;
    static PIN_Handle buttonPinHandle;
    static PIN_State buttonPinState;

    static uint8_t seqNumber;
    static uint8_t packet[PAYLOAD_LENGTH];
    uint8_t INDEX = 0;
    uint8_t RF_BUSY = 0;
    uint8_t EVENT_NUM = 0; // To count how many Interrupts occured
    uint8_t TX_STATUS = 0; // TX status. 1->DATA ready to transmit, 0->DATA not ready to transmit
    uint8_t BTN_INTPT_STATUS = 0; // Button Interrupt status. 1->SET, 0->RESET
    uint8_t RTC_INTPT_STATUS = 0; // RTC Interrupt Status. 1->SET, 0->RESET

    /***** LED PIN CONFIG TABLE *****/
    PIN_Config pinTable[] =
    {
    Board_PIN_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_PIN_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
    };

    /***** INTERRUPT PIN CONFIG TABLE *****/
    PIN_Config buttonPinTable[] = {
    Board_PIN_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    PIN_TERMINATE
    };

    /***** RTC ISR *****/
    void RTC_ISR()
    {
    AONRTCEventClear(AON_RTC_CH0 | AON_RTC_CH1 | AON_RTC_CH2); // Clear the RTC Event and Interrupt
    RTC_INTPT_STATUS = 1; //Set RTC interrupt status high
    }

    /***** Button ISR *****/
    void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId)
    {
    BTN_INTPT_STATUS = 1; //Set Interrupt status high
    }


    /**** RF CallBack ****/
    void RF_CallBack(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    RF_BUSY = 0;
    }

    /***** Function definitions *****/
    void *mainThread(void *arg0)
    {
    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, pinTable);
    if (ledPinHandle == NULL)
    while(1); /* Error initializing LED pins */

    /* Open LED pins */
    buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable);
    if(!buttonPinHandle)
    while(1); /* Error initializing INTERRUPT pins */

    /* Setup callback for button pins */
    if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFxn) != 0) {
    while(1); /* Error registering button callback function */
    }


    RF_Params rfParams;
    RF_Params_init(&rfParams);

    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = packet;
    RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;

    /* Request access to the radio */
    #if defined(DeviceFamily_CC26X0R2)
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioSetup, &rfParams);
    #else
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    #endif// DeviceFamily_CC26X0R2

    /* Set the frequency */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);


    uint8_t DATA_BUF[SIZE]; // Array to store the data


    AONEventMcuWakeUpSet(AON_EVENT_MCU_WU2,AON_EVENT_RTC_CH2|AON_EVENT_IO); // Wake up MCU on RTC channel 2 event or Interrupt on GPIO
    AONRTCModeCh2Set(AON_RTC_MODE_CH2_CONTINUOUS); // Set RTC CH2 in continuous compare mode
    AONRTCCompareValueSet(AON_RTC_CH2,0x000f0000); // Set RTC CH2 compare value to 15sec
    AONRTCIncValueCh2Set(0x000f0000); // Set RTC CH2 to generate event every 15sec
    AONRTCChannelEnable(AON_RTC_CH2); // Enable RTC CH2
    AONRTCCombinedEventConfig(AON_RTC_CH0 | AON_RTC_CH1 | AON_RTC_CH2); // Enable RTC combined event
    IntEnable(INT_AON_RTC_COMB); // Enable RTC Combined Event to wake the CPU from WFI Command
    IntRegister(INT_AON_RTC_COMB,RTC_ISR); // Register RTC Interrupt with RTC_ISR function
    AONRTCEnable(); // Enable RTC


    while(1)
    {
    if(BTN_INTPT_STATUS == 1)
    {
    DATA_BUF[INDEX++] = EVENT_NUM++;
    DATA_BUF[INDEX++] = 1;

    if(INDEX == SIZE && TX_STATUS == 0)
    {
    TX_STATUS = 1;
    INDEX = 0;
    }
    BTN_INTPT_STATUS = 0;
    }


    if(RTC_INTPT_STATUS == 1)
    {
    if(INDEX > 0 && TX_STATUS == 0)
    TX_STATUS = 1;

    RTC_INTPT_STATUS = 0;
    }


    if(TX_STATUS == 1 && RF_BUSY == 0)
    {
    //Create packet with incrementing sequence number and random payload
    packet[0] = (uint8_t)(seqNumber >> 8);
    packet[1] = (uint8_t)(seqNumber++);

    uint8_t i;
    for(i = 2; i < PAYLOAD_LENGTH; i++)
    {
    packet[i] = DATA_BUF[i-2];
    }

    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal,&RF_CallBack, 0);
    TX_STATUS = 0;
    RF_BUSY = 1;
    }

    if(RF_BUSY == 0)
    PowerCC26XX_standbyPolicy();
    }
    }

  • There are a couple of things you need to check. 

    1. The postCmd returns a command handle, check if this is a valid command handle. 

    2. In a debug session put a breakpoint at RF_postCmd, to make sure the postCmd is actually executed.

    Regards,

    Sid

  • I put the breakpoint on the Callback function as the callback function will only be called when RF_postcmd() gets executed. Now in my case callback function is never called as the debugger is never stopping at callback function.

    Another thing I want to say is when I comment the RTC event code and keeps other things the same then data gets transmitted successfully and RF_postcmd() is returning a valid command handle like 2, 3, 4, 5, 6 etc.

  • Can you please elaborate on what your application needs to do? If you are trying to wake the device up for transmission, there maybe simpler ways to do it.

    If you use the TI drivers and examples in the SDK, the power management is taken care of by the drivers to give optimal power performance. 

  • I have the following requirements for my project

    1. I need to transmit data set 1 when interrupts occur, and it goes to sleep mode in-between times.

    2. Periodically, it needs to wake up from power-down modes and send another data set.

    I am using GPIO interrupt to trigger transmission of data set 1.

    & Using RTC to periodically wake up the device to trigger the transmission of data set 2

    But I am facing a problem with RTC. when It gets wakes up it is not transmitting the data.

  • Have you verified that the device actually wakes up on the RTC interrupt? 

  • Yes, the device wakes up upon RTC interrupt

  • Can you put a break point in this line. 

    RTC_INTPT_STATUS = 0;

    And check the value of the variable TX_STATUS at this point, ensure it is 1. 

    And then put a break point after this line

    if(TX_STATUS == 1 && RF_BUSY == 0)

    To ensure it actually posts the required TX command. 
    We need to figure out which part of the code is not being reached or if we are actually posting a TX command.

    Regards,
    Sid 

  • Yes the TX_STATUS sets to 1 & it also enters into if(TX_STATUS==1 && RF_BUSY==0).
    as I said the problem is RF_postCmd() is executing but the callback is never called.

  • Here you mentioned that when RTC code is commented out, RF_postCmd() gives proper command handle. 

    Another thing I want to say is when I comment the RTC event code and keeps other things the same then data gets transmitted successfully and RF_postcmd() is returning a valid command handle like 2, 3, 4, 5, 6 etc.

    What is the returned handle in this case, when the RF_postCmd() is executed at the RTC interrupt?

    Yes the TX_STATUS sets to 1 & it also enters into if(TX_STATUS==1 && RF_BUSY==0).
    as I said the problem is RF_postCmd() is executing but the callback is never called.

    It is worth to check if the postCmd returns a valid command handle or not at this point.

  • It passes a value of 2 which is a valid command handle.

  • Is it possible for you to share the project with us? We need to reproduce the issue you are seeing, to see why the Radio is not transmitting even after the TX command got a valid command handle.  

  • Here is the drive link for my project.
    Project URL

  • Hi Gopal,

    I debugged your project without any changes and never pressed a button. I placed break points in

    1. RTC_ISR(). Which it reaches.

    2. Break point in the while loop here as shown in the image. If you notice the value of TX_STATUS here , it is not set to 1. 

    So it never reaches my third breakpoint at RF_postCmd(), So it did not post the TX command at all. 

    If there have been any code modifications after you verified that RF_postCmd() is is executing, please re-check the logic and ensure that the command is posted.

    Regards,

    Sid

  • Sir,

    There is a condition (index>0) for RTC to post TX_STATUS i.e. at least one data should be present in Array "DATA_BUF". Data will be inserted into it when the button is pressed.

    since you never pressed the button so no data was present in the array and RTC didn't post the TX_STATUS. so it never reaches to the third breakpoint

  • In that case, after pressing the button once. When the RTC_ISR is triggered, I do see that the TX_STATUS is 1 and RF_BUSY is 0. 
    It reaches the breakpoint at RF_postCmd(), and then it also reaches the break point in the RF_callback() every time. 

    Not sure, when you are seeing the failure condition.

  • Sir,

    I am uploading a video to show my problem. After pressing the button once. when RTC_ISR is triggered, the TX_STATUS is 1 and RF_BUSY is 0. Also, it reaches the breakpoint at RF_postCmd() but after that, it never reaches the breakpoint in RF_callback().

    First I thought it was a hardware problem so I run the same project on CC1350 but this board is also facing the same problem i.e. without RTC it reaches the breakpoint in RF_Callback but when RTC is included it never reaches the breakpoint in RF_callback().

    I am uploading the videos for both boards. (CC1310 & CC1350)

    Also, Did you introduce any changes to the code?

    Video URL

  • Hi Gopal,

    Try these changes in your code. I saw the behavior you mentioned. I think it is a race condition. 

    We need to ensure that the CmdFS is executed,  before you do a Tx. To ensure this, I changed the line 

        /* Set the frequency */
        // RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);

    After this change, it seems to be working fine.

    Regards,

    Sid

  • Thanks This Problem is solved