b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

freertos创建任务_freertos 任务_freertos任务切换

电脑杂谈  发布时间:2017-02-21 01:11:40  来源:网络整理

前面文章 < FreeRTOS 任务调度 任务创建 > 介绍了 FreeRTOS 中如何创建任务以及其具体实现。

一般来说, 我们会在程序开始先创建若干个任务, 而此时任务调度器还没又开始运行,因此每一次任务创建后都会依据其优先级插入到就绪链表,同时保证全局变量 pxCurrentTCB 指向当前创建的所有任务中优先级最高的一个,但是任务还没开始运行。

当初始化完毕后,调用函数 vTaskStartScheduler启动任务调度器开始开始调度,此时,pxCurrentTCB所指的任务才开始运行。

所以, 本章,介绍任务调度器启动以及如何进行任务切换。

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

分析的源码版本是 v9.0.0

(为了方便查看,github 上保留了一份源码Source目录下的拷贝)

创建任务后,系统不会自动启动任务调度器,需要用户调用函数 启动调度器。 该函数被调用后,会先创建系统自己需要用到的任务,比如空闲任务 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_INTERRUPTS();

        #if ( configUSE_NEWLIB_REENTRANT == 1 )
        {
            // 如果使用了这个库
            // 更新第一个任务的的指针到全局变量
            _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
        }
        #endif

        // 初始化变量
        xNextTaskUnblockTime = portMAX_DELAY;
        xSchedulerRunning = pdTRUE;
        xTickCount = ( TickType_t ) 0U;

        // 如果启动统计任务运行时间, 宏 configGENERATE_RUN_TIME_STATS = 1
        // 需要定义以下宏, 初始化一个定时器用于该功能 
        portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();

        // 设置系统节拍计数器, 启动任务
        // 硬件相关, 由系统移植层提供, 下面介绍
        if( xPortStartScheduler() != pdFALSE )
        {
            // 不会运行到这里, 如果调度器运行正常
        }
        else
        {
            // 当调用 xTaskEndScheduler()才会来到这里
        }
    }
    else
    {
        // 内存不足,创建空闲任务/定时任务失败, 调度器启动失败
        configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
    }

    // 预防编译器警告
    ( void ) xIdleTaskHandle;
}


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-33581-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 王南
      王南

      统一是大势所趋

    • 邓丽君
      邓丽君

      至于被平均的部份肯定在不你手中

    热点图片
    拼命载入中...