freeRTOS The Idle Task and the Idle Task Hook
Idle Task
There must always be at least one task that can enter the Running state. To ensure this is the case, an Idle task is automatically created by the scheduler when vTaskStartScheduler() is called.The idle task does very little more than sit in a loop—it is always able to run.
The idle task has the lowest possible priority (priority zero), to ensure it never prevents a higher priority application task from entering the Running state—although there is nothing to prevent application designers creating tasks at, and therefore sharing, the idle task priority, if desired.
Note: If an application uses the vTaskDelete() API function then it is essential that the Idle task is not starved of processing time. This is because the Idle task is responsible for cleaning up kernel resources after a task has been deleted.
Idle Task Hook Functions
It is possible to add application specific functionality directly into the idle task through the use of an idle hook (or idle callback) function—a function that is called automatically by the idle task once per iteration of the idle task loop.
Common uses for the Idle task hook include:(Idle task hook使用範圍)
- Executing low priority, background, or continuous processing functionality.
- Measuring the amount of spare processing capacity. (The idle task will run only when all higher priority application tasks have no work to perform; so measuring the amount of processing time allocated to the idle task provides a clear indication of how much processing time is spare.)
- Placing the processor into a low power mode, providing an easy and automatic method of saving power whenever there is no application processing to be performed (although the power saving that can be achieved using this method is less than can be achieved by using the tick-less idle mode described in Chapter 10, Low Power Support).
Limitations on the Implementation of Idle Task Hook Functions
Idle task hook functions must adhere to the following rules.
- An Idle task hook function must never attempt to block or suspend.(Note: Blocking the idle task in any way could cause a scenario where no tasks are available to enter the Running state.)
- If the application makes use of the vTaskDelete() API function, then the Idle task hook must always return to its caller within a reasonable time period. This is because the Idle task is responsible for cleaning up kernel resources after a task has been deleted. If the idle task remains permanently in the Idle hook function, then this clean-up cannot occur.
Example
#include "FreeRTOS.h"
#include "task.h"
#include "stm32f4xx.h"
//Task1
// ----------------------------------------------------------------------------
void vTask1( void *pvParameters )
{
volatile uint16_t count1=0;
TickType_t xLastWakeTime;
/* The xLastWakeTime variable needs to be initialized with the current tick
count. Note that this is the only time the variable is written to explicitly.
After this xLastWakeTime is automatically updated within vTaskDelayUntil(). */
xLastWakeTime = xTaskGetTickCount();
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
count1++;
GPIO_ToggleBits(GPIOD,GPIO_Pin_15);
/* This task should execute every 1 milliseconds exactly. As per
the vTaskDelay() function, time is measured in ticks, and the
pdMS_TO_TICKS() macro is used to convert milliseconds into ticks.
xLastWakeTime is automatically updated within vTaskDelayUntil(), so is not
explicitly updated by the task. */
vTaskDelayUntil( &xLastWakeTime, pdMS_TO_TICKS( 1 ) );
}
}
////Task2
//// ----------------------------------------------------------------------------
void vTask2( void *pvParameters )
{
volatile uint16_t count2=0;
TickType_t xLastWakeTime;
/* The xLastWakeTime variable needs to be initialized with the current tick
count. Note that this is the only time the variable is written to explicitly.
After this xLastWakeTime is automatically updated within vTaskDelayUntil(). */
xLastWakeTime = xTaskGetTickCount();
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
count2++;
/* This task should execute every 1 milliseconds exactly. As per
the vTaskDelay() function, time is measured in ticks, and the
pdMS_TO_TICKS() macro is used to convert milliseconds into ticks.
xLastWakeTime is automatically updated within vTaskDelayUntil(), so is not
explicitly updated by the task. */
GPIO_ToggleBits(GPIOD,GPIO_Pin_13);
vTaskDelayUntil( &xLastWakeTime, pdMS_TO_TICKS( 1 ) );
}
}
void GPIOInit(){
GPIO_InitTypeDef g;
g.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; // ?? 12,13,14,15 ?
g.GPIO_Mode = GPIO_Mode_OUT; // ???????
g.GPIO_Speed = GPIO_Speed_100MHz; // ?? GPIO ???100 MHz
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); // ?? GPIOD
GPIO_Init(GPIOD, &g); // ??? GPIO D
}
int main( void )
{
GPIOInit();
/* Create one of the two tasks. Note that a real application should check
the return value of the xTaskCreate() call to ensure the task was created
successfully. */
xTaskCreate( vTask1, /* Pointer to the function that implements the task. */
"Task 1",/* Text name for the task. This is to facilitate
debugging only. */
1000, /* Stack depth - small microcontrollers will use much
less stack than this. */
NULL, /* This example does not use the task parameter. */
1, /* This task will run at priority 1. */
NULL ); /* This example does not use the task handle. */
/* Create the other task in exactly the same way and at the same priority. */
xTaskCreate( vTask2, "Task 2", 1000, NULL, 2, NULL );
/* Start the scheduler so the tasks start executing. */
vTaskStartScheduler();
/* If all is well then main() will never reach here as the scheduler will
now be running the tasks. If main() does reach here then it is likely that
there was insufficient heap memory available for the idle task to be created.
Chapter 2 provides more information on heap memory management. */
for( ;; );
}
/* Declare a variable that will be incremented by the hook function. */
volatile uint32_t ulIdleCycleCount = 0UL;
/* Idle hook functions MUST be called vApplicationIdleHook(), take no parameters,
and return void. */
void vApplicationIdleHook( void )
{
/* This hook function does nothing but increment a counter. */
ulIdleCycleCount++;
}
留言
張貼留言