freertos 源码分析五 任务调度一
vTaskStartScheduler
创建空闲进程, 调用适配xPortStartScheduler();
void vTaskStartScheduler( void )
{
xReturn = xTaskCreate( prvIdleTask,
configIDLE_TASK_NAME,
configMINIMAL_STACK_SIZE,
( void * ) NULL,
portPRIVILEGE_BIT,
&xIdleTaskHandle );
if( xReturn == pdPASS )
{
portDISABLE_INTERRUPTS();
xNextTaskUnblockTime = portMAX_DELAY;
xSchedulerRunning = pdTRUE;
xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
xPortStartScheduler();
}
else
{
configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
}
}
stm32,适配不同有差异
设置挂起中断和系统定时中断优先级,设置定时中断
BaseType_t xPortStartScheduler( void )
{
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; //pendsv 优先级
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; // systick 优先级
vPortSetupTimerInterrupt();
uxCriticalNesting = 0;
prvPortStartFirstTask();
vTaskSwitchContext();
prvTaskExitError();
return 0;
}
设置系统定时中断
__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
{
portNVIC_SYSTICK_CTRL_REG = 0UL;
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}
portNVIC_SYSTICK_LOAD_REG 系统定时计数器重载时间
portNVIC_SYSTICK_CTRL_REG
[2]CLKSOURCE 1 = core clock.
[1]TICKINT 1 = counting down to 0 pends the SysTick handler.
[0]ENABLE 1
prvPortStartFirstTask,调用svc中断
static void prvPortStartFirstTask( void )
{
__asm volatile (
" ldr r0, =0xE000ED08 \n"
" ldr r0, [r0] \n" //中断向量表偏移
" ldr r0, [r0] \n" // 取出中断向量表第一个数据 即栈顶指针
" msr msp, r0 \n" //设置msp指向栈顶
" cpsie i \n" // 开中断
" cpsie f \n" //开异常
" dsb \n" //数据同步屏障
" isb \n" //清空流水线
" svc 0 \n" //svc中断
" nop \n"
" .ltorg \n" // 数据缓冲池
);
}
恢复任务context
void vPortSVCHandler( void )
{
__asm volatile (
" ldr r3, pxCurrentTCBConst2 \n" //当前任务块
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" //第一个数据为任务块栈顶指针
" ldmia r0!, {r4-r11} \n" // 恢复r4-r11
" msr psp, r0 \n" //恢复栈
" isb \n" //清空流水线
" mov r0, #0 \n"
" msr basepri, r0 \n"
" orr r14, #0xd \n"
" bx r14 \n" //从中断返回
" \n"
" .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
);
}
就绪链表查找最高优先级,赋值给当前任务
void vTaskSwitchContext( void )
{
if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
{
xYieldPending = pdTRUE;
}
else
{
xYieldPending = pdFALSE;
taskSELECT_HIGHEST_PRIORITY_TASK();
}
}
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
UBaseType_t uxTopPriority = uxTopReadyPriority; \
\
\
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
{ \
configASSERT( uxTopPriority ); \
--uxTopPriority; \
} \
\
\
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
uxTopReadyPriority = uxTopPriority; \
}