FreeRTOS基本函数说明
- 0. FreeRTOS
- 1. 变量类型定义
- 2. 任务函数
-
- 1. 任务创建(==xTaskCreate==)
- 2. 任务删除(==vTaskDelete==)
- 3. 任务延时(==vTaskDelay== )
- 4. 任务延迟到指定时间(==vTaskDelayUntil==)
- 5. 获得任务优先级(==uxTaskPriorityGet== )
- 6. 设置任务优先级(==vTaskPrioritySet== )
- 7. 挂起任务(==vTaskSuspend==)
- 8. 唤醒挂起的任务(==vTaskResume==)
- 9. 从中断唤醒挂起的任务(==xTaskResumeFromISR==)
- 10. 为任务分配标签值(==vTaskSetApplicationTaskTag==)
- 3. 内核函数
- 4. 队列管理
-
- 1. 创建一个新的队列(==xQueueCreate==)
- 2. 传递一个项目到队列(==xQueueSend==)
- 3. 传递项目到一个队列中的后面(==xQueueSendToBack==)
- 4. 从队列接收一个项目(==xQueueReceive==)
- 5. 从中断传递一个项目到队列的后面(==xQueueSendFromISR==)
- 6.从中断传递项目到一个队列中的后面(==xQueueSendToBackFromISR==)
- 7. 从中断传递一个项到队列的前面(==xQueueSendToFrontFromISR==)
- 8. 中断时从队列接收一个项目(==xQueueReceiveFromISR==)
- 9. 为队列命名,并加入队列到登记管理中(==vQueueAddToRegistry==)
- 10. 从登记管理中移除队列(==vQueueUnregisterQueue==)
- 5. 信号量
-
- 1. 使用已存在的队列结构来创建计数型信号量(==xSemaphoreCreateCounting==)
- 2. 使用已存在的队列结构来创建互斥锁信号量的宏(==xSemaphoreCreateMutex==)
- 3. 使用已存在的队列结构来创建递归互斥锁的宏(==xSemaphoreCreateRecursiveMutex==)
- 4. 获取信号量的宏(==xSemaphoreTake==)
- 5. 递归获得互斥锁信号量的宏(==xSemaphoreTakeRecursive==)
- 6. 释放信号量的宏(==xSemaphoreGive==)
- 7. 用于递归释放,或“返还”,互斥锁信号量的宏(==xSemaphoreGiveRecursive==)
- 8. 从中断释放一个信号量的宏(==xSemaphoreGiveFromISR==)
0. FreeRTOS
作为一个轻量级的操作系统,FreeRTOS 提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能等,可基本满足较小系统的需要。FreeRTOS 内核支持优先级调度算法,每个任务可根据重要程度的不同被赋予一定的优先级,CPU 总是让处于就绪态的、优先级最高的任务先运行。FreeRT0S 内核同时支持轮换调度算法,系统允许不同的任务使用相同的优先级,在没有更高优先级任务就绪的情况下,同一优先级的任务共享CPU的使用时间。
FreeRTOS 的内核可根据用户需要设置为可剥夺型内核或不可剥夺型内核。当FreeRTOS 被设置为可剥夺型内核时,处于就绪态的高优先级任务能剥夺低优先级任务的CPU使用权,这样可保证系统满足实时性的要求;当FreeRTOS 被设置为不可剥夺型内核时,处于就绪态的高优先级任
务只有等当前运行任务主动释放CPU 的使用权后才能获得运行,这样可提高CPU 的运行效率,FreeRTOS对系统任务的数量没有限制。
1. 变量类型定义
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned portLONG
#define portBASE_TYPE long
2. 任务函数
1. 任务创建(xTaskCreate)
portBASE_TYPE xTaskCreate(
pdTASK_CODE pvTaskCode,
//指向任务的实现函数的指针。效果上仅仅是函数名
const portCHAR * const pcNane,
//具有描述性的任务名。FreeRTOS 不会使用它。
unsigned portSHORT usStackDepth,
//指定任务堆栈的大小
void *pvParameters,
//指针用于作为一个参数传向创建的任务
unsigned portBASE_TYPE uxPriority,
//任务运行时的优先级
xTaskHandle *pvCreatedTask
//用于传递任务的句柄,可以引用从而对任务进行其他操作。
)
说明:
- 这里的任务是指一个永远不会退出的C 函数,通常是一个死循环。
- pcNane 其只是单纯地用于辅助调试。应用程序可以通过定义常量
config_MAX_TASK_NAME_LEN 来定义任务名的最大长度,包括’\0’结束符。如果传入的字符串长度超过了这个最大值,字符串将会自动被截断。 - usStackDepth 这个值指定的是栈空间可以保存多少个字(word),而不是多少个字节(byte)。栈空间大小为usStackDepth*4(bytes)。
- uxPriority 优先级的取值范围可以从最低优先级0 到最高优先级(configMAX_PRIORITIES–1)。
返回:
- pdPASS 表明任务创建成功,准备运行。
- errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 由于内存堆空间不足,FreeRTOS 无法分配足够的空间来保存任务结构数据和任务栈,因此无法创建任务。
2. 任务删除(vTaskDelete)
void vTaskDelete(
xTaskHandle pxTask
//处理要删除的任务。传递 NULL将删除自己
)
说明:
- FreeRTOSConfig.h 中的INCLUDE_vTaskDelete=1,这个函数才能用。从RTOS 实时内核管理。
中移除任务。要删除的任务将从就绪,封锁,挂起,事件列表中移除。 - 任务被删除后就不复存在,也不会再进入运行态。
- 空闲任务负责释放内核分配给已删除任务的内存。
使用提示:
- 只有内核为任务分配的内存空间才会在任务被删除后由空闲任务自动回收。任务自己占用的内存或资源需要由应用程序自己显式地释放。
3. 任务延时(vTaskDelay )
void vTaskDelay(
portTickType xTicksToDelay
//时间数量,调用任务应该锁住的时间片周期
)
说明:
- FreeRTOSConfig.h 中的INCLUDE_vTaskDelay=1,这个函数才能用。
- 延时任务为已知时间片,任务被锁住剩余的实际时间由时间片速率决定。portTICK_RATE_MS 常量以时间片速率来计算实际时间。
- vTaskDelay()指定一个任务希望的时间段,这个时间之后任务解锁。
- vTaskDelay()不提供一个控制周期性任务频率的好方法,和其他任务和中断一样,在调用vTaskDelay()后将影响频率。
提示:
- vTaskDelayUntil() ,这个交替的API 函数设计了执行固定的频率。它是指定的一个绝对时间(而不是一个相对时间)后,调用任务解锁。可以实现周期性任务执行。
4. 任务延迟到指定时间(vTaskDelayUntil)
void vTaskDelayUntil(
portTickType *pxPreviousWakeTime,
//指定一个变量来掌握任务最后开启的时间, 第一次使用时必须使用
//当前时间来初始化, 在vTaskDelayUntil 中,这个变量是自动修改的
portTickType xTimeIncrement
//循环周期时间
)
说明:
- FreeRTOSConfig.h 中的INCLUDE_vTaskDelayUntil=1,这个函数才能用。
- 延时一个任务到指定时间,这个和vTaskDelay() 不同, vTaskDelay 是延时一个相对时间,而vTaskDelayUntil 是延时一个绝对时间。
- 常量 portTICK_RATE_MS 用来计算时间片频率的实时时间,按照一个时间片周期。
- 任务将在一定时间开启(*pxPreviousWakeTime + xTimeIncrement)。使用相同的xTimeIncrement 参数值来调用vTaskDelayUntil()将使任务按固定的周期执行。
注意:
- vTaskDelayUntil() 如果指定的苏醒时间使用完,将立即返回。因此,一个使用vTaskDelayUntil() 来周期性的执行的任务,如果执行周期因为任何原因(例如任务是临时为悬挂状态)暂停而导致任务错过一个或多个执行周期,那么需要重新计算苏醒时间。通过检 查像pxPreviousWakeTime 可变的参数来组织当前时间片计数。然而在大多数使用中并不是必须的。
使用提示:
- 如果一个任务想按固定的频率运行,如让一个LED 灯,按1KHz 频率运行,如果只有一个任务那么调用vTaskDelay 或vTaskDelayUntil 都能完成,但是如果有多个任务,vTaskDelay 就不行了,因为优先级或其它问题,它不知道什么时候再能运行,因此其不是周期执行,也就谈不上固定频率了