2009-5-10
作为
main
函数中的最后一个重量级函数
vTaskStartScheduler
。今天就在这里做个了断吧!
原来如此,这个函数一上来二话不��嗦,直接
create
了一个
task
,嗯,就是大名鼎鼎的
idletask
。
xReturn = xTaskCreate( prvIdleTask, ( signed portCHAR * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );
按理说在创建完
idletask
之后就应该直接
startscheduler
了,但是,这里还有很重要的一些动作还没有表演完。
Interrupts are turned off here, to ensure a tick does not occur before or during the call to xPortStartScheduler().The stacks of the created tasks contain a status word with interrupts switched on so interrupts will automatically get re-enabled when the first task starts to run.
嗯,就是这个,所以下面紧接着的是
portDISABLE_INTERRUPTS();//
对,这个也是平台相关的
【
#define portDISABLE_INTERRUPTS() vPortSetInterruptMask()//
很明显这个是要平台来实现的了】
xSchedulerRunning = pdTRUE;
xTickCount = ( portTickType ) 0;
很正点的语句,且不可或缺!
接下来才是主角的登场。
portBASE_TYPE xPortStartScheduler( void )
这个函数依然是平台相关的,从函数名也可以看出来的。具体实现在个平台下的
port.c
中。
portBASE_TYPE xPortStartScheduler( void )
{
/* Make PendSV and SysTick the lowest priority interrupts. */
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */
vPortStartFirstTask();
/* Should not get here! */
return 0;
}
这个是
iar/arm_cm3
的实现,注释很详细,在此不多说了。还是说说最后的那个函数调用吧
void vPortStartFirstTask( void )
{
asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" svc 0 \n" /* System call to start first task. */
);
}
这就是精华,看来是要好好研究研究
arm
的汇编啊!