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; \
}