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: Switching between tasks with Semaphores

Part Number: CC1310

Tool/software: TI-RTOS

Hello,

I am having some issues switching back and forth between tasks. In my RTOS program I have four tasks, UART receive, RF transmit, RF receive, and Power shutdown. I have set up semaphores to switch between these tasks, but when I run through them once, I can not switch back to a task. Is this an issue with task priority? I have posted my code below, thanks for any help in advance!

Thanks,

William

/***** Includes *****/
/* Standard C Libraries */
#include <stdlib.h>

/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/Assert.h>
#include <xdc/runtime/Error.h>
#include <xdc/cfg/global.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Swi.h>

/* TI Drivers */
#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/pin/PINCC26XX.h>
#include <ti/devices/cc13x0/driverlib/timer.h>
#include <ti/drivers/power/PowerCC26XX.h>
#include <ti/drivers/UART.h>
#include <ti/devices/cc13x0/driverlib/timer.h>
#include <ti/drivers/Power.h>
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(inc/hw_prcm.h)
#include DeviceFamily_constructPath(driverlib/sys_ctrl.h)

/* Driverlib Header files */
#include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)

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

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

/***** Defines *****/
#define TX_RF_TASK_STACK_SIZE 1024
#define TX_RF_TASK_PRIORITY   3

#define RX_RF_TASK_STACK_SIZE 1024
#define RX_RF_TASK_PRIORITY   2

#define RX_UART_TASK_STACK_SIZE 1024
#define RX_UART_TASK_PRIORITY  5

#define POWER_SHUTDOWN_TASK_STACK_SIZE 1024
#define POWER_SHUTDOWN_TASK_PRIORITY  4

/* RF_RxPacket TX Configuration */
#define PAYLOAD_LENGTH         41
#define RF_RxPacketSizeVariable  1
#define RF_RxPacket_INTERVAL     (uint32_t)(4000000*0.5f) /* Set RF_RxPacket interval to 500ms */

/* RF_RxPacket RX Configuration */
#define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */
#define MAX_LENGTH             41 /* 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  /* The Data Entries data field will contain:
                                   * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
                                   * Max 30 payload bytes
                                   * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */

/***** Prototypes *****/
static void txTaskFunction(UArg arg0, UArg arg1);
static void RxUARTTaskFunction(UArg arg0, UArg arg1);
static void rxTaskFunction(UArg arg0, UArg arg1);
static void PowerShutdownTaskFunction(UArg arg0, UArg arg1);
void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
static void buttonCb(PIN_Handle handle, PIN_Id pinId);
static void buttonClockCb(UArg arg);
void shutDownFunc(void);

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

static Task_Params rxTaskParams;
Task_Struct rxTask;    /* not static so you can see in ROV */
static uint8_t rxTaskStack[RX_RF_TASK_STACK_SIZE];

static Task_Params rxUartTaskParams;
Task_Struct uartTask;    /* not static so you can see in ROV */
static uint8_t rxUartTaskStack[RX_UART_TASK_STACK_SIZE];

static Task_Params powerShutdownTaskParams;
Task_Struct ShutdownTask;    /* not static so you can see in ROV */
static uint8_t ShutdownTaskStack[ POWER_SHUTDOWN_TASK_STACK_SIZE];

static RF_Object rfObject;
static RF_Handle rfHandle;

Semaphore_Struct semRFTxStruct;
Semaphore_Handle semRFTxHandle;

Semaphore_Struct semUARTRxStruct;
Semaphore_Handle semUARTRxHandle;

Semaphore_Struct semRFRxStruct;
Semaphore_Handle semRFRxHandle;

/* Semaphore used to gate for shutdown */
Semaphore_Struct semShutdownStruct;
Semaphore_Handle semShutdownHandle;

/* Clock used for debounce logic */
Clock_Struct buttonClock;
Clock_Handle  hButtonClock;

/* Pin driver handles */
PIN_Handle hPins;
PIN_Handle hButtons;

/* Button pin state */
PIN_State buttonState;

/* Flag to store whether we woke up from shutdown or not */
bool isWakingFromShutdown;

/* PIN_Id for active button (in debounce period) */
PIN_Id activeButtonPinId;

/* Wake-up Button pin table */
PIN_Config ButtonTableWakeUp[] = {
    CC1310DK_4XD_DIO24_ANALOG   | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE,
    PIN_TERMINATE                                 /* Terminate list */
};

/* Shutdown Button pin table */
PIN_Config ButtonTableShutdown[] = {
    CC1310DK_4XD_DIO24_ANALOG   | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    PIN_TERMINATE                                 /* Terminate list */
};

/* 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

/* Receive dataQueue for RF Core to fill in data */
static dataQueue_t dataQueue;
static rfc_dataEntryGeneral_t* currentDataEntry;
static uint8_t RF_RxPacketLength;
static uint8_t* RF_RxPacketDataPointer;

unsigned char UART_Input[PAYLOAD_LENGTH];
unsigned char RF_TxRF_RxPacket[PAYLOAD_LENGTH];
unsigned char RF_RxPacketSize[RF_RxPacketSizeVariable];
unsigned char RF_RxPacket[PAYLOAD_LENGTH];

/***** Function definitions *****/

void TxRFTask_init()
{
    Task_Params_init(&txTaskParams);
    txTaskParams.stackSize = TX_RF_TASK_STACK_SIZE;
    txTaskParams.priority = TX_RF_TASK_PRIORITY;
    txTaskParams.stack = &txTaskStack;
    txTaskParams.arg0 = (UInt)1000000;
    Task_construct(&txTask, txTaskFunction, &txTaskParams, NULL);
}

void RxUARTTask_init()
{
    Task_Params_init(&rxUartTaskParams);
    rxUartTaskParams.stackSize = RX_UART_TASK_STACK_SIZE;
    rxUartTaskParams.priority = RX_UART_TASK_PRIORITY;
    rxUartTaskParams.stack = &rxUartTaskStack;
    rxUartTaskParams.arg0 = (UInt)1000000;
    Task_construct(&uartTask, RxUARTTaskFunction, &rxUartTaskParams, NULL);
}

void RxRFTask_init()
{
    Task_Params_init(&rxTaskParams);
    rxTaskParams.stackSize = RX_RF_TASK_STACK_SIZE;
    rxTaskParams.priority = RX_RF_TASK_PRIORITY;
    rxTaskParams.stack = &rxTaskStack;
    rxTaskParams.arg0 = (UInt)1000000;
    Task_construct(&rxTask, rxTaskFunction, &rxTaskParams, NULL);
}

void PowerShutdownTask_init()
{
    Task_Params_init(&powerShutdownTaskParams);
    powerShutdownTaskParams.stackSize = POWER_SHUTDOWN_TASK_STACK_SIZE;
    powerShutdownTaskParams.priority = POWER_SHUTDOWN_TASK_PRIORITY;
    powerShutdownTaskParams.stack = &ShutdownTaskStack;
    powerShutdownTaskParams.arg0 = (UInt)1000000;
    Task_construct(&ShutdownTask, PowerShutdownTaskFunction, &powerShutdownTaskParams, NULL);
}

static void RxUARTTaskFunction(UArg arg0, UArg arg1)
{
    if (isWakingFromShutdown)
    {
        Semaphore_pend(semUARTRxHandle, BIOS_WAIT_FOREVER);
        /* Call driver init functions */
        GPIO_init();
        UART_init();

        int bufclear;
        int readShift;

        UART_Handle uart;
        UART_Params uartParams;

        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 9600;
        uartParams.readMode = UART_MODE_BLOCKING;
        uartParams.writeMode = UART_MODE_BLOCKING;
        uartParams.readTimeout = 10000000;
        uartParams.writeTimeout = UART_WAIT_FOREVER;
        uartParams.readCallback = NULL;
        uartParams.writeCallback = NULL;
        uartParams.dataLength = UART_LEN_8;
        uartParams.stopBits = UART_STOP_ONE;
        uartParams.parityType = UART_PAR_NONE;

        uart = UART_open(Board_UART0, &uartParams);

        if (uart == NULL)        /* UART_open() failed */
            {
                while (1);
            }

      /* memset(RF_RxPacketSize,0,1);
        for(bufclear = 0; bufclear < 1; bufclear++)
            {
                UART_read(uart, RF_RxPacketSize, 1);
                memset(RF_RxPacketSize, NULL ,1);
            }

        unsigned char UART_Input[PAYLOAD_LENGTH];

        UART_read(uart, RF_RxPacketSize, 1);
        for(readShift = 0; readShift < 1; readShift++)
            {
                RF_RxPacketSize[readShift] = UART_Input[readShift];
            }
        memset(RF_RxPacketSize,0,2);

        memset(UART_Input, 0, 41);
        for(bufclear = 0; bufclear < 41; bufclear++)
            {
                UART_read(uart, UART_Input, 41);
                memset(UART_Input, NULL, 41 );
            }

        UART_read(uart, UART_Input, 41);
        for(readShift = 0; readShift < 41; readShift++)
            {
                RF_TxRF_RxPacket[readShift] = UART_Input[readShift];
            }
        memset(UART_Input, 0, 41);

        UART_close(uart);*/

        Semaphore_post(semRFTxHandle);

    }
    else
    {
        //post shutdown semaphore
        Semaphore_post(semShutdownHandle);
    }
}


static void txTaskFunction(UArg arg0, UArg arg1)
{
    /*Ready for transmission*/
    Semaphore_pend(semRFTxHandle, BIOS_WAIT_FOREVER);

    uint32_t curtime;

    RF_Params rfParams;
    RF_Params_init(&rfParams);

    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = RF_TxRF_RxPacket;
    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 */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);

    /* Get current time */
    curtime = RF_getCurrentTime();

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

    /* Send RF_RxPacket */
    RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx,
                                               RF_PriorityNormal, NULL, 0);

    switch(terminationReason)
    {
        case RF_EventCmdDone:
            // A radio operation command in a chain finished
            break;
        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
            Assert_isTrue(false, NULL);
    }

    uint32_t cmdStatus = ((volatile RF_Op*)&RF_cmdPropTx)->status;
    switch(cmdStatus)
    {
        case PROP_DONE_OK:
            // RF_RxPacket transmitted successfully
            break;
        case PROP_DONE_STOPPED:
            // received CMD_STOP while transmitting RF_RxPacket and finished
            // transmitting RF_RxPacket
            break;
        case PROP_DONE_ABORT:
            // Received CMD_ABORT while transmitting RF_RxPacket
            break;
        case PROP_ERROR_PAR:
            // Observed illegal parameter
            break;
        case PROP_ERROR_NO_SETUP:
            // Command sent without setting up the radio in a supported
            // mode using CMD_PROP_RADIO_SETUP or CMD_RADIO_SETUP
            break;
        case PROP_ERROR_NO_FS:
            // Command sent without the synthesizer being programmed
            break;
        case PROP_ERROR_TXUNF:
            // TX underflow observed during operation
            break;
        default:
            // Uncaught error event - these could come from the
            // pool of states defined in rf_mailbox.h
            Assert_isTrue(false, NULL);
    }

    RF_close(rfHandle);

    Semaphore_post(semRFRxHandle);

}

static void rxTaskFunction(UArg arg0, UArg arg1)
{
    Semaphore_pend(semRFRxHandle, BIOS_WAIT_FOREVER);
    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(1);
    }

    /* Modify CMD_PROP_RX command for application needs */
    RF_cmdPropRx.pQueue = &dataQueue;           /* Set the Data Entity queue for received data */
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;  /* Discard ignored RF_RxPackets from Rx queue */
    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;   /* Discard RF_RxPackets with CRC error from Rx queue */
    RF_cmdPropRx.maxPktLen = MAX_LENGTH;        /* Implement RF_RxPacket length filtering to avoid PROP_ERROR_RXBUF */
    RF_cmdPropRx.pktConf.bRepeatOk = 0;
    RF_cmdPropRx.pktConf.bRepeatNok = 0;

    if (!rfHandle) {
        /* Request access to the radio */
        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);
    }

    /* Enter RX mode and wait for response*/
    // RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);

    RF_CmdHandle rx_cmd = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);

    CPUdelay(160000); /* Wait for x/3 cycles*/

    RF_cancelCmd(rfHandle, rx_cmd, 0);  /* Abort the RF rx_cmd */
}

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

        /* Handle the RF_RxPacket data, located at &currentDataEntry->data:
         * - Length is the first byte with the current configuration
         * - Data starts from the second byte */
        RF_RxPacketLength      = *(uint8_t*)(&currentDataEntry->data);
        RF_RxPacketDataPointer = (uint8_t*)(&currentDataEntry->data + 1);

        /* Copy the payload + the status byte to the RF_RxPacket variable */
        memcpy(RF_RxPacket, RF_RxPacketDataPointer, (RF_RxPacketLength + 1));

        RFQueue_nextEntry();

        //if data is good
        Semaphore_post(semShutdownHandle);
        //else post rftx
    }
}

static void PowerShutdownTaskFunction(UArg arg0, UArg arg1)
{
    shutDownFunc();
}

static void buttonClockCb(UArg arg) {
    PIN_Handle buttonHandle = (PIN_State *) arg;

    /* Stop the button clock */
    Clock_stop(hButtonClock);

    /* Check that there is active button for debounce logic*/
    if (activeButtonPinId != PIN_TERMINATE) {
        /* Debounce logic, only toggle if the button is still pushed (low) */
        if (!PIN_getInputValue(activeButtonPinId)) {
            /* Toggle LED based on the button pressed */
            switch (activeButtonPinId) {
            case Board_PIN_BUTTON1:
                Semaphore_post(semShutdownHandle);
                break;
            default:
                /* Do nothing */
                break;
            }
        }
    }

    /* Re-enable interrupts to detect button release. */
    PIN_setConfig(buttonHandle, PIN_BM_IRQ, activeButtonPinId | PIN_IRQ_NEGEDGE);

    /* Set activeButtonPinId to none... */
    activeButtonPinId = PIN_TERMINATE;
}

static void buttonCb(PIN_Handle handle, PIN_Id pinId) {
    /* Set current pinId to active */
    activeButtonPinId = pinId;

    /* Disable interrupts during debounce */
    PIN_setConfig(handle, PIN_BM_IRQ, activeButtonPinId | PIN_IRQ_DIS);

    /* Set timeout 50 ms from now and re-start clock */
    Clock_setTimeout(hButtonClock, (50 * (1000 / Clock_tickPeriod)));
    Clock_start(hButtonClock);
}

void shutDownFunc(void)
{
        /* Pend on semaphore before going to shutdown */
        Semaphore_pend(semShutdownHandle, BIOS_WAIT_FOREVER);

        /* Configure DIO for wake up from shutdown */
        PINCC26XX_setWakeup(ButtonTableWakeUp);

        /* Go to shutdown */
        Power_shutdown(0, 0);

        /* Should never get here, since shutdown will reset. */
        while(1);

}

/*
 *  ======== main ========
 */
int main(void)
{
    /* Get the reason for reset */
     uint32_t rSrc = SysCtrlResetSourceGet();

    if(rSrc == RSTSRC_WAKEUP_FROM_SHUTDOWN)
    {
        /* Call driver init functions. */
        Board_initGeneral();
        isWakingFromShutdown = true;
    }
    else
    {
        Board_initGeneral();
        isWakingFromShutdown = false;
    }

    /* Setup button pins with ISR */
    hButtons = PIN_open(&buttonState, ButtonTableShutdown);
    PIN_registerIntCb(hButtons, buttonCb);

    /* Construct clock for debounce */
    Clock_Params clockParams;
    Clock_Params_init(&clockParams);
    clockParams.arg = (UArg)hButtons;
    Clock_construct(&buttonClock, buttonClockCb, 0, &clockParams);
    hButtonClock = Clock_handle(&buttonClock);

    Semaphore_Params semParams;
    /* Construct a Semaphore object to be used as a resource lock, inital count 0 */
    Semaphore_Params_init(&semParams);
    Semaphore_construct(&semRFTxStruct, 0, &semParams);
    Semaphore_construct(&semUARTRxStruct, 1, &semParams);
    Semaphore_construct(&semRFRxStruct, 0, &semParams);
    Semaphore_construct(&semShutdownStruct, 0, &semParams);

    /* Obtain instance handle */
    semRFTxHandle = Semaphore_handle(&semRFTxStruct);
    semUARTRxHandle = Semaphore_handle(&semUARTRxStruct);
    semRFRxHandle = Semaphore_handle(&semRFRxStruct);
    semShutdownHandle = Semaphore_handle(&semShutdownStruct);

    /* Initialize tasks */
    RxUARTTask_init();
    TxRFTask_init();
    RxRFTask_init();
    PowerShutdownTask_init();

    /* Start BIOS */
    BIOS_start();

    return (0);
}