嵌入式FreeRTOS学习十一,深入理解任务调度机制

一.任务调度机制

  • 可抢占:高优先级的任务先运行
  • 时间片轮转:同优先级的任务轮流执行
  • 空闲任务礼让:如果有同是优先级为0的其他就绪任务,空闲任务主动放弃一次运行机会
  • 函数调用vTaskDelay( xDelay5ms )可以主动放弃任务执行,让出CPU使用权
  • 系统中最低优先级中断比最高优先级任务大
int main( void )
{
	prvSetupHardware();
	
	xTaskCreate(vTask1, "Task 1", 1000, NULL, 0, NULL);
	xTaskCreate(vTask2, "Task 2", 1000, NULL, 0, NULL);
	xTaskCreate(vTask3, "Task 3", 1000, NULL, 2, NULL);

	/* 启动调度器 */
	vTaskStartScheduler();

	/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
	return 0;
}

=========================================================================

二.空闲任务函数 portTASK_FUNCTION( prvIdleTask, pvParameters )

static portTASK_FUNCTION( prvIdleTask, pvParameters )
{    
    ( void ) pvParameters;   
    portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
    for( ; ; )
    {      
        prvCheckTasksWaitingTermination();
        #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
            {               
                if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
                {
                    taskYIELD();
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
        #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
        #if ( configUSE_IDLE_HOOK == 1 )
            {
                extern void vApplicationIdleHook( void );               
                vApplicationIdleHook();
            }
        #endif /* configUSE_IDLE_HOOK */
        #endif /* configUSE_TICKLESS_IDLE */
    }
}

FreeRTOS操作系统中配置项 configUSE_PREEMPTION == 1表示同等优先级之间可抢占,配置项configIDLE_SHOULD_YIELD == 1 表示表示主动礼让,只有在任务可抢占的情况下,才考虑空闲礼让的情况。 

如果 配置选项配置为configUSE_PREEMPTION == 0不抢占的情况,那么直接进行礼让 taskYIELD(),任何其他的情况发生都是直接礼让。可抢占的时候可以配置是否礼让,不抢占中有礼让的这一种情况。

在空闲任务portTASK_FUNCTION中,会对任务就绪链表里的任务进行一次判断,如果当前任务就绪链表长度listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) )大于1,那么说明链表里面出了空闲任务外,还有其他的优先级为0的任务。那么空闲任务马上就做出任务礼让。其中tskIDLE_PRIORITY =0,即pxReadyTasksLists[ 0 ] 。

 礼让了其他任务以后,空闲任务函数执行 taskYIELD() 礼让其他任务,让其他任务先运行,函数执行到taskYIELD()后马上启动任务调度函数,任务调度函数执行任务Task1,任务Task2,任务Task3,等这三个任务运行完后,再执行回去执行空闲任务函数,从上次礼让的位置继续执行下去。

=========================================================================

可抢占可礼让的情况下,任务执行的的顺序是idle_task 执行一会后,马上执行任务Task 1,是否会执行任务Task 2,任务Task 3还得看任务是否会轮流执行。

在 xTaskIncrementTick函数中可以看到,只有配置成configUSE_PREEMPTION == 1可抢占和 configUSE_TIME_SLICING == 1时间片轮转的情况,任务Task2才可以得到执行。 不抢占不轮转,任务Task2永远得不到运行。

扫描二维码关注公众号,回复: 15353316 查看本文章

猜你喜欢

转载自blog.csdn.net/weixin_44651073/article/details/127947891
今日推荐