任务调度由SysTick_Handler和 PendSV_Handler两个中断接管
 系统时钟计数器按给定频率倒计时,至0触发SysTick_Handler中断,此中断函数为宏中对xPortSysTickHandler的重命名。
 增加计数,置位可挂起中断。
void xPortSysTickHandler( void )
{portDISABLE_INTERRUPTS();{if( xTaskIncrementTick() != pdFALSE ){portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;}}portENABLE_INTERRUPTS();
}
xTaskIncrementTick 以设定频率增加计数,处理延时任务。
BaseType_t xTaskIncrementTick( void )
{TCB_t * pxTCB;                                                                                                                                 TickType_t xItemValue;BaseType_t xSwitchRequired = pdFALSE;if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ){const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;xTickCount = xConstTickCount;if( xConstTickCount == ( TickType_t ) 0U ){taskSWITCH_DELAYED_LISTS();  //计数溢出 交换延时链表与溢出链表}if( xConstTickCount >= xNextTaskUnblockTime )   //处理延时链表{for( ; ; ){if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )  //空{xNextTaskUnblockTime = portMAX_DELAY;break;}else  //非空{pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );if( xConstTickCount < xItemValue ){                                                                                                                              xNextTaskUnblockTime = xItemValue;break;}listREMOVE_ITEM( &( pxTCB->xStateListItem ) );  //延时已过if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ){listREMOVE_ITEM( &( pxTCB->xEventListItem ) );}prvAddTaskToReadyList( pxTCB );  //添至就绪链表#if ( configUSE_PREEMPTION == 1 ){if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ){xSwitchRequired = pdTRUE;  //优先级大于现运行任务需切换}}#endif}}}#if ( configUSE_PREEMPTION == 1 ){if( xYieldPending != pdFALSE ){xSwitchRequired = pdTRUE;}}#endif}else{++xPendedTicks;  // 增加计数}return xSwitchRequired;
}
listLIST_IS_EMPTY宏定义
#define listLIST_IS_EMPTY( pxList )   ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE ) 
可挂起中断,此中断函数在宏中重命名为PendSV_Handler。系统时钟中断中对其置位,以低优先级运行,无高于其优先级时会调入对任务进行切换。
void xPortPendSVHandler( void )
{__asm volatile("   mrs r0, psp                         \n""   isb                                 \n""   ldr r3, pxCurrentTCBConst           \n" //当前运行任务"   ldr r2, [r3]                        \n" "   stmdb r0!, {r4-r11}                 \n"  //保存r4-r11 psp"   str r0, [r2]                        \n"  //保存当前栈顶pxTopOfStack "   stmdb sp!, {r3, r14}                \n"  //保存r3 r14至msp"   mov r0, %0                          \n"  // 优先级"   msr basepri, r0                     \n"  "   bl vTaskSwitchContext               \n" // 在就绪链表寻找最高优先级设为当前切换任务"   mov r0, #0                          \n""   msr basepri, r0                     \n""   ldmia sp!, {r3, r14}                \n"  // 恢复 r3 lr"   ldr r1, [r3]                        \n"  //当前TCB指针 TCB已切换"   ldr r0, [r1]                        \n"  //当前TCB栈顶pxTopOfStack"   ldmia r0!, {r4-r11}                 \n"  //从TCB栈恢复 r4-r11 变动后指向任务参数"   msr psp, r0                         \n"  //psp栈指向tcb栈 "   isb                                 \n"  // "   bx r14                              \n"  // 中断返回从PSP栈恢复寄存器值,任务回调函数指针载入PC,完成任务切换。"                                       \n""   .align 4                            \n""pxCurrentTCBConst: .word pxCurrentTCB  \n"::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ));
}
参考创建任务时,任务堆栈设置
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,TaskFunction_t pxCode,void * pvParameters )
{pxTopOfStack--;                                                      *pxTopOfStack = portINITIAL_XPSR;   //thumb                                 pxTopOfStack--;*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; //task回调函数指针pxTopOfStack--;*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS;             /* LR */pxTopOfStack -= 5;                                                   /* R12, R3, R2 and R1. */*pxTopOfStack = ( StackType_t ) pvParameters;                        /* R0 */pxTopOfStack -= 8;                                                   /* R11, R10, R9, R8, R7, R6, R5 and R4. */return pxTopOfStack;
}