目录
1、创建任务的函数
举例:动态分配内存创建
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char * const pcName, // 任务名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位word,表示4字节
void * const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t * const pxCreatedTask ); // 任务句柄
三个核心:①执行函数;②栈的大小;③优先级
对于一个任务并没有什么复杂的,它可以说是一个“函数”,其它的参数倒是不怎么重要。
但是需要给它提供一个栈,因为在函数运行的时候有调用关系、局部变量,这些东西都保存在栈里面;还有,任务有可能被暂停,此时CPU寄存器都得保存在栈里面。
2、如何创建任务
继续点进去,看到它的定义,将无关紧要的部分删除之后,剩下的就是TCB的主要内容
举个例子:
那么函数指针和调用任务时传入的参数在TCB里面怎么没有体现?
原因就是创建任务时,“myTask”这个函数指针的地址被保存在PC寄存器;
同时由于函数的调用关系,“NULL”这个参数的被保存在R0寄存器里;
void myFirstTask(void *argument);
也就是说,通过TCB里面的两个栈指针,就能找到着两个参数。
3、任务调度机制
3.1 优先级
①高优先级的任务,优先执行,可以抢占低优先级的任务
②对于实时系统,高优先级的任务不停止,低优先级的任务永远无法执行
③同等优先级的任务,时间片轮转
3.2 状态
运行态:running
就绪态:ready
阻塞:blocked,等待某件事(时间、事件)
暂停:suspend,休息
3.3 调度方法与状态切换
①找到最高优先级的运行态、就绪态任务,运行它
②如果大家平级,排队轮流执行;链表前面的先运行,运行1个tick后去链表尾部排队
3.4 调度的本质就是链表切换
①可抢占:高优先级的任务先运行
②时间片轮转:同优先级的任务轮流执行
③空闲任务礼让:如果有同是优先级0的其他就绪任务,空闲任务主动放弃一次运行机会
*-------------------------------------------------------有个有意思的地方-----------------------------------------------*
由于有空闲任务的存在,就会发生以下情况: