切换代码:
void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n"
" \n" /* Restore the context, including the critical nesting count. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers. */
" msr psp, r0 \n"
" bx r14 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
见 FreeRTOS V6.0.4 port.c, 其中的 vTaskSwitchContext 函数
void vTaskSwitchContext( void )
{
if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
{
/* The scheduler is currently suspended - do not allow a context
switch. */
xMissedYield = pdTRUE;
return;
}
traceTASK_SWITCHED_OUT();
#if ( configGENERATE_RUN_TIME_STATS == 1 )
{
unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
/* Add the amount of time the task has been running to the accumulated
time so far. The time the task started running was stored in
ulTaskSwitchedInTime. Note that there is no overflow protection here
so count values are only valid until the timer overflows. Generally
this will be about 1 hour assuming a 1uS timer increment. */
pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime );
ulTaskSwitchedInTime = ulTempCounter;
}
#endif
taskFIRST_CHECK_FOR_STACK_OVERFLOW();
taskSECOND_CHECK_FOR_STACK_OVERFLOW();
/* Find the highest priority queue that contains ready tasks. */
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
{
--uxTopReadyPriority;
}
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the
same priority get an equal share of the processor time. */
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );
traceTASK_SWITCHED_IN();
vWriteTraceToBuffer();
}
见 FreeRTOS V6.0.4 tasks.c |