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

你可能感兴趣的:(嵌入式硬件)