freeRtos調度函數代碼解讀

讀了一下下freeRTOS的代碼,結合代碼過一下freeRTOS調度器是怎麼工作的。

vTaskStartScheduler

創建完用戶的各種任務之後,調用函數vTaskStartScheduler便進入了任務調度,任務地阿杜這個函數做了三件事。

  1. 創建 idle 任務 , 以下便是這部分代碼

可以看出idle task的任務優先級被設置爲portPRIVILEGE_BIT, 而portPRIVILEGE_BIT被定義爲0x00,也就是最低優先級(freeRTOS中數字越大優先級越高)。換句話說,idle task的回調函數只有在系統“無事可做”的時候會被調用。

// The Idle task is created using user provided RAM
vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
// Create the idle task
xIdleTaskHandle = xTaskCreateStatic(	prvIdleTask,
							configIDLE_TASK_NAME,
							ulIdleTaskStackSize,
							( void * ) NULL, 
							portPRIVILEGE_BIT, 
							pxIdleTaskStackBuffer,
							pxIdleTaskTCBBuffer );
  1. 創建 timer task
		if( xReturn == pdPASS )
		{
			xReturn = xTimerCreateTimerTask();
		}
  1. 啓動timer task 和 最高優先級task ,即調用xPortStartScheduler
if( xPortStartScheduler() != pdFALSE )

然後進入xPortStartScheduler,這個函數並不在freeRTOS的三大源碼文件中,而是屬於port的一部分,以下代碼來自MSVC-MingW的實現(此代碼可運行於windows上)。

  • 啓動 tick 中斷

    pvHandle = CreateThread( NULL, 0, prvSimulatedPeripheralTimer, NULL, CREATE_SUSPENDED, NULL );
    	if( pvHandle != NULL )
    	{
    		SetThreadPriority( pvHandle, portSIMULATED_TIMER_THREAD_PRIORITY );
    		SetThreadPriorityBoost( pvHandle, TRUE );
    		SetThreadAffinityMask( pvHandle, 0x01 );
    		ResumeThread( pvHandle );
    	}
    
  • 啓動最高優先級任務

ResumeThread( pxThreadState->pvThread );

  • 調用函數ProcessSimulatedInterrupts

至此在此層函數範圍內程序不在往下執行,即程序進入函數·ProcessSimulatedInterrupts便不再出來了,ProcessSimulatedInterrupts的主題是一個死循環,完成任務的調度,如以下代碼。

static void prvProcessSimulatedInterrupts( void )
{
...
	for(;;)
	{
...
		for( i = 0; i < portMAX_INTERRUPTS; i++ )
		{
        ...
					if( ulIsrHandler[ i ]() != pdFALSE )
...
		}

		if( ulSwitchRequired != pdFALSE )
		{
			void *pvOldCurrentTCB;

			pvOldCurrentTCB = pxCurrentTCB;

			vTaskSwitchContext();

			/* If the task selected to enter the running state is not the task
			that is already in the running state. */
			if( pvOldCurrentTCB != pxCurrentTCB )
			{
				pxThreadState = ( ThreadState_t *) *( ( size_t * ) pvOldCurrentTCB );
				SuspendThread( pxThreadState->pvThread );

				xContext.ContextFlags = CONTEXT_INTEGER;
				( void ) GetThreadContext( pxThreadState->pvThread, &xContext );

				pxThreadState = ( ThreadState_t * ) ( *( size_t *) pxCurrentTCB );

				ResumeThread( pxThreadState->pvThread );
			}
		}

		pxThreadState = ( ThreadState_t * ) ( *( size_t *) pxCurrentTCB );
		SetEvent( pxThreadState->pvYieldEvent );
		ReleaseMutex( pvInterruptEventMutex );
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章