系列一:微型操作系统内核源码详解系列一:rtos内核源码概论篇(以freertos为例)-CSDN博客
系列二:微型操作系统内核源码详解系列二:数据结构和对象篇(以freertos为例)-CSDN博客
系列三:微型操作系统内核源码详解系列三(0):空间存储及内存管理篇(前置篇)-CSDN博客
微型操作系统内核源码详解系列三(1):任务及切换篇(任务函数定义)-CSDN博客
微型操作系统内核源码详解系列三(2):任务及切换篇(任务函数定义)-CSDN博客
微型操作系统内核源码详解系列三(3):任务及切换篇(任务函数定义)-CSDN博客
微型操作系统内核源码详解系列三(4):arm架构篇-CSDN博客
微型操作系统内核源码详解系列三(5):进程与线程-CSDN博客
系列四:
微型操作系统内核源码详解系列四(1):操作系统调度算法(linux0.11版本内核)-CSDN博客
微型操作系统内核源码详解系列四(2):操作系统调度算法(rt-thread内核)-CSDN博客
微型操作系统内核源码详解系列四(3):操作系统调度算法(FreeRTOS内核篇上)-CSDN博客
微型操作系统内核源码详解系列四(4):操作系统调度算法(FreeRTOS内核篇下)-CSDN博客
系列五:
微型操作系统内核源码详解系列五(1):arm cortex m3架构-CSDN博客
微型操作系统内核源码详解系列五(2):cm3下栈的初始化-CSDN博客
这一篇让笔者介绍arm cortex m3架构下任务栈的初始化,以入栈为例,如图是arm cm3下任务栈各个地址的内容:
让我们看看pxPortInitialiseStack函数是如何完成任务栈初始化的:
首先pxTopOfStack--,因为一开始它是指向栈顶的,自减后它指向栈内下一个地址,这个位置将会被保存到xPSR寄存器中,xPSR的24位被置1,表示这是Thumb指令状态,实际上cm3架构只支持Thumb指令状态。
xPSR这些寄存器请参考这篇博客,笔者认为讲得非常好:
[001] [ARM-Cortex-M3/4] 内部寄存器_xpsr寄存器-CSDN博客
现在来到下一个地址,
这一段代码是为了字节对齐:
pxCode是任务函数的地址,在arm架构中,分为arm指令集状态和Thumb指令集状态,你可以使用这两种指令集,区别是,Thumb指令集寄存器最低位是0,cm3下都是Thumb指令集,所以,为了预防未定义问题,必须把任务的地址最低位进行清0。
毫无疑问,这是为了保存LR寄存器,它是用于存储任务调用返回地址的专用寄存器,当一个函数被调用时,返回地址会被保存到 LR 寄存器中,以便在函数执行完毕后能够正确返回到调用该函数的下一条指令。但是,rtos中通常任务是不会返回的,所以这里的prvTaskEixtError其实是一个无限循环函数,用来调试:
这个错误返回函数代码如下:
r12,r3,r2,r1这四个寄存器通常是被用作传递作用,所以直接跳过:
R0用来保存任务形参,在之前的博客笔者貌似介绍过pvParameters,它会贯穿整个任务周期,可以被用来调试或传递作用:
在前文读者讲过LR寄存器,不过前一个保存到LR寄存器里的内容是一个用于调试的函数,为了发挥LR寄存器真正的作用,我们肯定要保存一个用于自身任务的返回值,所以这个中间的寄存器,保存了一个特殊的寄存器,被用作返回:
往下的八个寄存器,通常也是被用作参数传递等作用,无特殊含义,默认初始化为0,因此跳过即可:
最后返回栈顶指针,在栈顶指针下面就是空闲栈了(如果读者自己定义的栈空间有剩余的话),这些空闲栈浪费了资源,读者可以通过调试一步步缩小任务栈的大小,合理使用内存资源。