前面文章两篇文章介绍了FreeRTOS的启动过程,但是有些问题还没有解决,在本篇文章中将会逐一解决。
首先,在《FreeRTOS内核源码解读之-------系统启动(一)》中提到Cortex-M4内核中两个不同的栈指针寄存器MSP和PSP。对于不具有嵌入式OS的应用,可以在操作中只使用MSP栈指针寄存器;对于含有嵌入式OS(就像FreeRTOS)应用,异常处理(包括内核状态下)使用的是MSP,对于应用任务使用的是PSP。每一个应用任务都有自己的栈空间,那么上面这种机制是怎么实现的呢?
还有FreeRTOS是一个多任务运行的操作系统,那么当一个任务正在运行时,会被优先级更高的任务或者中断打断,FreeRTOS是怎么保证被打断的任务在重新运行时不会出现问题?换句话说,如何实现保护现场、任务切换等?
本文从这两个问题触发,具体阐述FreeRTOS内核启动过程,在下一篇介绍FreeRTOS任务调度。
- 问题引入
- Cortex-M4对于多任务运行的硬件架构支持特性
一、问题引入
通过上一篇文章《FreeRTOS内核源码解读之-------系统启动()》分析,我们知道FreeRTOS最后调用prvStartFirstTask产生一个SVC中断,产生SVC中断之后,在函数vPortSVCHandler进行有FreeRTOS内核态到用户态的切换。两个函数的代码如下:
__asm void prvStartFirstTask( void )
{
PRESERVE8
/* Cortext-M3硬件中,0xE000ED08地址处为VTOR(向量表偏移量)寄存器,存储向量表起始地址*/
ldr r0, =0xE000ED08
ldr r0, [r0]
/* 取出向量表中的第一项,向量表第一项存储主堆栈指针MSP的初始值*/
ldr r0, [r0]
/* 将堆栈地址存入主堆栈指针 */
msr msp, r0
/* 使能全局中断*/
cpsie i
cpsie f
dsb
isb
/* 调用SVC启动第一个任务 */
svc 0
nop