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/LAUNCHXL-CC1310: Tx task not getting executed after some period

Part Number: LAUNCHXL-CC1310

Tool/software: TI-RTOS

Hello,

I have written code in which clock module after 5 clock cycles will post semaphore to execute RF Tx task.

Here is my code :

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

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>

/* TI-RTOS Header files */
#include <ti/drivers/PIN.h>
#include <ti/drivers/pin/PINCC26XX.h>
#include <ti/drivers/timer/GPTimerCC26XX.h>

#include <ti/drivers/GPIO.h>

#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>
#include <inc/hw_fcfg1.h>
#include <ti/sysbios/knl/Clock.h>

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

#include "smartrf_settings.h"

#include <ti\devices\cc13x0\driverlib\aon_batmon.h>
#include "stdio.h"

#define  SEND_VIBRATION_ALERT_EVENT              1
/* Pin driver handles */
static PIN_Handle buttonPinHandle;
static PIN_Handle ledPinHandle;

/* Global memory storage for a PIN_Config table */
static PIN_State buttonPinState;
static PIN_State ledPinState;

unsigned char vib_counter = 0;

uint32_t batt_value;

/*
 * Initial LED pin configuration table
 *   - LEDs Board_LED0 is on.
 *   - LEDs Board_LED1 is off.
 */
PIN_Config ledPinTable[] = {
    Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

/*
 * Application button pin configuration table:
 *   - Buttons interrupts are configured to trigger on falling edge.
 */
PIN_Config buttonPinTable[] = {
    Board_BUTTON0  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    Board_BUTTON1  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    Board_DIO1     | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES,
    PIN_TERMINATE
};

GPTimerCC26XX_Handle hTimer;

/***** Defines *****/
#define TX_TASK_STACK_SIZE 2048
#define TX_TASK_PRIORITY   2

/* Packet TX Configuration */
#define PAYLOAD_LENGTH      30
#define PACKET_INTERVAL     (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */



/***** Prototypes *****/
static void txTaskFunction(UArg arg0, UArg arg1);



/***** Variable declarations *****/
static Task_Params txTaskParams;
Task_Struct txTask;    /* not static so you can see in ROV */
static uint8_t txTaskStack[TX_TASK_STACK_SIZE];

Task_Struct task0Struct;
Char task0Stack[TX_TASK_STACK_SIZE];

static RF_Object rfObject;
static RF_Handle rfHandle;

uint32_t curtime;
static uint8_t packet[PAYLOAD_LENGTH];
static uint16_t seqNumber;
static PIN_Handle pinHandle;

Semaphore_Struct semTxStruct;
Semaphore_Handle semTxHandle;


unsigned char vibration = 0;

uint32_t macAddress =  FCFG1_O_MAC_15_4_0;

 char batt[6];

 Void clk0Fxn(UArg arg0);


 Clock_Struct clk0Struct, clk1Struct;
 Clock_Handle clk2Handle;




/*
 *  ======== buttonCallbackFxn ========
 *  Pin interrupt Callback function board buttons configured in the pinTable.
 *  If Board_LED3 and Board_LED4 are defined, then we'll add them to the PIN
 *  callback function.
 */


/*  batmon register format - 32 bit register
 *   most significant 21 bits reserved
 *   bit 10-8  - integer part of battery voltage
 *   bit 7-0   - fraction part of voltage
 *   to get integer part shift register value to right by 8
 *   to get fraction part use 7-4 bits only so shift register value by 4 and AND with 0X0F
 *   multiply with 0.0625
 *   Refer CC1310 Technical Reference Manual pg no - 1432 for info
 *   0x10 - 1/16 = 0.0625v
 *   0x20 - 1/8  = .125 V
 *
 *
 */

void get_battery_voltage(unsigned int value)
{
    double batt_voltage = 0,fraction_part = 0;
    unsigned int integer_part = 0;
    integer_part = value >> 8;
    fraction_part = ((value >> 4) & 0x0F ) * 0.0625;

    batt_voltage = integer_part + fraction_part;
    if(batt_voltage > 2.3)
    {
        integer_part = 0;
    }
    integer_part = 0;
}
void TxTask_init(PIN_Handle inPinHandle)
{
    pinHandle = inPinHandle;

    Task_Params_init(&txTaskParams);
    txTaskParams.stackSize = TX_TASK_STACK_SIZE;
    txTaskParams.priority = TX_TASK_PRIORITY;
    txTaskParams.stack = &txTaskStack;
    txTaskParams.arg0 = (UInt)1000000;

    Task_construct(&txTask, txTaskFunction, &txTaskParams, NULL);
}

static void txTaskFunction(UArg arg0, UArg arg1)
{

    uint32_t curtime;
    RF_Params rfParams;
    RF_CmdHandle cmd_handle;
    RF_Params_init(&rfParams);

    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = packet;
    RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;
    RF_cmdPropTx.startTrigger.pastTrig = 1;
    RF_cmdPropTx.startTime = 0;

    /* Request access to the radio */
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);

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

    /* Get current time */
    curtime = RF_getCurrentTime();
    while(1)
    {
        Semaphore_pend(semTxHandle, BIOS_WAIT_FOREVER);
        printf("In the tx task\r\n");

        /* Create packet with incrementing sequence number and random payload */
        packet[0] = (uint8_t)(seqNumber >> 8);
        packet[1] = (uint8_t)(seqNumber++);

       /* for (i = 2; i < 6; i++)
        {
            //packet[i] = rand();
            packet[i] =  (uint8_t)((macAddress << j) & 0x000000FF);
            j++;
        }*/
        memcpy(&packet[2],&macAddress,4);

        /* Set absolute TX time to utilize automatic power management */
        curtime += PACKET_INTERVAL;
        RF_cmdPropTx.startTime = curtime;


        /* Send packet */
        RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
        if (!(result & RF_EventLastCmdDone))
        {
            /* Error */
            while(1);
        }
        PIN_setOutputValue(pinHandle, Board_LED0,!PIN_getOutputValue(Board_LED0));

        RF_flushCmd( rfHandle, cmd_handle, 1);

        //Semaphore_post(semTxHandle);


    }
}
void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId) {
    uint32_t currVal = 0;

    /* Debounce logic, only toggle if the button is still pushed (low) */
    //CPUdelay(8000*50);
    if (!PIN_getInputValue(pinId)) {
        /* Toggle LED based on the button pressed */
        switch (pinId) {
            case Board_BUTTON0:
                currVal =  PIN_getOutputValue(Board_LED0);
                PIN_setOutputValue(ledPinHandle, Board_LED0, !currVal);
                break;

            case Board_BUTTON1:
                //currVal =  PIN_getOutputValue(Board_LED1);
                //PIN_setOutputValue(ledPinHandle, Board_LED1, !currVal);
                batt_value = AONBatMonBatteryVoltageGet();
                get_battery_voltage(batt_value);
                //AONBatMonDisable();
                GPIO_toggle(Board_LED1) ;


                    //TxTask_init(ledPinHandle);
                    Semaphore_post(semTxHandle);

                break;
            case Board_DIO1:
                //currVal =  PIN_getOutputValue(Board_LED1);
                //PIN_setOutputValue(ledPinHandle, Board_LED1, !currVal);

                break;
            default:
                /* Do nothing */
                break;
        }
    }
}




/*
 *  ======== main ========
 */
int main(void)
{
    /* Call board init functions */
    //GPIO_init();

    Semaphore_Params semParams;

    Error_Block eb;


   Clock_Params clkParams;

   /* Call board init functions */
   Board_initGeneral();



   Clock_Params_init(&clkParams);
   clkParams.period = 1000000/Clock_tickPeriod;
   clkParams.startFlag = TRUE;

   /* Construct a periodic Clock Instance */
   Clock_construct(&clk0Struct, (Clock_FuncPtr)clk0Fxn,
                   1000000/Clock_tickPeriod, &clkParams);

   clkParams.period = 0;
   clkParams.startFlag = FALSE;

   /* Construct a one-shot Clock Instance */

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

    buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable);
    if(!buttonPinHandle) {
        System_abort("Error initializing button pins\n");
    }


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

    Semaphore_Params_init(&semParams);
    Error_init(&eb);
    //Semaphore_construct(&semTxStruct, 0, &semParams);

    /* Obtain instance handle */
    semTxHandle =  Semaphore_create(0, &semParams, &eb);

    TxTask_init(ledPinHandle);

    /* Start kernel. */
    BIOS_start();

    return (0);
}


Void clk0Fxn(UArg arg0)
{
   //UInt32 time;

   //time = Clock_getTicks();
    PIN_setOutputValue(ledPinHandle, Board_LED1, !PIN_getOutputValue(Board_LED1));
   vib_counter++;
   if(vib_counter> 5)
   {

       Semaphore_post(semTxHandle);

       vib_counter = 0;
   }
   //System_printf("System time in clk0Fxn = %lu\n", (ULong)time);

}

Initially, code runs nicely, but after sometimes RF Tx task is not being executed but the clock module is running as I can see the LED toggling and again after sometimes task  exectues .

What can be the reason behind blocking of task as there is no other task running.

  • Hi,

    if you want to send packets after an event happened (button or timer), then I recommend not to use absolute timing, but TRIG_NOW:

    RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;

    You can remove all other code related to startTime. In addition, call RF_yield() after the TX command has completed. You can remove RF_flushCmd() as this is not needed here RF_yield() tells the RF driver that you don't know when the next RF command will be executed and it can  power the RF core down immediately.

    If you want to know the root cause for the observed behavior:

    • The program calculates an absolute TX timestamp
    • Due to Semaphore_pend(semTxHandle, BIOS_WAIT_FOREVER); the calculated timestamp lags behind the real time
    • Due to RF_cmdPropTx.startTrigger.pastTrig = 1; you won't notice that and the TX command will behave like it TRIG_NOW.
    • After 1/4 RAT cycle (~4.5 minutes), the RF core will not interpret startTime as a timestamp in the past, but 12 minutes in the future and will block. 

  • Dear Richard,
    Thank you for profound explanation. Your suggestion resolved my issue and the task is running without blocking.However I would request you to give me web link about the details of RF structure and APIs for more insights.
  • Hi,

    The RF commands are documented in the DriverLib API documentation and there is some (rather unstructured) documentation in the Technical Reference Manual section 23.7. Some basic information about command execution can be found in the Proprietary RF user's guide.