目录
创建任务的大概流程:
a.判断栈的生长方向——向下还是向上(M3系列栈的方向为向下生长(高地址到低地址))
b.申请栈空间(在内存中)
c.申请TCB空间(在内存中)(栈和堆都是在内存中的区域,只是功能不一样,栈存储函数中的局部变量还有函数的调用;堆存放全局变量)
d.将TCB中的栈指针指向申请的栈空间
e.标记栈的创建方法(是动态创建还是静态创建)
f.调用prvInitialiseNewTask函数初始化一些信息
g.调用prvAddNewTaskToReadyList函数加入到就绪列表
补充prvlnitialiseNewTask函数和prvAddNewTaskToReadyList函数
prvlnitialiseNewTask函数详细:
a.配置了configCHECK_FOR_STACK_OVERFLOW 大于1或者 configUSE_TRACE_FACILITY 或者 INCLUDE_uxTaskGetStackHighWaterMark,则栈中的内容将初始化成0xa5
b.保存栈顶指针的地址
c.TCB成员中的函数名称赋值(长度不能超过configMAX_TASK_NAME_LEN,该宏在FreeRTOSconfig.h文件中)
d.TCB中的任务优先级赋值(大于configMAX_PRIORITIES,则赋值为configMAX_PRIORITIES-1)
e.如果使能互斥信号量则保存原始优先级(在互斥信号量中,为了避免优先级翻转,所以会将低优先级的任务提高到与阻塞任务优先级一样高,有了这个就可以在使用完成后,恢复原来的优先级)
f.初始化状态列表项
g.初始化事件列表项(升序排列)
h.将状态列表项的所属指向当前TCB
i.修改事件列表项的值(configMAX_PRIORITIES-当前优先级)
j.将事件列表项的所属指向当前TCB
k.调用pxPortInitialiseStack函数(R4-R11,需要手动弹出,R0-R3,R12-R15,xPSR自动弹出)
l.将TCB赋值给任务句柄
prvAddNewTaskToReadyList函数详细:
a.进入临界区(第一次看到在将新任务加入到就绪列表)(关闭中断)
b.全局变量uxCurrentNumberOfTasks自加(表示任务总数量加1)
c.判断当前任务控制块是否为NULL(判断是否是第一个任务)
是:
1、将该控制块的值赋值给当前任务控制块
2、初始化所有列表(configMAX_PRIORITIES个就绪列表、两个延时列表(第一个是延时列表、第二个是延时溢出列表)、一个等待就绪列表(当任务调度器被挂起时,恢复的任务会被恢复到该列表,当任务调度器开启时,会全部添加到就绪列表中),一个等待删除列表(该列表是,当任务要删除自身时,不能马上删除,于是将待删除的任务添加到等待删除列表中,当进入空闲任务时,会删除全部等待删除列表中的所有任务),一个任务挂起列表)
否:
任务调度器未开启并且创建任务的优先级高于当前任务控制块,则将该任务控制块赋值给当前任务控制块。在将任务加入到任务就绪列表中,完结。
d.将任务加入到任务就绪列表中
e.退出临界区
f.当任务调度器开启时,创建任务的优先级高于当前任务控制块。触发PendSV中断切换一次任务。