当前位置:网站首页>FreeRTOS任务基础
FreeRTOS任务基础
2022-08-09 22:39:00 【小梁不偷懒】
任务特性
- 没有数量限制(一个优先级下也可以拥有多个任务)
- 支持抢占(FreeRTOS为抢占式内核高优先级可以抢占低优先级的CPU使用权)
- 支持优先级(决定任务运行的先后)
- 每个任务都拥有堆栈导致了RAM使用量增大
- 抢占需考虑重入问题
任务状态
- 运行态(当前任务正在运行就是运行态)
- 就绪态(任务准备运行,所有就绪态态中优先级最高的任务下一次运行)
- 阻塞态(某个需要事件来引发的任务,事件没有发生时该任务的状态)
- 挂起态(暂停运行,有挂起和解挂两个过程)
这四个状态是可以互相转化的,刚创建好的任务是处于就绪态的,具体的转化过程如下图所示:
任务优先级
任务的优先级决定了任务执行的先后,在FreeRTOS中有32个优先级即0到31,数字越大优先级越高!
任务实现
void vATaskFunction(void *pvParameters)
{
while(1)//for(;;)
{
任务程序
vTaskDelay();
}
vTaskDelay();
}
上方代码为任务实现的基本框架,要注意的是任务中途不能返回或退出,如果一定要退出的话需要调用vTaskDelay(NULL)来删除此任务。
任务控制块(描述任务属性的数据结构)
FreeRTOS 的每个任务都有一些属性需要存储,FreeRTOS 把这些属性集合到一起用一个结
构体来表示,这个结构体叫做任务控制块:TCB_t,在使用函数 xTaskCreate()创建任务的时候就会自动的给每个任务分配一个任务控制块。
typedef struct tskTaskControlBlock
{
volatile StackType_t *pxTopOfStack; //任务堆栈栈顶
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGSxMPUSettings; //MPU 相关设置
#endif
ListItem_t xStateListItem; //状态列表项
ListItem_t xEventListItem; //事件列表项
UBaseType_t uxPriority; //任务优先级
StackType_t *pxStack; //任务堆栈起始地址
char pcTaskName[ configMAX_TASK_NAME_LEN ];//任务名字
#if ( portSTACK_GROWTH > 0 )
StackType_t *pxEndOfStack; //任务堆栈栈底
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting; //临界区嵌套深度
#endif
#if ( configUSE_TRACE_FACILITY == 1 ) //trace 或到 debug 的时候用到
UBaseType_t uxTCBNumber;
UBaseType_t uxTaskNumber;
#endif
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxBasePriority; //任务基础优先级,优先级反转的时候用到
UBaseType_t uxMutexesHeld; //任务获取到的互斥信号量个数
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t pxTaskTag;
#endif
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) //与本地存储有关
void
*pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#if( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulRunTimeCounter; //用来记录任务运行总时间
#endif
#if ( configUSE_NEWLIB_REENTRANT == 1 )
struct _reent xNewLib_reent; //定义一个 newlib 结构体变量
#endif
#if( configUSE_TASK_NOTIFICATIONS == 1 )//任务通知相关变量
volatile uint32_t ulNotifiedValue; //任务通知值
volatile uint8_t ucNotifyState; //任务通知状态
#endif
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
//用来标记任务是动态创建的还是静态创建的,如果是静态创建的此变量就为 pdTURE,
//如果是动态创建的就为 pdFALSE
uint8_t ucStaticallyAllocated;
#endif
#if( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDelayAborted;
#endif
} tskTCB;
//新版本的 FreeRTOS 任务控制块重命名为 TCB_t,但是本质上还是 tskTCB,主要是为了兼容
//旧版本的应用。
typedef tskTCB TCB_t;
上述代码为TCB_t结构体在tasks.c 中的定义。
任务堆栈
FreeRTOS是依靠堆栈来回复一个任务的运行的,任务调度器在切换任务的时候就是使用堆栈来恢复任务原现场的。
创建任务的时候需要给任务指定堆栈,如果使用的函数 xTaskCreate()创建任务(动态方法)
的话那么任务堆栈就会由函数 xTaskCreate()自动创建;如果使用函数 xTaskCreateStatic()创建任务(静态方法)的话就需要程序员自行定义任务堆栈,然。后堆栈首地址作为函数的参数 puxStackBuffer 传递给函数。
堆栈的大小
不管是使用函数 xTaskCreate()还是 xTaskCreateStatic()创建任务都需要指定任务堆栈大小。任务堆栈的数据类型为 StackType_t,StackType_t 本质上是 uint32_t,在 portmacro.h 中有如下定义
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
注意:StackType_t 类型的变量为 4 个字节,那么任务的实际堆栈大小就应该是我们所
定义的 4 倍
边栏推荐
猜你喜欢
随机推荐
matplotlib散点图自定义坐标轴(文字坐标轴)
经济衰退即将来临前CIO控制成本的七种方法
深入理解多线程(第一篇)
Gumbel distribution of discrete choice model
测试2年,当时身边一起入行的朋友已经月薪20k了,自己还没过万,到底差在了哪里?
【集训DAY3】挖金矿【二分答案】
Has your phone ever been monitored?
Gartner's global integrated system market data tracking, hyperconverged market growth rate is the first
tiup cluster scale-out
【接口测试】requests 库请求体字符串解码
【集训DAY3】中位数
LiveData : Transformations.map and Transformations.switchMap usage
直播平台怎么搭建,原生js实现编辑器撤消/恢复功能
JSON对象和字符串相互转化
力扣:474.一和零
HStreamDB v0.9 发布:分区模型扩展,支持与外部系统集成
What are the Shenzhen fortress machine manufacturers?Which one do you recommend?
ABAP中Collect的用法
SRv6性能测量
Gold Warehouse Database KingbaseGIS User Manual (6.2. Management Functions)