No scheduling with FreeRTOS on CC3200 Launchpad

1.9k views Asked by At

I'm trying to build a system with multiple tasks on a CC3200 wifi (TI) lauchpad board with freeRTOS. I created three tasks in my main:

    // Create task1
    osi_TaskCreate( task1, ( signed portCHAR * ) "task1",
            OSI_STACK_SIZE, NULL, 1, NULL );

    //Two more tasks

All three tasks have the same priority (1) and therefore I expect that all three tasks will get the same amount of processor time.

Each task is only responsible for printing its name on the uart port:

void task1( void *pvParameters )
{
    while(1)
    {
        Report("task1");
    }
}

Unfortunately, I only see task 1 printing its name all the time. What should I do to fix this?

2

There are 2 answers

0
hooskworks On BEST ANSWER

As far as my memory of FreeRTOS goes if you do create all of your threads with equal priority then you only get the equal sharing you'd like if you either don't define USE_TIME_SLICING or define it and set it to '1'.

When it comes to multiple threads competing for access to a hardware resource (or shared memory resource) then you always want to control access to it somehow. In this case the simplest (though not fastest) option is to use a mutex, FreeRTOS also has binary semaphores which will accomplish the same thing and could be slightly faster. Generally though a mutex and binary semaphore are interchangeable. For the details of the two i'd go and read the FreeRTOS docs on them and it should clear things up.

if you forgive the pseudo code, you want each thread to be doing something along the lines of the following

createMutex(UART_Lock)

void task1
{
    while(1)
    {
       if(GetLockOnMutex(UART_Lock))
       {
          PrintToUART();
          ReleaseMutex();
       }
    }
}

void task2
{
    while(1)
    {
       if(GetLockOnMutex(UART_Lock))
       {
          PrintToUART();
          ReleaseMutex();
       }
    }
}

void task3
{
    while(1)
    {
       if(GetLockOnMutex(UART_Lock))
       {
          PrintToUART();
          ReleaseMutex();
       }
    }
}

So when each thread is brought into context it will try and get a lock on the mutex which is being used to limit access to the UART. If it succeeds then it will send something and only when the printing function returns (which could be over multiple time slices) will it release the lock on the UART for another thread to try and get. If a thread can't get a lock then it just tries again until it's time slice is up. You could have a thread that fails to get a lock put itself back to sleep until it's next brought into context but that's only really important if your CPU is quite busy and your having to think about if your tasks are actually schedule-able.

Basically, If you don't control access to the UART and there is no guarantee that during a given time slice for a thread it completes it's access to the UART then the scheduler could pre-empt the unfinished thread and others could attempt to use the UART.

It would be logical to assume the UARTs send buffer might sort it out in your case but you really don't want to rely on it as it's only so big and there's nothing to stop one thread filling it up completely.

0
JOK On

Thnx!

I implemented this as follows:

void vTestTask1( void *pvParameters )
{
    while(1) {
        if(xSemaphoreTake(uart_lock, 1000)) {
            // Use Guarded Resource
            Report("1");
            // Give Semaphore back:
            xSemaphoreGive(uart_lock);
        }
        vTaskDelay(1000);
    }
}
void vTestTask2( void *pvParameters )
{
    while(1) {
        if(xSemaphoreTake(uart_lock, 1000)) {
            // Use Guarded Resource
            Report("2");
            // Give Semaphore back:
            xSemaphoreGive(uart_lock);
        }
        vTaskDelay(1000);
    }
}

It worked perfectly as it is printing 121212 etc via the uart.