任务的定义
在FreeRTOS中,任务共有三部分组成,即TCB、任务栈以及任务函数。
TCB——即任务控制块,其中记录着任务运行的基本信息,包括栈顶指针、优先级、挂载队列节点等参数。
任务栈——任务栈也属于TCB中的一部分,单独拿出来讲主要是因为任务切换的状态保存与恢复全都在任务中进行。
任务函数——这是我们能直观看到的任务执行的展示,它是一个无限循环的函数,如下所示:
void task_Function(void *pArg)
{
while(1)
{
//任务主体实现
}
}任务的创建流程
在实际使用过程中,我们指定完需要的参数后通过调用提供的任务创建函数便可以创建一个FreeRTOS任务,而其实在FreeRTOS内部,任务的创建可分为五个流程,即:
1、任务参数的二次赋值。
2、任务栈的初始化。
3、挂载节点的初始化。
4、列表初始化以及插入任务。
5、启动调度器。
调度器实现
获取当前正在运行挥着即将运行的任务
配置调度器的中断优先级为最低(注意这里指的是中断,最低优先级的中断的执行优先也大于最大的任务优先级)
获取msp的值(1、取出SCB_VTOR中向量表的地址 2、再根据向量表的地址获取向量表的值)
打开全局中断,使能SVC系统调用,随后执行SVC中断服务函数
要想中断服务函数有效,其名字必须要和中断向量表中的一致。
SVC中断服务函数中进行任务获取,r4-r11寄存器加载,并将r0的值(在加载寄存器时进行了自增)更新到psp(进程指针),使用0x0D按位或上r14寄存器的值(为了返回后CPU处于Thumb状态)。
异常返回,加载栈中其余寄存器到CPU寄存器中:xPSR、PC、R14、R12、R3、R2、R1、R0,同时更新PSP的值指向栈顶。
任务切换
任务切换通过taskYIELD()函数实现,该函数内使能了PendSV中断,在中断服务函数内完成了任务切换。
在进入PendSV中断服务函数时,xPSR、PC、R14、R12、R3、R2、R1、R0寄存器会自动加载到任务栈中,同时自动更新psp的值,将pCurrentTCB存储到r2中,随后手动加载其他寄存器,r0同步更新,随后将r0的值存储到r2(即pCurrentTCB的第一个元素——栈顶指针),以上就是上下文切换中的上文保存。
在进行下文切换前需要将r14和r3寄存器压入栈进行保护,因为接下来会进行函数vTaskSwitchContext调用,并且不确定会不会使用r3寄存器,随后关闭指定优先级的中断进入临界段,开始进行函数调用选择一个最高优先级的任务。
随后退出临界段,从主栈中恢复r3、14寄存器的值,根据r3寄存器的pCurrentTCB的地址,将其内容(pCurrentTCB)赋值给r1,同时加载r1指向的内容到r0,即栈顶指针,随后手动加载普通寄存器,并将r0的值更新到psp,等退出时会自动加载特殊寄存器。
——任务定义与调度器机制&spm=1001.2101.3001.5002&articleId=129441740&d=1&t=3&u=9106132ec5424299b57677b14c432a76)
372

被折叠的 条评论
为什么被折叠?



