FreeRTOS学习笔记——常用函数说明
通过学习教程,对FreeRTOS已经有了了解,已经满足基本的开发。为此,记录主要的结构体和函数,用于后续使用。
一、任务创建、任务管理相关
在 FreeRTOS 中,任务是操作系统的基本执行单位。通过这些任务,FreeRTOS 能够实现多任务调度。任务的管理包括创建任务、删除任务、控制任务的执行、挂起和恢复任务等操作。
以下是 FreeRTOS 中与任务管理相关的常用函数及其详细说明:
1. xTaskCreate()
函数原型:
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,const char * const pcName,uint16_t usStackDepth,void *pvParameters,UBaseType_t uxPriority,TaskHandle_t *pxCreatedTask );
函数参数:
pxTaskCode
:任务函数的入口点(函数指针)。这是一个函数,函数原型为void taskFunction(void *pvParameters)
,任务的实际执行代码。pcName
:任务的名称,用于调试时显示。usStackDepth
:任务栈的大小,以字节为单位。栈空间必须足够大,以容纳任务的局部变量、调用栈等。pvParameters
:传递给任务的参数,在任务创建时使用。可以是任何类型的数据,通常用来传递任务所需的初始化信息。uxPriority
:任务的优先级。FreeRTOS 支持多种任务优先级,优先级越高,任务越先执行。pxCreatedTask
:输出参数,用于返回任务句柄。句柄可以用于以后对任务进行控制(如删除、挂起等)。
返回值:
pdPASS
:任务成功创建。errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
:内存不足,无法分配足够的空间给任务。
函数作用:
xTaskCreate()
用于创建一个任务并将其添加到任务调度器中。它会分配任务的堆栈空间,并且启动任务的执行。任务会按照指定的优先级和调度策略开始执行。
2. vTaskDelete()
函数原型:
void vTaskDelete( TaskHandle_t xTaskToDelete );
函数参数:
xTaskToDelete
:要删除的任务句柄。如果传入NULL
,则会删除当前任务。
函数返回值:
- 无返回值。
函数作用:
vTaskDelete()
用于删除指定的任务。删除任务后,FreeRTOS 会释放该任务的资源,包括堆栈和任务控制块(TCB)。删除任务会影响系统的运行,因此应该小心使用,特别是删除当前正在执行的任务。
3. vTaskSuspend()
函数原型:
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
函数参数:
xTaskToSuspend
:要挂起的任务句柄。如果传入NULL
,则挂起当前任务。
函数返回值:
- 无返回值。
函数作用:
vTaskSuspend()
用于挂起一个任务。挂起的任务不会继续执行,直到显式调用 vTaskResume()
恢复任务。此函数用于任务暂停的场景,允许在一定条件下挂起任务。
4. vTaskResume()
函数原型:
void vTaskResume( TaskHandle_t xTaskToResume );
函数参数:
xTaskToResume
:要恢复的任务句柄。如果传入NULL
,则恢复当前任务。
函数返回值:
- 无返回值。
函数作用:
vTaskResume()
用于恢复被挂起的任务,使其重新进入就绪队列,等待调度器进行调度。该函数与 vTaskSuspend()
配合使用,用于任务的动态挂起和恢复。
5. vTaskPrioritySet()
函数原型:
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
函数参数:
xTask
:任务句柄。可以是任何任务的句柄,或者NULL
,表示当前任务。uxNewPriority
:新的任务优先级。优先级是一个整数,数值越大表示优先级越高。
函数返回值:
- 无返回值。
函数作用:
vTaskPrioritySet()
用于设置任务的优先级。通过此函数,可以动态改变任务的优先级。该函数常用于任务执行过程中根据不同需求调整任务的优先级。
6. xTaskGetTickCount()
函数原型:
TickType_t xTaskGetTickCount( void );
函数参数:
- 无参数。
返回值:
- 返回当前的 tick 计数(系统时钟滴答的次数)。这是 FreeRTOS 内部用来控制任务时间的一个全局时钟。
函数作用:
xTaskGetTickCount()
用于获取系统当前的 tick 数。Tick 是 FreeRTOS 用来管理任务时间片的计时单位。此函数通常用于任务延迟、超时、定时器等操作中,获取当前时间以便执行基于时间的任务操作。
7. vTaskDelay()
函数原型:
void vTaskDelay( const TickType_t xTicksToDelay );
函数参数:
xTicksToDelay
:延迟的时间,单位为 Tick。任务会进入阻塞状态,直到经过指定的 Tick 数之后再被唤醒。
返回值:
- 无返回值。
函数作用:
vTaskDelay()
用于让当前任务延迟一段时间,在这段时间内任务处于阻塞状态,不占用 CPU。该函数是实现任务延迟的一种简单方式,常用于控制任务的执行频率或等待某些事件发生。
总结
在 FreeRTOS 中,任务的创建和管理是非常核心的功能。以下是常用的任务管理相关的函数:
xTaskCreate()
:用于创建任务。vTaskDelete()
:用于删除任务。vTaskSuspend()
和vTaskResume()
:用于挂起和恢复任务。vTaskPrioritySet()
:用于动态调整任务优先级。xTaskGetTickCount()
:获取系统时钟滴答计数。vTaskDelay()
:使当前任务延迟一段时间。
这些函数和 API 提供了 FreeRTOS 中进行任务管理和调度的核心功能。你可以根据需求创建任务、调整任务优先级、管理任务的执行顺序,并对任务进行延迟和挂起等操作。
二、消息队列相关
FreeRTOS 提供了队列机制,使任务可以安全地将数据从一个任务传递到另一个任务。消息队列不仅支持数据交换,还支持任务间的同步。以下是 FreeRTOS 中与消息队列相关的常用函数及其详细说明。
1. xQueueCreate()
函数原型:
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
函数参数:
uxQueueLength
:队列的长度,即队列可以容纳的最大数据项数。uxItemSize
:队列每个数据项的大小(单位:字节)。
返回值:
xQueueCreate()
:返回一个队列句柄。如果队列创建失败(内存不足等原因),则返回NULL
。
函数作用:
xQueueCreate()
用于创建一个新的队列。队列的大小由 uxQueueLength
和 uxItemSize
决定。返回值是一个队列句柄,可以用于后续的队列操作(如发送、接收数据等)。
2. xQueueSend()
函数原型:
BaseType_t xQueueSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );
函数参数:
xQueue
:队列的句柄。pvItemToQueue
:指向要发送到队列中的数据的指针。该数据的类型应与队列初始化时设置的uxItemSize
一致。xTicksToWait
:如果队列满,当前任务等待的最长时间(以 Tick 为单位)。如果设置为0
,表示不等待。如果设置为portMAX_DELAY
,任务会无限期阻塞直到数据成功发送。
返回值:
pdPASS
:数据成功发送到队列。errQUEUE_FULL
:队列已满,且没有足够时间将数据发送到队列。
函数作用:
xQueueSend()
将数据项添加到队列的尾部。如果队列已满,任务会等待,直到队列有空位或者超时。此函数支持阻塞模式(当队列满时等待)和非阻塞模式(当队列满时不等待)。
3. xQueueSendToBack()
函数原型:
BaseType_t xQueueSendToBack( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );
函数参数:
xQueue
:队列的句柄。pvItemToQueue
:指向要发送到队列中的数据的指针。xTicksToWait
:队列已满时等待的最长时间。
返回值:
pdPASS
:数据成功发送到队列。errQUEUE_FULL
:队列已满,且没有足够时间将数据发送到队列。
函数作用:
xQueueSendToBack()
将数据项添加到队列的尾部。此函数与 xQueueSend()
的不同之处在于,它总是将数据添加到队列的尾部。功能上与 xQueueSend()
类似,但更明确地指定了添加到队列的尾部。
4. xQueueReceive()
函数原型:
BaseType_t xQueueReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );
函数参数:
xQueue
:队列的句柄。pvBuffer
:指向接收数据存储位置的指针。接收到的数据会被复制到此缓冲区。xTicksToWait
:如果队列为空,任务等待的最大时间(以 Tick 为单位)。如果设置为0
,表示不等待;如果设置为portMAX_DELAY
,任务将无限期等待。
返回值:
pdPASS
:成功从队列中接收到数据。errQUEUE_EMPTY
:队列为空,且在指定的等待时间内未接收到数据。
函数作用:
xQueueReceive()
从队列的头部获取数据。如果队列为空,任务将等待,直到数据可用或者超时。此函数支持阻塞模式(等待数据)和非阻塞模式(队列为空时立即返回)。
5. xQueuePeek()
函数原型:
BaseType_t xQueuePeek( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );
函数参数:
xQueue
:队列的句柄。pvBuffer
:指向存储接收数据的缓冲区。xTicksToWait
:如果队列为空,任务等待的最大时间(以 Tick 为单位)。如果设置为0
,表示不等待;如果设置为portMAX_DELAY
,任务将无限期等待。
返回值:
pdPASS
:成功从队列中查看到数据。errQUEUE_EMPTY
:队列为空,且在指定的等待时间内未接收到数据。
函数作用:
xQueuePeek()
允许任务从队列中查看数据(即获取队列中的数据,但不从队列中移除该数据)。该函数通常用于读取队列中的数据但不改变队列的状态。类似于 xQueueReceive()
,但是不移除数据项。
6. xQueueReset()
函数原型:
BaseType_t xQueueReset( QueueHandle_t xQueue );
函数参数:
xQueue
:队列的句柄。
返回值:
pdPASS
:队列成功重置。errQUEUE_EMPTY
:队列为空,无法重置。
函数作用:
xQueueReset()
用于清空队列,将队列中的所有元素移除,使队列恢复到空状态。通常用于需要重新初始化队列的场景,确保队列处于空状态。
7. uxQueueMessagesWaiting()
函数原型:
UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );
函数参数:
xQueue
:队列的句柄。
返回值:
- 返回队列中当前存储的消息数量。
函数作用:
uxQueueMessagesWaiting()
返回当前队列中有多少个消息项。可以用来检查队列中是否有数据,或者在需要知道队列状态时调用。
8. uxQueueSpacesAvailable()
函数原型:
UBaseType_t uxQueueSpacesAvailable( QueueHandle_t xQueue );
函数参数:
xQueue
:队列的句柄。
返回值:
- 返回队列中剩余的空间,即队列中可以存放多少个数据项。
函数作用:
uxQueueSpacesAvailable()
用于获取队列中剩余的空闲空间。它返回一个值,表示队列中可以接受多少个额外的数据项。
总结
FreeRTOS 中的消息队列是任务之间通信的重要机制,支持数据交换、同步和队列管理。以下是常用的队列相关函数:
xQueueCreate()
:创建一个队列。xQueueSend()
和xQueueSendToBack()
:将数据发送到队列。xQueueReceive()
和xQueuePeek()
:从队列接收数据或查看数据。xQueueReset()
:重置队列,将其清空。uxQueueMessagesWaiting()
:获取队列中的消息数量。uxQueueSpacesAvailable()
:获取队列中剩余的空间。
通过这些函数,FreeRTOS 提供了灵活且高效的任务间通信手段,可以保证在多任务并发执行的情况下,任务间的数据传递是安全和同步的。
三、信号量相关
在 FreeRTOS 中,信号量有多种类型,常见的有 二值信号量、计数信号量 和 互斥信号量。它们在任务同步、资源管理等方面扮演着重要的角色。
1. xSemaphoreCreateBinary()
函数原型:
SemaphoreHandle_t xSemaphoreCreateBinary(void);
函数参数:
- 无参数。
返回值:
- SemaphoreHandle_t:返回创建的信号量句柄。如果信号量创建失败(例如内存不足),返回
NULL
。
函数作用:
xSemaphoreCreateBinary()
创建一个二值信号量,二值信号量的值只能是 0 或 1。二值信号量通常用于任务间的同步,例如用来控制一个任务是否可以访问一个共享资源。
2. xSemaphoreCreateCounting()
函数原型:
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount );
函数参数:
uxMaxCount
:计数信号量的最大值。这个值定义了信号量的最大计数。uxInitialCount
:计数信号量的初始值。该值决定了信号量创建时的初始计数。
返回值:
- SemaphoreHandle_t:返回创建的计数信号量句柄。如果信号量创建失败,返回
NULL
。
函数作用:
xSemaphoreCreateCounting()
创建一个计数信号量,计数信号量可以用于多个任务间的同步和资源计数。信号量的计数值可以在 0 到 uxMaxCount
之间变化,通常用于限制某个资源的可用数量,例如信号量计数可以用来管理对硬件设备的访问。
3. xSemaphoreCreateMutex()
函数原型:
SemaphoreHandle_t xSemaphoreCreateMutex(void);
函数参数:
- 无参数。
返回值:
- SemaphoreHandle_t:返回创建的互斥信号量句柄。如果信号量创建失败,返回
NULL
。
函数作用:
xSemaphoreCreateMutex()
用于创建一个互斥信号量,互斥信号量用于实现任务之间的互斥访问。互斥信号量通常用于保护临界区,确保在同一时刻只有一个任务可以访问共享资源。创建互斥信号量时,信号量的初始值为 1,表示资源是可用的。
4. xSemaphoreTake()
函数原型:
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
函数参数:
xSemaphore
:信号量的句柄。xTicksToWait
:任务等待信号量的最大时间(单位为 Tick)。如果信号量可用,任务立即获取。如果信号量不可用,任务将阻塞,直到信号量可用或者超时。如果设置为0
,表示非阻塞模式;如果设置为portMAX_DELAY
,表示任务会无限期等待。
返回值:
pdPASS
:成功获取信号量。errQUEUE_FULL
:无法在指定的等待时间内获取信号量。
函数作用:
xSemaphoreTake()
用于从信号量获取信号。如果信号量已被占用,任务会根据 xTicksToWait
参数阻塞等待直到信号量释放。如果获取成功,函数会返回 pdPASS
,任务可以访问共享资源。如果任务超时或信号量不可用,则返回 errQUEUE_FULL
。
5. xSemaphoreGive()
函数原型:
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
函数参数:
xSemaphore
:信号量的句柄。
返回值:
pdPASS
:成功释放信号量。errQUEUE_FULL
:无法释放信号量。
函数作用:
xSemaphoreGive()
用于释放一个信号量。当任务释放信号量时,其他等待该信号量的任务会被唤醒,并且可以获取信号量。如果当前没有任务等待信号量,信号量的计数将增加。对于互斥信号量,这通常意味着解除临界区保护,使其他任务能够访问共享资源。
6. xSemaphoreTakeFromISR()
函数原型:
BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );
函数参数:
xSemaphore
:信号量的句柄。pxHigherPriorityTaskWoken
:指向BaseType_t
的指针。如果信号量的释放导致任务切换(例如唤醒了一个高优先级任务),该参数将设置为pdTRUE
,否则设置为pdFALSE
。
返回值:
pdPASS
:成功获取信号量。errQUEUE_FULL
:无法获取信号量。
函数作用:
xSemaphoreTakeFromISR()
用于从中断服务例程(ISR)中获取信号量。与 xSemaphoreTake()
类似,但它适用于中断上下文。该函数支持在 ISR 中获取信号量,并允许在 ISR 中进行任务调度(通过 pxHigherPriorityTaskWoken
参数)。该函数不会阻塞,如果信号量不可用,它会立即返回。
7. xSemaphoreGiveFromISR()
函数原型:
BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );
函数参数:
xSemaphore
:信号量的句柄。pxHigherPriorityTaskWoken
:指向BaseType_t
的指针,指示是否由于给信号量而唤醒了一个高优先级任务。
返回值:
pdPASS
:成功释放信号量。errQUEUE_FULL
:无法释放信号量。
函数作用:
xSemaphoreGiveFromISR()
用于从中断服务例程(ISR)中释放信号量。它允许 ISR 向任务发出信号,从而唤醒等待的任务。该函数也支持在 ISR 中进行任务调度(通过 pxHigherPriorityTaskWoken
参数)。
8. xSemaphoreCreateRecursiveMutex()
函数原型:
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);
函数参数:
- 无参数。
返回值:
- SemaphoreHandle_t:返回创建的递归互斥信号量句柄。如果创建失败,返回
NULL
。
函数作用:
xSemaphoreCreateRecursiveMutex()
用于创建一个递归互斥信号量。递归互斥信号量允许同一任务多次获取该信号量,而不会导致死锁。适用于任务需要多次进入临界区的情况(例如任务中有多个函数调用都需要访问同一个资源)。
总结
在 FreeRTOS 中,信号量是任务同步、互斥和资源管理的重要工具。以下是与信号量相关的常用函数:
xSemaphoreCreateBinary()
:创建一个二值信号量。xSemaphoreCreateCounting()
:创建一个计数信号量。xSemaphoreCreateMutex()
:创建一个互斥信号量。xSemaphoreTake()
:从信号量获取信号,等待信号量可用。xSemaphoreGive()
:释放信号量,通知等待信号量的任务。xSemaphoreTakeFromISR()
:在 ISR 中获取信号量。xSemaphoreGiveFromISR()
:在 ISR 中释放信号量。xSemaphoreCreateRecursiveMutex()
:创建一个递归互斥信号量。
通过这些函数,FreeRTOS 为任务之间的同步、互斥和资源访问控制提供了强大的支持,确保多任务环境中的资源共享不会导致数据冲突或死锁。
四、互斥量相关
互斥量相比于二值信号量,其通过优先级继承,解决了优先级反转的问题。
互斥量(Mutex)用于保护临界区,确保同一时刻只有一个任务能够访问共享资源。当一个任务拥有互斥量时,其他任务将被阻塞,直到互斥量被释放。互斥量通常用于防止多个任务同时修改共享资源,从而引发数据不一致或资源冲突。
FreeRTOS 中提供了几个函数来管理互斥量的创建、获取、释放等操作。以下是关于互斥量的相关函数说明。
1. xSemaphoreCreateMutex()
函数原型:
SemaphoreHandle_t xSemaphoreCreateMutex(void);
函数参数:
- 无参数。
返回值:
- SemaphoreHandle_t:返回创建的互斥量句柄。如果创建失败(如内存不足),返回
NULL
。
函数作用:
xSemaphoreCreateMutex()
用于创建一个 互斥量,该互斥量适用于保护共享资源。创建时,互斥量的初始值为 1,表示资源是可用的。当任务获取到互斥量时,互斥量的值会变为 0,表示资源被占用。互斥量的唯一特点是,它能够实现 优先级继承,从而有效避免优先级反转问题。
2. xSemaphoreTake()
函数原型:
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
函数参数:
xSemaphore
:互斥量的句柄。xTicksToWait
:任务等待互斥量的最长时间(以 Tick 为单位)。如果设置为 0,表示非阻塞模式;如果设置为portMAX_DELAY
,表示任务将无限期等待直到获取到互斥量。
返回值:
pdPASS
:成功获取互斥量。errQUEUE_FULL
:无法获取互斥量,且在指定的等待时间内未获取到互斥量。
函数作用:
xSemaphoreTake()
用于获取一个互斥量。如果互斥量已被其他任务占用,任务会根据 xTicksToWait
参数阻塞,直到互斥量被释放或者超时。如果获取成功,返回 pdPASS
,否则返回 errQUEUE_FULL
。
3. xSemaphoreGive()
函数原型:
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
函数参数:
xSemaphore
:互斥量的句柄。
返回值:
pdPASS
:成功释放互斥量。errQUEUE_FULL
:无法释放互斥量(可能是互斥量已经被释放或其他原因)。
函数作用:
xSemaphoreGive()
用于释放互斥量。当任务释放互斥量时,其他任务将有机会获取该互斥量并访问共享资源。释放互斥量时,如果有其他任务等待该互斥量,调度器会进行任务切换,优先执行等待中的任务。
4. xSemaphoreGiveFromISR()
函数原型:
BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );
函数参数:
xSemaphore
:互斥量的句柄。pxHigherPriorityTaskWoken
:指向BaseType_t
类型的指针。如果释放互斥量导致唤醒了高优先级任务,该参数会被设置为pdTRUE
,否则为pdFALSE
。
返回值:
pdPASS
:成功释放互斥量。errQUEUE_FULL
:无法释放互斥量。
函数作用:
xSemaphoreGiveFromISR()
用于在中断服务例程(ISR)中释放互斥量。这是一个用于中断上下文的函数,与 xSemaphoreGive()
类似,但支持在中断中释放互斥量。它还可以通过 pxHigherPriorityTaskWoken
参数触发任务切换,确保高优先级任务能够尽早执行。
5. xSemaphoreTakeFromISR()
函数原型:
BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );
函数参数:
xSemaphore
:互斥量的句柄。pxHigherPriorityTaskWoken
:指向BaseType_t
类型的指针。如果获取互斥量导致高优先级任务被唤醒,该参数会被设置为pdTRUE
,否则为pdFALSE
。
返回值:
pdPASS
:成功获取互斥量。errQUEUE_FULL
:无法获取互斥量。
函数作用:
xSemaphoreTakeFromISR()
用于从中断服务例程(ISR)中获取互斥量。在 ISR 中,只有在互斥量可用时才能获取,否则 ISR 会退出,并且任务会根据 pxHigherPriorityTaskWoken
来决定是否需要进行任务切换。
6. 优先级继承机制
互斥量的一个关键特性是 优先级继承。在 FreeRTOS 中,互斥量通过 优先级继承 机制有效地解决了 优先级反转 问题。
6.1 优先级反转问题
优先级反转是指一个高优先级任务因等待低优先级任务释放资源而被阻塞的现象。这可能导致实时系统的性能下降,甚至导致任务无法按时完成。
6.2 优先级继承的工作原理
当一个高优先级任务请求互斥量,而该互斥量已经被低优先级任务持有时,FreeRTOS 会通过 优先级继承 机制将低优先级任务的优先级临时提升为与高优先级任务相同。这使得低优先级任务能够尽快释放互斥量,从而避免高优先级任务的长时间阻塞。待低优先级任务释放互斥量后,它的优先级恢复到原来的值。
总结
在 FreeRTOS 中,互斥量是一种强大的同步工具,用于任务间的互斥访问共享资源。通过互斥量的优先级继承机制,FreeRTOS 解决了 优先级反转 问题,确保了系统的实时性和任务调度的稳定性。
以下是与互斥量相关的常用函数:
xSemaphoreCreateMutex()
:创建一个互斥量。xSemaphoreTake()
:获取互斥量,任务会阻塞直到互斥量可用。xSemaphoreGive()
:释放互斥量,允许其他任务获取互斥量。xSemaphoreGiveFromISR()
:从中断中释放互斥量。xSemaphoreTakeFromISR()
:从中断中获取互斥量。
通过这些函数,FreeRTOS 提供了对任务同步的精确控制,帮助开发者在多任务环境下管理共享资源的访问,避免冲突,保证系统的高效性和实时性。
五、事件组相关
FreeRTOS 中的事件组(Event Group)提供了一种高效的方式来管理任务的同步。任务可以通过事件组等待一个或多个事件的发生,并在事件满足时继续执行。事件组的核心是位掩码,每一位代表一个事件。
1. xEventGroupCreate()
函数原型:
EventGroupHandle_t xEventGroupCreate(void);
函数参数:
- 无参数。
返回值:
- EventGroupHandle_t:返回创建的事件组句柄。如果创建失败,返回
NULL
。
函数作用:
xEventGroupCreate()
用于创建一个新的事件组。事件组的初始值为 0,表示所有事件位均未设置。事件组用于任务之间的同步和状态传递,可以通过设置和清除事件位来通知任务事件的发生。
2. xEventGroupSetBits()
函数原型:
BaseType_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
函数参数:
xEventGroup
:事件组的句柄。uxBitsToSet
:要设置的事件位掩码。每一位对应一个事件,设置某一位表示相应的事件发生。
返回值:
pdPASS
:成功设置事件位。errQUEUE_FULL
:操作失败。
函数作用:
xEventGroupSetBits()
用于设置事件组中的一个或多个事件位。当设置某一位时,任务可以等待这些事件的发生。该函数用于在任务中发送事件通知给其他任务。多个事件位可以在一次操作中同时设置。
3. xEventGroupClearBits()
函数原型:
BaseType_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
函数参数:
xEventGroup
:事件组的句柄。uxBitsToClear
:要清除的事件位掩码。每一位对应一个事件,清除某一位表示该事件未发生。
返回值:
pdPASS
:成功清除事件位。errQUEUE_FULL
:操作失败。
函数作用:
xEventGroupClearBits()
用于清除事件组中的一个或多个事件位。当清除某一位时,表示该事件未发生。该函数用于在任务中重置事件的状态,以便后续使用。
4. xEventGroupWaitBits()
函数原型:
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait );
函数参数:
xEventGroup
:事件组的句柄。uxBitsToWaitFor
:任务等待的事件位掩码。任务会等待至少这些事件发生。xClearOnExit
:如果设置为pdTRUE
,当任务退出时会自动清除等待的事件位。xWaitForAllBits
:如果设置为pdTRUE
,任务会等待所有指定的事件位。如果设置为pdFALSE
,任务会等待任何一个事件位。xTicksToWait
:等待的最长时间(以 Tick 为单位)。如果设置为0
,表示非阻塞;如果设置为portMAX_DELAY
,表示任务会无限期等待。
返回值:
- 返回事件组当前的事件位掩码。可以通过该掩码判断哪些事件已经发生。
函数作用:
xEventGroupWaitBits()
用于让任务等待一个或多个事件的发生。任务会阻塞直到事件组中的指定事件位被设置为 1
。该函数支持等待一个或多个事件,并可以指定是否清除事件位,以及等待超时的处理方式。
- 如果
xWaitForAllBits
为pdTRUE
,任务会等待所有指定的事件位; - 如果
xWaitForAllBits
为pdFALSE
,任务会等待任何一个指定的事件位。
5. xEventGroupGetBits()
函数原型:
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
函数参数:
xEventGroup
:事件组的句柄。
返回值:
- 返回当前事件组的事件位掩码,表示哪些事件已发生。
函数作用:
xEventGroupGetBits()
用于获取事件组中当前的事件位掩码。任务可以使用这个函数查看事件组中哪些事件已经发生,从而决定是否继续执行操作。这个函数通常用于检查某些事件是否已被触发。
6. xEventGroupSetBitsFromISR()
函数原型:
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
函数参数:
xEventGroup
:事件组的句柄。uxBitsToSet
:要设置的事件位掩码。pxHigherPriorityTaskWoken
:指向BaseType_t
的指针,如果设置事件后唤醒了高优先级任务,则该参数会被设置为pdTRUE
,否则为pdFALSE
。
返回值:
pdPASS
:成功设置事件位。errQUEUE_FULL
:操作失败。
函数作用:
xEventGroupSetBitsFromISR()
用于从中断服务例程(ISR)中设置事件组中的一个或多个事件位。当事件位被设置时,等待该事件的任务会被唤醒。该函数支持中断上下文,可以用于中断触发任务同步。
7. xEventGroupWaitBitsFromISR()
函数原型:
EventBits_t xEventGroupWaitBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, BaseType_t *pxHigherPriorityTaskWoken );
函数参数:
xEventGroup
:事件组的句柄。uxBitsToWaitFor
:任务等待的事件位掩码。xClearOnExit
:是否在退出时清除事件位。xWaitForAllBits
:是否等待所有指定的事件位。pxHigherPriorityTaskWoken
:如果设置事件后唤醒了高优先级任务,则该参数会被设置为pdTRUE
,否则为pdFALSE
。
返回值:
- 返回当前事件组的事件位掩码。
函数作用:
xEventGroupWaitBitsFromISR()
允许从 ISR 中等待事件组的一个或多个事件位。这使得在中断上下文中也能检查和等待事件组的状态,常用于中断中等待任务同步。
总结
FreeRTOS 中的事件组是一种非常强大的同步机制,适用于任务间的状态传递和协作。事件组通过使用位掩码的方式让多个任务等待不同的事件,可以灵活地进行任务间的同步。
以下是与事件组相关的常用函数:
xEventGroupCreate()
:创建一个事件组。xEventGroupSetBits()
:设置事件组中的事件位。xEventGroupClearBits()
:清除事件组中的事件位。xEventGroupWaitBits()
:等待一个或多个事件的发生。xEventGroupGetBits()
:获取事件组当前的事件位。xEventGroupSetBitsFromISR()
:从 ISR 中设置事件组的事件位。xEventGroupWaitBitsFromISR()
:从 ISR 中等待事件组的一个或多个事件位。
这些函数让任务能够灵活地同步和协作,适用于需要等待多个事件发生的场景。在 FreeRTOS 中,事件组为多任务间的协调提供了高效的解决方案。
六、任务通知相关
任务通知提供了一种简单、快速的方式用于任务间的通信。任务通知主要通过对任务的通知位进行设置、清除和检查来实现任务之间的同步与通知。任务通知通常用于通知一个任务进行某项工作或等待某个事件发生。
1. xTaskNotifyGive()
函数原型:
BaseType_t xTaskNotifyGive( TaskHandle_t xTask );
函数参数:
xTask
:要通知的任务的句柄。如果传入NULL
,表示通知当前任务。
返回值:
pdPASS
:成功发送通知。errQUEUE_FULL
:无法发送通知。
函数作用:
xTaskNotifyGive()
用于通知指定任务执行某个操作。它会将指定任务的通知值设置为 1
。如果目标任务正在等待通知,它将从阻塞状态变为就绪状态。
2. xTaskNotify()
函数原型:
BaseType_t xTaskNotify( TaskHandle_t xTask, uint32_t ulValue, eNotifyAction eAction );
函数参数:
-
xTask
:目标任务的句柄。如果传入NULL
,则表示通知当前任务。 -
ulValue
:通知的值,可以是任何整数值,通常用于传递某些状态或信息。 -
eAction
:通知操作的类型。该参数指定如何将通知值与任务的当前通知值结合。它有以下几种取值:eSetBits
:设置任务的通知值(将通知值的指定位设置为1
)。eIncrement
:将任务的通知值加上ulValue
。eSetValueWithOverwrite
:设置任务的通知值为ulValue
,如果原通知值已经存在,则覆盖它。eSetValueWithoutOverwrite
:仅当任务的通知值为0
时,才会将ulValue
设置为任务的通知值。
返回值:
pdPASS
:成功发送通知。errQUEUE_FULL
:无法发送通知。
函数作用:
xTaskNotify()
用于通知任务并传递一个整数值。它是一个更灵活的通知机制,允许向任务传递更多的信息,并支持不同的通知操作类型(如设置、递增、覆盖等)。可以通过 eAction
参数选择适合的通知类型。
3. xTaskNotifyWait()
函数原型:
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToWaitFor, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
函数参数:
ulBitsToClearOnEntry
:进入函数时清除的通知位掩码。如果不需要清除某些位,可以设置为0
。ulBitsToWaitFor
:等待的通知位掩码。任务会等待这些位被设置为1
。pulNotificationValue
:指向一个变量,用于接收通知值。该值在任务成功接收到通知后返回。xTicksToWait
:任务等待的最大时间(以 Tick 为单位)。如果任务在等待期间未接收到通知,它会在超时后返回。
返回值:
pdTRUE
:成功接收到通知。pdFALSE
:超时或没有接收到通知。
函数作用:
xTaskNotifyWait()
用于让任务等待一个通知。当任务接收到通知时,它会从等待状态变为就绪状态。可以设置 ulBitsToWaitFor
来指定等待的通知位,当通知位被设置时,任务会继续执行。此外,ulBitsToClearOnEntry
可以用于在等待时清除任务的通知位。
4. ulTaskNotifyTake()
函数原型:
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
函数参数:
xClearCountOnExit
:是否在任务通知完成后清除通知位。如果为pdTRUE
,则在任务退出时清除通知位。xTicksToWait
:任务等待通知的最大时间(以 Tick 为单位)。如果任务未在指定时间内接收到通知,则返回0
。
返回值:
- 返回任务当前的通知值,通常是接收到的通知值或者计数。
函数作用:
ulTaskNotifyTake()
使任务等待一个通知,并获取通知值。任务将阻塞直到接收到通知,或者等待超时。任务收到通知后,返回接收到的通知值。
5. xTaskNotifyStateClear()
函数原型:
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
函数参数:
xTask
:要清除通知状态的任务句柄。如果传入NULL
,表示清除当前任务的通知状态。
返回值:
pdPASS
:成功清除通知状态。errQUEUE_FULL
:操作失败。
函数作用:
xTaskNotifyStateClear()
用于清除指定任务的通知状态,通常用于任务完成某项操作后,重置通知状态,准备下一次的通知。
6. xTaskNotifyFromISR()
函数原型:
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTask, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
函数参数:
xTask
:要通知的任务句柄。如果传入NULL
,表示通知当前任务。ulValue
:通知的值,通常用于传递某些信息。eAction
:通知的操作类型(eSetBits
、eIncrement
、eSetValueWithOverwrite
、eSetValueWithoutOverwrite
)。pxHigherPriorityTaskWoken
:指向BaseType_t
的指针,如果通知导致高优先级任务被唤醒,则设置为pdTRUE
,否则为pdFALSE
。
返回值:
pdPASS
:成功发送通知。errQUEUE_FULL
:操作失败。
函数作用:
xTaskNotifyFromISR()
用于在中断服务例程(ISR)中通知任务。与 xTaskNotify()
类似,它允许从 ISR 中向任务发送通知,并且支持在 ISR 中进行任务调度(通过 pxHigherPriorityTaskWoken
参数)。
总结
在 FreeRTOS 中,任务通知是一种轻量级的同步机制,用于任务间的通知和信号传递。以下是常用的任务通知相关函数:
xTaskNotifyGive()
:用于通知目标任务进行某项操作。xTaskNotify()
:用于通知任务并传递通知值,支持不同的通知操作(如设置、递增、覆盖等)。xTaskNotifyWait()
:让任务等待通知,直到接收到通知或超时。ulTaskNotifyTake()
:等待任务通知并返回通知值。xTaskNotifyStateClear()
:清除任务的通知状态。xTaskNotifyFromISR()
:在中断服务例程中通知任务。
任务通知提供了一种高效、低开销的任务同步机制,适用于任务之间需要快速、轻量级通信的场景。在实际应用中,任务通知可以有效地减少消息队列和信号量带来的性能开销,特别是对于频繁的任务间通知。
七、内存管理相关
FreeRTOS 提供了灵活的内存管理功能,允许系统根据需求进行内存分配。FreeRTOS 支持多种内存分配器,包括 heap_1、heap_2、heap_3、heap_4 和 heap_5 等。不同的内存分配器适用于不同的应用场景,允许开发者选择最合适的内存管理策略。
1. pvPortMalloc()
函数原型:
void *pvPortMalloc( size_t xSize );
函数参数:
xSize
:要分配的内存大小,单位是字节。
返回值:
void*
:返回分配的内存块的指针。如果分配失败,返回NULL
。
函数作用:
pvPortMalloc()
用于从堆中分配一块指定大小的内存。这个函数是一个标准的内存分配器接口,提供了对动态内存的分配。在 FreeRTOS 中,pvPortMalloc()
基于系统选择的堆管理方案(如 heap_4
)来实现。
- 默认情况下,
pvPortMalloc()
使用配置的堆分配方案。如果使用的是heap_4
,它提供了合适的内存管理功能,如合并相邻的空闲内存块,减少内存碎片。 pvPortMalloc()
通常用于动态分配内存,例如为任务创建堆栈或分配队列和信号量。
2. vPortFree()
函数原型:
void vPortFree( void *pvAddress );
函数参数:
pvAddress
:指向要释放的内存块的指针。
返回值:
- 无返回值。
函数作用:
vPortFree()
用于释放之前通过 pvPortMalloc()
分配的内存块。调用此函数时,FreeRTOS 将释放分配的内存,并将其返回到堆中,供以后使用。
- 需要注意的是,只有使用
pvPortMalloc()
分配的内存才能通过vPortFree()
进行释放。调用vPortFree()
时,必须确保传入的指针有效,否则会导致程序崩溃。
3. xPortGetFreeHeapSize()
函数原型:
size_t xPortGetFreeHeapSize(void);
函数参数:
- 无参数。
返回值:
- 返回当前可用的堆内存大小,单位是字节。
函数作用:
xPortGetFreeHeapSize()
用于获取系统堆中当前剩余的可用内存量。该函数返回一个 size_t
类型的值,表示当前未分配的堆内存大小。
- 这个函数对于监控内存使用情况非常有用,特别是在嵌入式系统中,当系统内存使用接近上限时,开发者可以通过该函数检测系统的剩余内存,避免内存不足的问题。
4. xPortGetMinimumEverFreeHeapSize()
函数原型:
size_t xPortGetMinimumEverFreeHeapSize(void);
函数参数:
- 无参数。
返回值:
- 返回自系统启动以来,堆中未分配的最大内存量,单位是字节。
函数作用:
xPortGetMinimumEverFreeHeapSize()
用于返回系统自启动以来,堆内存中曾经出现过的最大空闲内存量。这个值有助于分析系统在运行过程中最大内存利用情况,从而为内存分配和系统性能优化提供数据支持。
- 该函数对于监控内存使用情况非常有帮助,尤其是在资源受限的嵌入式系统中。
5. vTaskAllocateMPURegions()
函数原型:
BaseType_t vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t *pxRegions );
函数参数:
xTask
:任务的句柄。pxRegions
:指向MemoryRegion_t
类型数组的指针,每个数组元素描述了任务可以访问的内存区域。
返回值:
pdPASS
:成功分配内存区域。errQUEUE_FULL
:内存区域分配失败。
函数作用:
vTaskAllocateMPURegions()
用于为任务分配内存区域。FreeRTOS 支持内存保护单元(MPU)来限制任务访问特定内存区域,确保任务只能访问被授权的内存区域。该函数在任务创建后调用,通常用于增强系统的内存安全性。
MemoryRegion_t
是一个结构体,用于描述内存区域的起始地址、大小以及访问权限(例如,是否可读、可写、可执行)。
6. xPortGetHeapStats()
函数原型:
void xPortGetHeapStats( HeapStats_t *pxHeapStats );
函数参数:
pxHeapStats
:指向HeapStats_t
结构体的指针。该结构体包含了堆的统计信息,如总堆大小、已分配内存、最大空闲块大小等。
返回值:
- 无返回值。
函数作用:
xPortGetHeapStats()
用于获取堆的统计信息。它将堆的当前使用情况、剩余内存、已分配内存的统计数据填充到 HeapStats_t
结构体中。这个函数适用于开发过程中对内存使用进行分析和调试。
-
HeapStats_t
结构体通常包含以下信息:- 总堆大小。
- 当前已分配的内存大小。
- 当前剩余的空闲内存大小。
- 堆中最大的空闲块的大小。
7. xPortRealloc()
函数原型:
void *xPortRealloc( void *pvPointer, size_t xSize );
函数参数:
pvPointer
:要重新分配内存的指针。xSize
:重新分配的内存大小(单位:字节)。
返回值:
void*
:返回指向重新分配内存的指针。如果重新分配失败,返回NULL
。
函数作用:
xPortRealloc()
用于重新分配之前通过 pvPortMalloc()
分配的内存块。如果需要更大的内存块,它会将原有内存块内容复制到新的位置。如果无法分配足够的内存,则返回 NULL
。
总结
在 FreeRTOS 中,内存管理对于嵌入式系统的稳定性和性能至关重要。FreeRTOS 提供了灵活的内存管理方案,允许开发者根据系统的需求选择合适的内存分配策略。以下是与内存管理相关的常用函数:
pvPortMalloc()
:从堆中分配内存。vPortFree()
:释放通过pvPortMalloc()
分配的内存。xPortGetFreeHeapSize()
:获取当前可用的堆内存大小。xPortGetMinimumEverFreeHeapSize()
:获取系统启动以来的最大空闲堆内存大小。vTaskAllocateMPURegions()
:为任务分配内存保护区域。xPortGetHeapStats()
:获取堆的统计信息。xPortRealloc()
:重新分配内存。
通过这些函数,FreeRTOS 提供了高效的内存分配和管理机制,帮助开发者实现灵活的内存使用策略和优化。
八、中断管理相关
中断管理是嵌入式系统中非常重要的一个部分,FreeRTOS 为我们提供了中断管理的基础框架,使得任务和中断之间能够高效地进行协作。在处理中断时,通常需要注意以下几个要点:
- 中断的优先级:合理设置中断的优先级,可以确保中断能够及时响应,避免中断服务例程(ISR)被不必要的中断打断。
- 中断与任务的协作:FreeRTOS 中的中断服务例程通常不能直接执行复杂操作,而是将工作委托给任务来完成。
下面,我们详细介绍一些与中断管理相关的常用函数。
1. 中断优先级与 FreeRTOS 的任务调度
在 FreeRTOS 中,系统的调度是基于优先级的,每个任务都有一个优先级。对于中断,FreeRTOS 也有相应的优先级管理机制。
1.1 configMAX_SYSCALL_INTERRUPT_PRIORITY
这个配置项用于设置 FreeRTOS 系统调用可以从中断中调用的最大优先级。任何优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY
的中断将不能调用 FreeRTOS 的 API 函数。
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 5 // 设置允许 FreeRTOS 系统调用的最大中断优先级
- 中断优先级高于
configMAX_SYSCALL_INTERRUPT_PRIORITY
:这些中断可以处理紧急的硬件事件,但不能直接与 FreeRTOS API 交互。 - 中断优先级低于或等于
configMAX_SYSCALL_INTERRUPT_PRIORITY
:这些中断可以安全地调用 FreeRTOS 的系统调用(如xQueueSend()
、xSemaphoreGive()
等)。
1.2 设置中断优先级
在一些微控制器中(如 ARM Cortex-M 系列),可以使用 NVIC
(嵌套向量中断控制器)来设置中断的优先级。
例如:
NVIC_SetPriority(EXTI0_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY);
这行代码设置了外部中断 0(按键中断)的优先级。
2. 中断服务例程(ISR)与任务的协作
中断服务例程(ISR)是处理硬件中断的地方。在 FreeRTOS 中,ISR 通常用于处理硬件事件并通过 中断安全的 API 通知任务。常用的方法是通过 信号量、队列 或 事件标志 来通知任务处理事件。
2.1 xSemaphoreGiveFromISR()
在 ISR 中,不能直接执行阻塞操作(例如 xSemaphoreGive()
),因为中断执行期间任务调度和阻塞操作会导致中断响应延迟。因此,FreeRTOS 提供了专门为 ISR 设计的函数。
xSemaphoreGiveFromISR()
用于在 ISR 中释放信号量,并通过传递一个 pxHigherPriorityTaskWoken
参数,来通知调度器是否需要进行任务切换。
BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );
xSemaphore
:信号量句柄。pxHigherPriorityTaskWoken
:指示是否由于释放信号量导致高优先级任务被唤醒。如果是,设置为pdTRUE
。
如果需要在 ISR 中唤醒高优先级任务,pxHigherPriorityTaskWoken
会被设置为 pdTRUE
,并且会触发任务切换。
2.2 xQueueSendFromISR()
xQueueSendFromISR()
用于从 ISR 中向队列发送数据。这是一个非常典型的操作,用于将来自中断的数据传递给任务。
BaseType_t xQueueSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );
xQueue
:队列句柄。pvItemToQueue
:要发送到队列的数据指针。pxHigherPriorityTaskWoken
:指示是否需要进行任务切换。
这个函数允许在 ISR 中向任务传递信息。通过 pxHigherPriorityTaskWoken
,FreeRTOS 确保在 ISR 完成后进行适当的任务调度。
2.3 xEventGroupSetBitsFromISR()
如果使用事件组来管理任务间的同步,可以通过 xEventGroupSetBitsFromISR()
从 ISR 中设置事件标志。
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
xEventGroup
:事件组句柄。uxBitsToSet
:要设置的事件位掩码。pxHigherPriorityTaskWoken
:指示是否唤醒高优先级任务。
通过这种方式,ISR 可以设置事件组的位,并通知等待事件的任务执行。
3. 中断管理中的优先级控制与任务调度
3.1 portYIELD_FROM_ISR()
FreeRTOS 提供了 portYIELD_FROM_ISR()
函数,在 ISR 结束时判断是否需要进行任务切换。它会根据 pxHigherPriorityTaskWoken
的值决定是否唤醒更高优先级的任务。
portYIELD_FROM_ISR( pxHigherPriorityTaskWoken );
- 如果
pxHigherPriorityTaskWoken
为pdTRUE
,表示中断导致了高优先级任务被唤醒,FreeRTOS 会进行任务切换。
4. 按键中断处理的最佳实践
处理外部按键中断(如来自 GPIO 引脚的中断)时,一般采取以下步骤来确保系统的稳定性和效率:
-
简化 ISR:在中断服务例程中,只做最小的工作,比如清除中断标志、记录按键状态等,避免在 ISR 中执行复杂操作。
-
使用信号量或队列:通过
xSemaphoreGiveFromISR()
或xQueueSendFromISR()
等函数,将按键事件传递给任务进行处理。任务可以处理按键的去抖动、状态变化等复杂操作。void EXTI0_IRQHandler(void) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;// 清除中断标志EXTI_ClearITPendingBit(EXTI_Line0);// 通过信号量或队列通知任务xSemaphoreGiveFromISR(xButtonSemaphore, &xHigherPriorityTaskWoken);// 如果需要,高优先级任务唤醒portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
-
按键去抖动:在 ISR 中直接处理按键事件可能会导致去抖动问题。可以使用任务中的
vTaskDelay()
或软件去抖动算法来避免处理多次按键事件。 -
使用中断优先级管理:合理设置中断的优先级,确保高优先级的中断可以及时响应,并避免中断冲突。
总结
FreeRTOS 提供了一些强大的函数来管理中断和任务之间的协作。常用的中断管理函数包括:
xSemaphoreGiveFromISR()
:从 ISR 中释放信号量。xQueueSendFromISR()
:从 ISR 中发送队列消息。xEventGroupSetBitsFromISR()
:从 ISR 中设置事件标志。portYIELD_FROM_ISR()
:检查是否需要任务切换,并触发任务调度。- 合理设置中断优先级:通过
configMAX_SYSCALL_INTERRUPT_PRIORITY
和NVIC
设置,确保中断与任务调度协同工作。
通过这些机制,FreeRTOS 能够有效地处理硬件中断,并与任务调度系统配合,确保按键等外部中断事件的快速响应和处理。