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-CC26X2R1: Semaphore Placement and Configuration

Part Number: LAUNCHXL-CC26X2R1
Other Parts Discussed in Thread: AFE4404, CC2640

Tool/software: TI-RTOS

Hello TI Experts,

I am currently working on a project involving a CC26x2 chip integrated with an AFE4404, ADXL345, and a microSD card slot.  This project is a continuation from a previous board which used the CC2640. The last build had some threading issues and I want to ensure that we avoid them in this new build. Here’s some background on how the device functions:

Sensor Controller Studio (SCS) collects 14 samples from the AFE4404 then a sample (x, y, z) from the ADXL345 through I2C set at 400 KHz. This process continues until an internal buffer in SCS generates an alert to wake the cc26x2 up and empty the SCS buffer. Task1 continuously checks for the SCS interrupt and when one is detected the outputted SCS buffer is received and then parsed into individual samples by task1. These samples are then sent to a ping-pong buffer by Task1.  The general structure of this Task1 is shown below:

Initialize AFE, UART, I2C, SPI, ADXL345, microSD (FATFS), Pins, mem/buffers, and SCS.
Semaphore_Params semParams;
Semaphore_Params_init(&semParams);
Semaphore_construct(&semMainLoop, 0, &semParams);
hSemMainLoop = Semaphore_handle(&semMainLoop);
scifClearAlertIntSource();
while(1)
{
	Check if time to sync
	semaphore_pend(hSemMainLoop, BIOS_WAIT_FOREVER);
	scifClearAlertIntSource();
	Check SCS cfg variables to see how full SCS buffer is.
		If cfg variable indicated full or almost full, the buffer is emptied.
	ScifAckAlertEvents();
}

 

When one of the ping-pong buffer is approaching fullness, a semaphore is posted and Task2 is used to write the ping-pong buffer data to a microSD card through SPI. The general structure of Task 2 is shown below:

Semaphore_Params semParams2;
Semaphore_Params_init(&semParams2);
Semaphore_construct(&semWriteSD, 0, &semParams2);
hSemWriteSD = Semaphore_handle(&semWriteSD);
while(1)
{
	Semaphore_pend(hSemWriteSD, BIOS_WAIT_FOREVER);
	writeToSD();
}

 Additionally, a periodic clock instance is started prior to the call to BIOS_Start(), and is triggered approximately every 11 seconds. When triggered, a variable is set to true, and during the next write of data to the SD card, an f_sync operation occurs.  

 


Some questions:

1. Does this approach appear to be correct? 

2. According to documentation, semaphores are by default counting.  Is this a good setting for the tasks I have outlined?

3. Should there be priorities set for the semaphores mentioned?  If so how would you go about determining which would be best for prioritization?

 

Thanks!

- Stephen

 

 

 

 

  • Hi Stephen,

    When posting code onto the forum, please use the code formatting tool marked by the </> button. This allows the code to be easily read and can help you get support faster on the forums.

    How is hSemMainLoop and hSemWriteSD posted to? And by whom?
  • Hello,

    Thanks for the information on posting code, my apologies for the format of the last post.

    hSemMainLoop is posted within Task1 by the following code:

     

    scifOsalInit();
    scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);
    scifInit(&scifDriverSetup);

    void scTaskAlertCallback(void) 
    { 
        Semaphore_post(hSemMainLoop); 
    }
    

     

    hsemWriteSD is also posted within the context of Task1 by the following code:

    void postSemToWrite()
    {
        Semaphore_post(hSemWriteSD);
    }

    Also, this is the setup of the Tasks prior to the call to BIOS_start():

        Task_Params taskParams;
        Task_Params_init(&taskParams);
        taskParams.stackSize = MAIN_TASK_STACK_SIZE;
        taskParams.stack = &MainTaskStack;
        taskParams.priority = 1;
        Task_construct(&MainTaskStruct, (Task_FuncPtr)MainTask, &taskParams, NULL);
    
        Task_Params writeSDtaskParams;
        Task_Params_init(&writeSDtaskParams);
        writeSDtaskParams.stackSize = WRITESD_STACK_SIZE;
        writeSDtaskParams.stack = &WriteSDTaskStack;
        writeSDtaskParams.priority = 1;
        Task_construct(&WriteSDTaskStruct, (Task_FuncPtr)WriteSDTask, &writeSDtaskParams, NULL);
    
        Clock_Params clkParams;
        Clock_Params_init(&clkParams);
        clkParams.period = (5 * 60 * 1000000)/Clock_tickPeriod;
        clkParams.startFlag = TRUE;
        // Construct a periodic Clock Instance
        Clock_construct(&clk0Struct, (Clock_FuncPtr)clk0Fxn,
        (5 * 60 * 1000000)/Clock_tickPeriod, &clkParams);

    Thanks
    - Stephen




  • 1) It seems reasonable enough. However, I would like to comment on why you would want to tasks, MainTask and WriteSDTask, if both tasks are the same priority? They both are "dependent" on each other, meaning that the WriteSDTask only does its thing when MainTask calls postSemToWrite(). This sound to me like they both could be one task running an event driven state machine (take a look at SYS/BIOS Event). Using a Clock to signal f_sync is fine.
    2) Counting semaphores is probably fine. But if you want me to be pedantic, you are using them as if they were binary semaphores. Not that it's going to make much of a difference in this particular setup, but could potentially avoid bugs in the future.
    3) Not needed for priority semaphores in your setup.