freertos-内部机制:栈和寄存器变化
首先为了不会绕晕,需要明确概念:寄存器是公用的,栈是私有的,因为寄存器轮着用所以才需要将寄存器值压入栈,当压入栈后,寄存器就可以进行值的更新。
创建任务
创建任务本质是伪造现场,由于之后的启动任务需要进行现场的保存,但在没有任务即任务现场不存在的情况下需要进行伪造。
具体是栈的创建分配和寄存器值的写入:如下图,比较重要的是任务函数的地址(写入返回地址,因为中断切换任务时,主要就是切入到任务函数中)和传参R0
然后需要将这个栈的地址R4如图中200003CC保存在一个记录栈地址的数组中
启动任务
主栈:
启动任务或者任务调度本身是一个死循环while,通过中断进行任务调度。按程序顺序分析,在main函数中调用任务启动start_task函数,此时由于从main函数进入了子函数,LR寄存器记录了start_task函数的下一条指令;在start_task中进入while死循环,当任务1启动即出现中断时,“返回地址”寄存器记录了中断返回地址为while,即中断结束回到while循环;产生中断时,硬件自动将包含LR和“返回地址”等寄存器压入主栈;同时LR被赋予一个特殊值(EXC_RETURN);进入中断,首先进入System_Handler_asm,这里软件将R4~R11寄存器和LR压入主栈,同时LR写入R0,R1指向主栈。
任务1栈:
进入System_Handler,传参为R0,R1,此时由于进入子函数LR赋值为System_Handler下一条指令;System_Handler中,有三条分支,其中分支2为启动任务,首先找出任务1栈的地址,进入函数StartTask_asm,传参为任务1栈和R0,根据任务1栈软件恢复R4~R11寄存器,同时BX R0指令实现硬件恢复剩余寄存器。
切换任务
任务1栈:
硬件自动将包含LR和“返回地址”等寄存器压入任务1栈,同时LR被赋予一个特殊值(EXC_RETURN);进入中断,首先进入System_Handler_asm,软件保存任务1的R4~R11寄存器值到任务1栈,同时LR写入R0,R1指向任务1栈。
任务2栈:
进入System_Handler,传参为R0,R1,此时由于进入子函数LR赋值为System_Handler下一条指令;System_Handler中,有三条分支,其中分支3为切换任务,首先记录任务1栈进入数组,找出任务栈2的地址,进入函数StartTask_asm,传参为任务2栈和R0,根据任务2栈软件恢复R4~R11寄存器,同时BX R0指令实现硬件恢复剩余寄存器。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通