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.

CCS/TM4C1294NCPDT: RTOS Semaphore issue

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: SYSBIOS

Tool/software: Code Composer Studio

Hello everybody,

I modified the empty.c RTOS example and created 2 tasks that are sharing the same resource (LED) with a semaphore. But I guess the semphore that I have created is not doing what it suppose to :(

I would be very thankful for any kind of input.

I am posting my code below:

/*
* Copyright (c) 2015, 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.
*/

/*
* ======== empty.c ========
*/
/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>

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

/* TI-RTOS Header files */
// #include <ti/drivers/EMAC.h>
#include <ti/drivers/GPIO.h>
// #include <ti/drivers/I2C.h>
// #include <ti/drivers/SDSPI.h>
// #include <ti/drivers/SPI.h>
// #include <ti/drivers/UART.h>
// #include <ti/drivers/USBMSCHFatFs.h>
// #include <ti/drivers/Watchdog.h>
// #include <ti/drivers/WiFi.h>

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

#define TASKSTACKSIZE 512

Task_Struct task0Struct;
Char task0Stack[TASKSTACKSIZE];

Task_Struct task1Struct;
Char task1Stack[TASKSTACKSIZE];

Semaphore_Handle sem;
Semaphore_Params semParams;

/*
* ======== heartBeatFxn ========
* Toggle the Board_LED0. The Task_sleep is determined by arg0 which
* is configured for the heartBeat Task instance.
*/

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Task_0 */
Void heartBeatFxn0(UArg arg0, UArg arg1)
{
int i=0;
while (1) {
Semaphore_pend(sem, 0);
Task_sleep((unsigned int)arg0);
GPIO_toggle(Board_LED0);
Semaphore_post(sem);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Task_1 */
Void heartBeatFxn1(UArg arg0, UArg arg1)
{
while (1) {
Semaphore_pend(sem, 0);
Task_sleep((unsigned int)arg1);
GPIO_toggle(Board_LED0);
Semaphore_post(sem);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
* ======== main ========
*/
int main(void)
{
Task_Params taskParams;
Task_Params taskParams1;
/* Call board init functions */
Board_initGeneral();
// Board_initEMAC();
Board_initGPIO();
// Board_initI2C();
// Board_initSDSPI();
// Board_initSPI();
// Board_initUART();
// Board_initUSB(Board_USBDEVICE);
// Board_initUSBMSCHFatFs();
// Board_initWatchdog();
// Board_initWiFi();

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Creating a semaphore */
Semaphore_Params_init(&semParams);
sem = Semaphore_create(0, &semParams, NULL); /* Memory allocated in here */

if (sem == NULL) /* Check if the handle is valid */
{
System_abort("Semaphore could not be created");
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/* Construct heartBeat Task thread */
Task_Params_init(&taskParams);
taskParams.arg0 = 100;
taskParams.stackSize = TASKSTACKSIZE;
taskParams.stack = &task0Stack;
Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn0, &taskParams, NULL);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Construct heartBeat Task thread */
Task_Params_init(&taskParams1);
taskParams1.arg1 = 89;
taskParams1.stackSize = TASKSTACKSIZE;
taskParams1.stack = &task1Stack;
Task_construct(&task1Struct, (Task_FuncPtr)heartBeatFxn1, &taskParams1, NULL);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Turn on user LED */
GPIO_write(Board_LED0, Board_LED_ON);
//GPIO_write(Board_LED1, Board_LED_ON);
System_printf("Starting the example\nSystem provider is set to SysMin. "
"Halt the target to view any SysMin contents in ROV.\n");
/* SysMin will only print to the console when you call flush or exit */
System_flush();

/* Start BIOS */
BIOS_start();

return (0);
}

 

  • I am not sure what you are trying to do. You create a semaphore and two tasks. But in each task you pend on the semaphore with a 0 wait time, but don't check the return value. That will accomplish nothing. What you did was check the value of the semaphore, but don't wait for it to become valid and don't check if it was valid or not. Take a look at this training starting on page 8-10. It might help you understand the semaphores better.

    https://training.ti.com/sites/default/files/docs/TI_RTOS_Kernel_Workshop_Student_Guide_rev4.00.pdf

  • If you are trying to use a semaphore as a mutex, there is an example available in Resource Explorer called "Task Mutex Example".

  • Hello Bob,

    Thanks alot for your input. I read the training you posted and it was helpful. And I am not sure where to check the validity of the semaphore. The mutex example is a bit sophisticated for me since I am being unable to use semaphores correctly.

    All i am trying to do is to to protect the "Board_LED0"  which is being accessed by 2 different tasks. first task should blink the led twice for 500ms and the task should blink the led 3 times  for 5000ms and thats it.

    I am posting a segment of my code.

    Void heartBeatFxn0(UArg arg0, UArg arg1)
    {
    int i = 0;
    while (1) {
    Semaphore_pend(sem, BIOS_WAIT_FOREVER);

    for (i; i <2; i++){
    Task_sleep((unsigned int)arg0);
    GPIO_toggle(Board_LED0);
    }
    Semaphore_post(sem);

    }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Task_1 */
    Void heartBeatFxn1(UArg arg0, UArg arg1)
    {
    int i = 0;
    while (1) {
    Semaphore_pend(sem, BIOS_WAIT_FOREVER);
    for (i; i <3; i++){
    Task_sleep((unsigned int)arg1);
    GPIO_toggle(Board_LED0);
    }

    Semaphore_post(sem);
    }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /*
    * ======== main ========
    */
    int main(void)
    {
    Task_Params taskParams;
    Task_Params taskParams1;
    /* Call board init functions */
    Board_initGeneral();
    // Board_initEMAC();
    Board_initGPIO();
    // Board_initI2C();
    // Board_initSDSPI();
    // Board_initSPI();
    // Board_initUART();
    // Board_initUSB(Board_USBDEVICE);
    // Board_initUSBMSCHFatFs();
    // Board_initWatchdog();
    // Board_initWiFi();

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Creating a semaphore */
    Semaphore_Params_init(&semParams);
    sem = Semaphore_create(1, &semParams, NULL); /* Memory allocated in here */

    if (sem == NULL) /* Check if the handle is valid */
    {
    System_abort("Semaphore could not be created");
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /* Construct heartBeat Task_0 thread */
    Task_Params_init(&taskParams);
    taskParams.arg0 = 500;
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task0Stack;
    Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn0, &taskParams, NULL);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Construct heartBeat Task_1 thread */
    Task_Params_init(&taskParams1);
    taskParams1.arg1 = 5000;
    taskParams1.stackSize = TASKSTACKSIZE;
    taskParams1.stack = &task1Stack;
    Task_construct(&task1Struct, (Task_FuncPtr)heartBeatFxn1, &taskParams1, NULL);

    Best regards,

    Noori

  • OK, the first recommendation is that you use the </> icon when posting code examples. It will preserve the formatting and will look like this:

    #include <stdint.h>
    #include <stdbool.h>
    
    /*
     *  ======== empty_min.c ========
     */
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    
    /* Board Header file */
    #include "Board.h"
    
    #define TASKSTACKSIZE 512
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    
    Task_Struct task1Struct;
    Char task1Stack[TASKSTACKSIZE];
    
    Semaphore_Handle sem;
    Semaphore_Params semParams;
    
    Void heartBeatFxn0(UArg arg0, UArg arg1)
    {
        int i;
        while (1)
        {
            Semaphore_pend(sem, BIOS_WAIT_FOREVER);
    
            for (i = 0; i <2; i++)
            {
                GPIO_write(Board_LED0, Board_LED_ON);
                Task_sleep(250);
                GPIO_write(Board_LED0, Board_LED_OFF);
                Task_sleep(250);
            }
            Semaphore_post(sem);
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Task_1 */
    Void heartBeatFxn1(UArg arg0, UArg arg1)
    {
        int i;
        while (1)
        {
            Semaphore_pend(sem, BIOS_WAIT_FOREVER);
            for (i = 0; i <3; i++)
            {
                GPIO_write(Board_LED0, Board_LED_ON);
                Task_sleep(2500);
                GPIO_write(Board_LED0, Board_LED_OFF);
                Task_sleep(2500);
            }
            Semaphore_post(sem);
        }
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        Task_Params taskParams;
        Task_Params taskParams1;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
    
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /* Creating a semaphore */
        Semaphore_Params_init(&semParams);
        semParams.mode = Semaphore_Mode_BINARY;
        sem = Semaphore_create(1, &semParams, NULL); /* Memory allocated in here */
        if (sem == NULL) /* Check if the handle is valid */
        {
            System_abort("Semaphore could not be created");
        }
        Semaphore_post(sem);
    
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
        /* Construct heartBeat Task_0 thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 500;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn0, &taskParams, NULL);
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /* Construct heartBeat Task_1 thread */
        Task_Params_init(&taskParams1);
        taskParams1.arg1 = 5000;
        taskParams1.stackSize = TASKSTACKSIZE;
        taskParams1.stack = &task1Stack;
        Task_construct(&task1Struct, (Task_FuncPtr)heartBeatFxn1, &taskParams1, NULL);
    
    
        /* Turn on user LED  */
        GPIO_write(Board_LED0, Board_LED_ON);
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

    Since you are using the semaphore as a MUTEX to control access to hardware, I suggest that you use a binary semaphore instead of a counting semaphore and that you set it to 1 (true) before the call to BIOS_start(). The semaphore is created as a binary semaphore by line 85 above, and it is set to 1 by line 91.

    In the tasks you must initialize the variable i in the "for" loop. The "for" loop is called multiple times. Lines 41 and 59. 

    Finally, I was not sure what you meant by "blink two times for 500mS". I took that to mean 250mS on and 250mS off two times. Of course you can easily change that. Hope this helps.

  • I always see these things after I post. I just noticed you set the semaphore count to one when you created the semaphore. Line 91 is not necessary.

  • Hi Bob,

    now I guess I understand the semaphores better than before and gonna play around with them.

    Thanks alot for your speedy response, really appreciate it.

    Br

    Noori