Thursday, 10 September 2015

FreeRTOS Task




         A task is a user define function with a given priorityTask must return void and take a void pointer parameter.

void ATaskFunction( void *pvParameters );

Each task is a small program in its own right normally
run forever within an infinite loop, and will not exit.A single task function definition can be used to create any number of tasks

A task should have the following structure:

void vTaskName( void *pvParameters )
{
    for( ;; )
    {
    -- Task application code here. --
    }
} 


Task States





Running 

It is currently using the processor. Only one task can be in RUN mode at the moment.
Ready

Able to execute but a different task of equal or higher priority is already in the Running state.
Blocked 

Currently waiting for either a temporal or external event (indicated by semaphore or queue). 
Suspended 

Not available for scheduling.



Creating Tasks

Tasks are created using the FreeRTOS xTaskCreate() API function

portBASE_TYPE xTaskCreate
(
          pdTASK_CODE pvTaskCode,
         const signed portCHAR * const pcName,
         unsigned portSHORT usStackDepth,
         void *pvParameters,
         unsigned portBASE_TYPE uxPriority,
         xTaskHandle *pxCreatedTask
);


pvTaskCode:
Ø  The pvTaskCode parameter is simply a pointer to the function(in effect just the function name) that implements the task

pcName:
Ø  This is not used by FreeRTOS in any way. It is included purely as a debugging aid

usStackDepth:
Ø  The usStackDepth value tells the kernel how big to make the stack

pvParameters:
Ø  The value assigned to pvParameters will be the value passed into the task.

pxCreatedTask:
Ø  pxCreatedTask can be used to pass out a handle to the task being created.


Example:

void vTask1( void *pvParameters )
{
         const char *pcTaskName = "Task 1 is running\r\n";
         volatile unsigned long ul;
         for( ;; )
        {
              vPrintString( pcTaskName );
              for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
             {
             }
       }
}
void vTask2( void *pvParameters )
{
        const char *pcTaskName = "Task 2 is running\r\n";
        volatile unsigned long ul;
/* As per most tasks, this task is implemented in an infinite loop. */
        for( ;; )
        {
/* Print out the name of this task. */
               vPrintString( pcTaskName );
/* Delay for a period. */
              for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
              {
              }
        }
}



The main() function simply creates the tasks before starting the scheduler



int main( void )
{
         xTaskCreate( vTask1, "Task 1", 1000, NULL, 1, NULL );
         xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
         vTaskStartScheduler();
         for( ;; );
}

 Output:




















Create a task from within another task:


void vTask1( void *pvParameters )
{
        const char *pcTaskName = "Task 1 is running\r\n";
        volatile unsigned long ul;
        xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
       for( ;; )
       {
              vPrintString( pcTaskName );
             for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
             {
             }
      }
}


Using the Task Parameter


void vTaskFunction( void *pvParameters )
{
       char *pcTaskName;
       volatile unsigned long ul;
       pcTaskName = ( char * ) pvParameters;
      for( ;; )
     {
            vPrintString( pcTaskName );
            for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
           {
           }
     }
}


static const char *pcTextForTask1 = “Task 1 is running\r\n”;
static const char *pcTextForTask2 = “Task 2 is running\t\n”;
int main( void )
{
        xTaskCreate( vTaskFunction, "Task 1", 1000, (void*)pcTextForTask1,1,NULL );
        xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2,1, NULL );
        vTaskStartScheduler();
        for( ;; );
}





Task Priority




Ø  The Priority parameter of the xTaskCreate() API function assigns an initial priority to the task being created

Ø  The priority can be changed after the scheduler has been started


Ø  The maximum number of priorities available is set by the application defined configMAX_PRIORIIES within FreeRTOSConfig.h.


















Experimenting with priorities

static const char *pcTextForTask1 = “Task 1 is running\r\n”;
static const char *pcTextForTask2 = “Task 2 is running\t\n”;
int main( void )
{
      xTaskCreate( vTaskFunction, "Task 1", 1000, (void*)pcTextForTask1, 1, NULL );
      xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2, 2, NULL );
      vTaskStartScheduler();
      return 0;
}


The output


















The Idle Task and Idle Task Hook


Idle Task

Ø  The processor always needs something to execute
Ø  An Idle task is automatically created by the scheduler when vTaskStartScheduler() is called
Ø  The idle task has the lowest possible priority (priority 0)
Ø  The idle task is responsible for freeing memory allocated by RTOS to tasks that have since been deleted

Idle Task Hook
Ø  A function that is automatically called by the idle task once per iteration of the idle task loop


Changing priority of a Task

Ø  The vTaskPrioritySet() API function can be used to change the priority of any task after the schedulerhas been started

void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );

Ø  The uxTaskPriorityGet() API function can be used to query the priority of a task.

unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );


Changing task priorities

void vTask1( void *pvParameters )
{
        unsigned portBASE_TYPE uxPriority;
        uxPriority = uxTaskPriorityGet( NULL );
        for( ;; )
       {
               vPrintString( "Task1 is running\r\n" );
               vPrintString( "About to raise the Task2 priority\r\n" );
               vTaskPrioritySet( xTask2Handle, ( uxPriority + 1 ) );
       }
}


void vTask2( void *pvParameters )
{
        unsigned portBASE_TYPE uxPriority;
        uxPriority = uxTaskPriorityGet( NULL );
       for( ;; )
      {
             vPrintString( "Task2 is running\r\n" );
             vPrintString( "About to lower the Task2 priority\r\n" );
             vTaskPrioritySet( NULL, ( uxPriority - 2 ) );
      }
}



xTaskHandle xTask2Handle;
int main( void )
{
         xTaskCreate( vTask1, "Task 1", 1000, NULL, 2, NULL );
         xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, &xTask2Handle );
         vTaskStartScheduler();
         for( ;; );
}








Task Delete



Deleting A Task

Ø  A task can use the vTaskDelete() API function to delete itself or any other task

void vTaskDelete( xTaskHandle pxTaskToDelete );

pxTaskToDelete:

The handle of the task that is to be deleted


int main( void )
{
            /* Create the first task at priority 1. The task parameter is not used
                so is set to NULL. The task handle is also not used so likewise is set
               to NULL. */

          xTaskCreate( vTask1, "Task 1", 1000, NULL, 1, NULL );

          /* The task is created at priority 1 ______^. */
          /* Start the scheduler so the tasks start executing. */

         vTaskStartScheduler();

         /* main() should never reach here as the scheduler has been started. */
        for( ;; );
 }


void vTask1( void *pvParameters )
{
         const portTickType xDelay100ms = 100 / portTICK_RATE_MS;
        for( ;; )
        {
           /* Print out the name of this task. */
              vPrintString( "Task1 is running\r\n" );
              xTaskCreate( vTask2, "Task 2", 1000, NULL, 2, &xTask2Handle );
              vTaskDelay( xDelay100ms );
       }
}



void vTask2( void *pvParameters )

{


       vPrintString( "Task2 is running and about to delete itself\r\n" );
       vTaskDelete( xTask2Handle );
}









No comments:

Post a Comment