1. Relative delay
1.1 Function description
void vTaskDelay( portTickTypexTicksToDelay )
After calling the vTaskDelay() function, the task will enter a blocking state, and the duration is specified by the parameter xTicksToDelay of the vTaskDelay() function, and the unit is the system beat clock cycle. The constant portTICK_RATE_MS is used to assist in calculating the real time. This value is the period when the system beat clock is interrupted, and is in milliseconds. In the file, the macro INCLUDE_vTaskDelay must be set to 1 for this function to be valid.
The delay time specified by vTaskDelay() is the relative time calculated from the call to vTaskDelay(). For example, vTaskDelay(100), after calling vTaskDelay(), the task enters a blocking state, and after 100 system clock beat cycles, the task is unblocked. Therefore, vTaskDelay() is not suitable for occasions where tasks are executed periodically. In addition, other tasks and interrupt activities will affect the call of vTaskDelay() (for example, the high-priority task preempts the current task before the call), and therefore will affect the next execution time of the task. The API function vTaskDelayUntil() can be used for fixed frequency delay, which is used to delay an absolute time.
1.2 Parameter Description
xTicksToDelay: The total number of delay times, unit is the system clock beat cycle.
1.3 Examples of usage
voidvTaskFunction( void * pvParameters ) { /* Blocking for 500ms. */ constportTickType xDelay = 500 / portTICK_RATE_MS; for( ;; ) { /* The LED is triggered every 500ms, and the blocking state is entered after triggering */ vToggleLED(); vTaskDelay( xDelay ); } }
2. Absolute delay
2.1 Function description
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,const TickType_txTimeIncrement );
The task delays a specified time. Periodic tasks can use this function to ensure a constant frequency execution. In the file, the macro INCLUDE_vTaskDelayUntil must be set to 1 for this function to be valid.
An important thing about this function is different from the vTaskDelay() function: the delay time specified by vTaskDelay() starts after calling vTaskDelay() (executing the function), but the delay time specified by vTaskDelayUntil() is an absolute time.
After calling the vTaskDelay() function, the task will enter a blocking state, and the duration is specified by the parameters of the vTaskDelay() function, and the unit is the system beat clock cycle. Therefore, vTaskDelay() is not suitable for the occasions where tasks are executed periodically. Because the time from calling vTaskDelay() to the task's unblocking is not always fixed and the next time the task calls vTaskDelay() function is not always fixed (the time interval between the same task is not fixed itself, interrupts or high-priority task preemption may also change each execution time).
vTaskDelay() specifies a relative time from the time counting after calling the vTaskDelay() function until the task is unblocked, while vTaskDelayUntil() specifies an absolute time, and whenever the time arrives, the task is unblocked.
It should be noted that if the specified wake-up time has been reached, vTaskDelayUntil() returns immediately (no blocking). Therefore, tasks that are periodically executed using vTaskDelayUntil() stop periodically, regardless of any reason (such as the task temporarily enters a suspended state), so that the task has less than one or more execution cycles, then the required wake-up time needs to be recalculated. This can be detected by comparing the value pointed to by the pointer parameter pxPreviousWake to the current system clock count value, which is not necessary in most cases.
The constant portTICK_RATE_MS is used to assist in calculating the real time. This value is the period when the system beat clock is interrupted, and is in milliseconds.
This function cannot be used when the vTaskSuspendAll() function is called to suspend the RTOS scheduler.
2.2 Parameter description
pxPreviousWakeTime
: Pointer, pointing to a variable that holds the time when the task was last unblocked. Before the first use, the variable must be initialized to the current time. After that, this variable will be automatically updated in the vTaskDelayUntil() function.
xTimeIncrement
: Period cycle time. When the time is equal to (*pxPreviousWakeTime + xTimeIncrement), the task is unblocked. If the value of the parameter xTimeIncrement is not changed, the task calling the function will be executed at a fixed frequency.
2.3 Examples of usage
//Enforce every 10 beats void vTaskFunction( void * pvParameters ) { static portTickType xLastWakeTime; const portTickType xFrequency = 10; // Initialize the variable xLastWakeTime using the current time xLastWakeTime = xTaskGetTickCount(); for( ;; ) { //Waiting for the next cycle vTaskDelayUntil( &xLastWakeTime,xFrequency ); // Requires periodic execution of code to be placed here } }
3. Obtain task priority
3.1 Function description
UBaseType_t uxTaskPriorityGet(TaskHandle_t xTask );
Gets the priority of the specified task. In the file, the macro INCLUDE_vTaskPriorityGet must be set to 1 for this function to be valid.
3.2 Parameter Description
xTask: Task handle. NULL indicates the priority of obtaining the current task.
3.3 Return value
Returns the priority of the specified task.
3.4 Examples of usage
voidvAFunction( void ) { xTaskHandlexHandle; // Create a task and save the task handle xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); // ... // Use handle to get priority of the created task if( uxTaskPriorityGet( xHandle ) !=tskIDLE_PRIORITY ) { // Tasks can change their priorities } // ... // Is the current task priority higher than the created task priority? if( uxTaskPriorityGet( xHandle ) <uxTaskPriorityGet( NULL ) ) { // The current priority is high } }
4. Set task priority
4.1 Function description
void vTaskPrioritySet( TaskHandle_txTask,UBaseType_tuxNewPriority );
Sets the priority of the specified task. If the priority is set higher than the currently running task, a context switch will be performed before the function returns. In the file, the macro INCLUDE_vTaskPrioritySet must be set to 1 for this function to be valid.
4.2 Parameter Description
xTask: To set the handle of the priority task, NULL indicates that the task is currently running. uxNewPriority: The new priority to be set.
4.3 Examples of usage
voidvAFunction( void ) { xTaskHandlexHandle; // Create a task and save the task handle. xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); // ... // Use handles to increase the priority of creating tasks vTaskPrioritySet( xHandle,tskIDLE_PRIORITY + 1 ); // ... // Use NULL parameters to increase the priority of the current task and set it to the same as the created task. vTaskPrioritySet( NULL, tskIDLE_PRIORITY +1 ); }
5. Task hangs
5.1 Function description
void vTaskSuspend( TaskHandle_txTaskToSuspend );
Pending the specified task. A suspended task will never get processor time, regardless of the priority of the task.
Calling the vTaskSuspend function will not accumulate: even if the vTaskSuspend() function is called multiple times to suspend a task, you only need to call the vTaskResume() function once to unsuspend the suspended task. In the file, the macro INCLUDE_vTaskSuspend must be set to 1 for this function to be valid.
5.2 Parameter Description
xTaskToSuspend: The task handle to be suspended. NULL means that the current task is suspended.
5.3 Examples of usage
voidvAFunction( void ) { xTaskHandlexHandle; // Create a task and save the task handle. xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); // ... // Use a handle to suspend the created task. vTaskSuspend( xHandle ); // ... // The task is no longer running unless other tasks call vTaskResume(xHandle) //... // Suspend this task. vTaskSuspend( NULL ); // Unless another task calls vTaskResume with handle, it will never be executed here }
6. Recover pending tasks
6.1 Function description
void vTaskResume( TaskHandle_txTaskToResume );
Resumes pending tasks.
By calling the vTaskSuspend() pending tasks one or more times, you can call the vTaskResume() function to resume running again. In the file, the macro INCLUDE_vTaskSuspend must be set to 1 for this function to be valid.
6.2 Parameter Description
xTaskToResume: The task handle to be restored to run.
6.3 Examples of usage
voidvAFunction( void ) { xTaskHandle xHandle; // Create a task and save the task handle xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); // ... // Use handle to suspend the created task vTaskSuspend( xHandle ); // ... //The task is no longer running unless other tasks call vTaskResume(xHandle) //... // Resumes suspended tasks. vTaskResume( xHandle ); // Task gets processor time again // Task priority is the same as before }
7. Recover pending tasks (used in interrupt service functions)
7.1 Function description
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume );
Used to restore a pending task, used in the ISR.
Tasks suspended by calling the vTaskSuspend() function once or multiple times can be resumed by calling the xTaskResumeFromISR() function once.
xTaskResumeFromISR() cannot be used for synchronization between tasks and interrupts. If the interrupt happens to arrive before the task is suspended, this will cause a interrupt to be lost (the task has not been suspended yet, calling the xTaskResumeFromISR() function is meaningless, and you can only wait for the next interrupt). In this case, semaphores can be used as the synchronization mechanism. In the file, the macros INCLUDE_vTaskSuspend and INCLUDE_xTaskResumeFromISR must be set to 1 for this function to be valid.
7.2 Parameter Description
xTaskToResume: The task handle to be restored to run.
7.3 Return value
If the context switch is required after restoring the task, return pdTRUE, otherwise return pdFALSE. It is determined by the ISR whether context switching is required.
7.4 Examples of usage
xTaskHandlexHandle; //Note that this is a global variable void vAFunction( void ) // Create a task and save the task handle xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); // ... Remaining code. } void vTaskCode( void *pvParameters ) { for( ;; ) { // ... Execute some other functions here // Hang yourself vTaskSuspend( NULL ); //The task will hang until the ISR restores it } } void vAnExampleISR( void ) { portBASE_TYPExYieldRequired; // Restoring suspended tasks xYieldRequired = xTaskResumeFromISR(xHandle ); if( xYieldRequired == pdTRUE ) { // We should do a context switch // Note: How to do it depends on your specific use, you can view the documentation and routines portYIELD_FROM_ISR(); } }
The above is the detailed content of the functional analysis of FreeRTOS task control API functions. For more information about FreeRTOS task control API functions, please pay attention to my other related articles!