FreeRTOS 任务调度 任务切换

本文深入解析FreeRTOS的任务调度启动过程,包括vTaskStartScheduler函数的调用,以及Cortex-M3架构下移植层调度器的实现。在启动调度器后,系统会创建并运行首个任务。任务切换主要依赖于PendSV异常,实现高优先级任务的抢占和时间片轮转。FreeRTOS确保实时响应,避免中断响应延迟。
摘要由CSDN通过智能技术生成

@(嵌入式)

Freertos
FreeRtos

简述

前面文章 < FreeRTOS 任务调度 任务创建 > 介绍了 FreeRTOS 中如何创建任务以及其具体实现。
一般来说, 我们会在程序开始先创建若干个任务, 而此时任务调度器还没又开始运行,因此每一次任务创建后都会依据其优先级插入到就绪链表,同时保证全局变量 pxCurrentTCB 指向当前创建的所有任务中优先级最高的一个,但是任务还没开始运行。
当初始化完毕后,调用函数 vTaskStartScheduler启动任务调度器开始开始调度,此时,pxCurrentTCB所指的任务才开始运行。
所以, 本章,介绍任务调度器启动以及如何进行任务切换。

调度器涉及平台底层硬件操作,本文以Cotex-M3 架构为例, 具体可以参考 《Cortex-M3权威指南》(文末附)

分析的源码版本是 v9.0.0
(为了方便查看,github 上保留了一份源码Source目录下的拷贝)

启动调度器

创建任务后,系统不会自动启动任务调度器,需要用户调用函数 vTaskStartScheduler 启动调度器。 该函数被调用后,会先创建系统自己需要用到的任务,比如空闲任务 prvIdleTask,定时器管理的任务等。 之后, 调用移植层提供的函数 xPortStartScheduler
代码解析如下,

void vTaskStartScheduler( void )
{
    BaseType_t xReturn;
    #if( configSUPPORT_STATIC_ALLOCATION == 1 )
    {
        // 采用静态内存创建空闲任务
        StaticTask_t *pxIdleTaskTCBBuffer = NULL;
        StackType_t *pxIdleTaskStackBuffer = NULL;
        uint32_t ulIdleTaskStackSize;
        // 获取静态内存地址/参数
        vApplicationGetIdleTaskMemory(
            &pxIdleTaskTCBBuffer, 
            &pxIdleTaskStackBuffer, 
            &ulIdleTaskStackSize );
        // 创建任务
        // 空闲任务优先级为 0, 也就是其优先级最低
        // !! 但是, 设置了特权位, 所以其运行在 特权模式
        xIdleTaskHandle = xTaskCreateStatic(prvIdleTask, "IDLE", 
            ulIdleTaskStackSize, (void *) NULL, 
            (tskIDLE_PRIORITY | portPRIVILEGE_BIT), 
            pxIdleTaskStackBuffer,
            pxIdleTaskTCBBuffer); 

        if( xIdleTaskHandle != NULL )
        {
            xReturn = pdPASS;
        }
        else
        {
            xReturn = pdFAIL;
        }
    }
    #else
    {
        // 动态申请内存创建任务
        xReturn = xTaskCreate(prvIdleTask,
            "IDLE", configMINIMAL_STACK_SIZE,
            (void *)NULL,
            (tskIDLE_PRIORITY | portPRIVILEGE_BIT),
            &xIdleTaskHandle );     
    }
    #endif

    // 如果工程使用了软件定时器, 需要创建定时器任务进行管理
    #if ( configUSE_TIMERS == 1 )
    {
        if( xReturn == pdPASS )
        {
            xReturn = xTimerCreateTimerTask();
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
    }
    #endif

    if( xReturn == pdPASS )
    {

        // 关闭中断, 避免调度器运行前节拍定时器产生中断
        // 中断在第一个任务启动时恢复
        portDISABLE_INTERRUP
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值