void vTaskSuspend( TaskHandle_t xTaskToSuspend )
挂起指定任务。被挂起的任务绝不会得到 CPU的使用权,不管该任务具有什么优先级。任务可以通过调用 vTaskSuspend()函数都可以将处于任何状态的任务挂起,被挂起的任务得不到 CPU 的使用权,也不会参与调度,它相对于调度器而言是不可见的,除非它从挂起态中除。
void vTaskSuspendAll( void )
挂起所有任务就是挂起任务调度器。调度器被挂起后则不能进行上下文切换,但是中断还是使能的。 当调度器被挂起的时候,如果有中断需要进行上下文切换, 那么这个任务将会被挂起,在调度器恢复之后才执行切换任务。调度器恢复可以调用 xTaskResumeAll()函数,调用了多少次的 vTaskSuspendAll()就要调用多少次xTaskResumeAll()进行恢复
void vTaskResume( TaskHandle_t xTaskToResume )
任务恢复就是让挂起的任务重新进入就绪状态,恢复的任务会保留挂起前的状态信息,在恢复的时候根据挂起时的状态继续运行。如果被复任务在所有就绪态任务中,处于最高优先级列表的第一位,那么系统将进行任务上下文的切换。vTaskResume()函数用于恢复挂起的任务。无论任务在挂起时候调用过多少次这个vTaskSuspend()函数,也只需调用一次 vTaskResume ()函数即可将任务恢复运行,当然,无论调用多少次的 vTaskResume()函数,也只在任务是挂起态的时候才进行恢复。
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
xTaskResumeFromISR()与 vTaskResume()一样都是用于恢复被挂起的任务,不一样的是 xTaskResumeFromISR()专门用在中断 服务程序中。无论通过调用一次或多 次vTaskSuspend()函数而被挂起的任务,也只需调用一次 xTaskResumeFromISR()函数即可解挂 。
BaseType_t xTaskResumeAll( void )
恢复调度器,调用了多少次vTaskSuspendAll()函数就必须同样调用多少次 xTaskResumeAll()函数
void vTaskDelete( TaskHandle_t xTaskToDelete )
vTaskDelete()用于删除一个任务。当一个任务删除另外一个任务时,形参为要删除任务创建时返回的任务句柄,如果是删除自身, 则形参为 NULL。
void vTaskDelay( const TickType_t xTicksToDelay )
相对延时函数,vTaskDelay()用于阻塞延时,调用该函数后,任务将进入阻塞状态,进入阻塞态的任务将让出 CPU资源。延时的时长由形参 xTicksToDelay 决定,单位为系统节拍周期, 比如系统的时钟节拍周期为 1ms,那么调用 vTaskDelay(1)的延时时间则为 1ms。
其它任务和中断活动, 也会影响到 vTaskDelay()的调用(比如调用前高优先级任务抢占了当前任务),进而影响到任务的延时时间。
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
绝对延时函数 ,常用于较精确的周期运行任务,比如我有一个任务,希望它以固定频率定期执行,而不受外部的影响,任务从上一次运行开始到下一次运行开始的时间间隔是绝对的,而不是相对的。
void SystemInitTask(void const * argument);
osThreadId SystemInitHandle;
osThreadDef(SystemInit, SystemInitTask, osPriorityIdle, 0, 1024*2);
SystemInitHandle = osThreadCreate(osThread(SystemInit), NULL);
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
#endif
xQueueCreate()用于创建一个新的队列并返回可用于访问这个队列的队列句柄。队列句柄其实就是一个指向队列数据结构类型的指针。
void vQueueDelete( QueueHandle_t xQueue )
**vQueueDelete()也可用于删除信号量。**如果删除消息队列时,有任务正在等待消息,则不应该进行删除操作。
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
xQueueSend() 等 同 于xQueueSendToBack()。xQueueSend()用于向队列尾部发送一个队列消息。消息以拷贝的形式入队,而不是以引用的形式。该函数绝对不能在中断服务程序里面被调用,中断中必须使用带有中断保护功能的 xQueueSendFromISR()来代替。
#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
**如果不想删除消息的话,就调用 xQueuePeek()函数。**其实这个函数与 xQueueReceive()函数的实现方式一样,连使用方法都一样,只不过xQueuePeek()函数接收消息完毕不会删除消息队列中的消息而已
BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer )
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )
/*
* Reset a queue back to its original empty state. The return value is now
* obsolete and is always set to pdPASS.
*/
#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE )
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif
二值信号量和互斥量都共同使用一个类型 SemaphoreHandle_t 的句柄,该句柄的原型是一个 void 型的指针。使用该函数创建的二值信号量是空的,在使用函数xSemaphoreTake()获取之前必须先调用函数 xSemaphoreGive()释放后才可以获取。
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
#endif
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
vSemaphoreDelete()用于删除一个信号量,包括二值信号量,计数信号量,互斥量和递
归互斥量。如果有任务阻塞在该信号量上,那么不要删除该信号量。
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
xSemaphoreGive()是一个用于释放信号量的宏,真正的实现过程是调用消息队列通用发送函数,xSemaphoreGive()函数原型具体见代码清单 18-8。释放的信号量对象必须是已经被创建的,可以用于二值信号量、计数信号量、互斥量的释放,但不能释放由函数xSemaphoreCreateRecursiveMutex()创建的递归互斥量。此外该函数不能在中断中使用。
#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )
用于释放一个信号量,带中断保护。被释放的信号量可以是二进制信号量和计数信号量。和普通版本的释放信号量 API 函数有些许不同,它不能释放互斥量,这是因为互斥量不可以在中断中使用,互斥量的优先级继承机制只能在任务中起作用,而在中断中毫无意义。
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
xSemaphoreTake()函数用于获取信号量,不带中断保护。获取的信号量对象可以是二值信号量、计数信号量和互斥量,但是递归互斥量并不能使用这个 API 函数获取。
#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
用于获取信号量,是一个不带阻塞机制获取信号量的函数,获取对象必须由是已经创建的信号量,信号量类型可以是二值信号量和计数信号量,它与xSemaphoreTake()函数不同,它不能用于获取互斥量,因为互斥量不可以在中断中使用,并且互斥量特有的优先级继承机制只能在任务中起作用,而在中断中毫无意义。
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
#endif
xSemaphoreCreateRecursiveMutex()用于创建一个递归互斥量,不是递归的互斥量由函数 xSemaphoreCreateMutex() 或 xSemaphoreCreateMutexStatic()创建,且只能被同一个任务获取一次,如果同一个任务想再次获取则会失败。
#if( configUSE_RECURSIVE_MUTEXES == 1 )
#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
#endif
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
任务想要访问某个资源的时候,需要先获取互斥量,然后进行资源访问,在任务使用完该资源的时候,必须要及时归还互斥量,这样别的任务才能对资源进行访问。**互斥量的释放只能在任务中,不允许在中断中释放互斥量。**使用该函数接口时,只有已持有互斥量所有权的任务才能释放它,**当任务调用xSemaphoreGive()函数时会将互斥量变为开锁状态,**等待获取该互斥量的任务将被唤醒。如果任务的优先级被互斥量的优先级翻转机制临时提升,那么当互斥量被释放后,任务的优先级将恢复为原本设定的优先级。
#if( configUSE_RECURSIVE_MUTEXES == 1 )
#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
#endif
释放递归互斥量,获取了多少次就要释放多少次
本文来自[野火®]《FreeRTOS 内核实现与应用开发实战—基于STM32》