FreeRTOS 启动第一个线程的步骤
从main函数开始,初始化完成之后,通过SVC指令的中断函数来,初始化成需要的寄存器值,才能正常运行线程.
1,启动第一个线程函数prvStartFirstTask()
调用prvStartFirstTask前的,寄存器值如下
代码分析
__asm void prvStartFirstTask( void )
{
//指令指定当前文件保持堆栈八字节对齐。 它设置 PRES8 编译属性以通知链接器。
PRESERVE8
/* 通过中断向量表获取MSP的地址 */
ldr r0, =0xE000ED08
ldr r0, [r0]
ldr r0, [r0]
/* Set the msp back to the start of the stack. */
msr msp, r0
mov r0, #0
//初始化control寄存器
msr control, r0
/* Globally enable interrupts. */
cpsie i
cpsie f
dsb
isb
/* 通过SVC指令,启动线程
Call SVC to start the first task. */
svc 0
nop
nop
}
调用SVC时候的寄存器值
2,在SVC指令的中断函数中,设置线程属性.
__asm void vPortSVCHandler( void )
{
PRESERVE8
/* 获取当前优先级最高的线程的TCB属性. */
ldr r3, =pxCurrentTCB
ldr r1, [r3]
ldr r0, [r1]
/* 设置寄存器 */
ldmia r0!, {r4-r11, r14}
//设置PSP
msr psp, r0
isb
mov r0, #0
msr basepri, r0
//通过此函数MSP->PSP
bx r14
}
bx r14:指令是通过R14的值来判断SP的属性(LR=R14=0xFFFFFFFD 代表PSP)
3,切换到线程后(最高优先级线程 TimerTask),通过线程中事前预存的数据,初始化寄存器值.这样线程就正常运行了.