freertos 源码分析四 任务创建的简单分析

任务创建xTaskCreate
为TCB和TCB栈分配空间, 初始化,加入就绪任务链表

#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName,
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )
    {    
        TCB_t * pxNewTCB;
        BaseType_t xReturn;
        #if ( portSTACK_GROWTH > 0 )
        {
            pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); 
            if( pxNewTCB != NULL )
            {
                memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) ); 
                pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); 
                if( pxNewTCB->pxStack == NULL )
                {
                    vPortFree( pxNewTCB );
                    pxNewTCB = NULL;
                }
            }
        }
        #else
        {
            StackType_t * pxStack;
            pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
            if( pxStack != NULL )
            {
                pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );                                                                            
                if( pxNewTCB != NULL )
                {
                    memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
                    pxNewTCB->pxStack = pxStack;
                }
                else
                {
                    vPortFreeStack( pxStack );
                }
            }
            else
            {
                pxNewTCB = NULL;
            }
        }
        #endif
        if( pxNewTCB != NULL )
        {
            #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
            {
                pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
            }
            #endif
            prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
            prvAddNewTaskToReadyList( pxNewTCB );
            xReturn = pdPASS;
        }
        else
        {
            xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
        }
        return xReturn;
    }
#endif

TCB初始化
设置栈顶栈底,任务名,优先级,初始化及填充状态消息表项。

static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
                                  const char * const pcName,
                                  const uint32_t ulStackDepth,                                                                                     
                                  void * const pvParameters,
                                  UBaseType_t uxPriority,
                                  TaskHandle_t * const pxCreatedTask,
                                  TCB_t * pxNewTCB,
                                  const MemoryRegion_t * const xRegions )
{
    StackType_t * pxTopOfStack;
    UBaseType_t x;


    #if ( portSTACK_GROWTH < 0 )
    {
        pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
        pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );                                                                                                                                                 
        configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
        #if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
        {
            pxNewTCB->pxEndOfStack = pxTopOfStack;
        }
        #endif
    }
    #else
    {
        pxTopOfStack = pxNewTCB->pxStack;
        configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
        pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
    }
    #endif
    
    if( pcName != NULL )
    {
        for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
        {
            pxNewTCB->pcTaskName[ x ] = pcName[ x ];
            if( pcName[ x ] == ( char ) 0x00 )
            {
                break;
            }

        }
        pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
    }


    configASSERT( uxPriority < configMAX_PRIORITIES );
    if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )                                                                                       
    {
        uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
    }

    pxNewTCB->uxPriority = uxPriority;
    #if ( configUSE_MUTEXES == 1 )
    {
        pxNewTCB->uxBasePriority = uxPriority;
    }
    #endif

    vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
    vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
    listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority );
    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );

    if( pxCreatedTask != NULL )
    {
        *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
    }

}

加入就绪态链表 禁中断 任务数加一,设为当前,开中断

static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )                                                                                           
{
    taskENTER_CRITICAL();  
    {
        uxCurrentNumberOfTasks++;
        if( pxCurrentTCB == NULL )
        {
            pxCurrentTCB = pxNewTCB;
            if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
            {
                prvInitialiseTaskLists();
            }

        }
        else
        {
            if( xSchedulerRunning == pdFALSE )
            {
                if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
                {
                    pxCurrentTCB = pxNewTCB;
                }

            }

        }
        uxTaskNumber++;

        prvAddTaskToReadyList( pxNewTCB );
    }
    taskEXIT_CRITICAL();
    if( xSchedulerRunning != pdFALSE )
    {
        if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
        {
            taskYIELD_IF_USING_PREEMPTION();
        }
    }
}

若是uxCurrentNumberOfTasks 为1,即第一个任务,初始化各链表

static void prvInitialiseTaskLists( void )
{
    UBaseType_t uxPriority;
    for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
    {
        vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
    }
    vListInitialise( &xDelayedTaskList1 );
    vListInitialise( &xDelayedTaskList2 );
    vListInitialise( &xPendingReadyList );
    #if ( INCLUDE_vTaskDelete == 1 )
    {
        vListInitialise( &xTasksWaitingTermination );
    }
    #endif
    #if ( INCLUDE_vTaskSuspend == 1 )
    {
        vListInitialise( &xSuspendedTaskList );
    }
    #endif
    pxDelayedTaskList = &xDelayedTaskList1;
    pxOverflowDelayedTaskList = &xDelayedTaskList2;
}  

prvAddTaskToReadyList宏定义

#define prvAddTaskToReadyList( pxTCB )                                                                 \
    traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                           \
    taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                \
    listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
    tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )

记录最高优先级

#define taskRECORD_READY_PRIORITY( uxPriority ) \
{                                               \
    if( ( uxPriority ) > uxTopReadyPriority )   \
    {                                           \
        uxTopReadyPriority = ( uxPriority );    \
    }                                           \
}

listINSERT_END 加入链表

taskYIELD_IF_USING_PREEMPTION 定义 
#if ( configUSE_PREEMPTION == 0 )
    #define taskYIELD_IF_USING_PREEMPTION()
#else
    #define taskYIELD_IF_USING_PREEMPTION()    portYIELD_WITHIN_API()                                                                              
#endif

#ifndef portYIELD_WITHIN_API
    #define portYIELD_WITHIN_API    portYIELD                                                                                                      
#endif
stm32对应portYIELD 定义 适配不同定义不同
#define portYIELD()||   |   |   |   __asm volatile ( "SWI 0" )
  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FreeRTOS 是一个开源的实时操作系统 (RTOS),被广泛用于嵌入式系统开发。它提供了多任务管理、内存管理、任务通信和同步等功能,适用于多种处理器架构和开发板。 如果你想进行 FreeRTOS 源码分析,以下是一些常见的步骤和建议: 1. 下载源码:你可以从 FreeRTOS 官方网站或 GitHub 上获取 FreeRTOS源码。确保下载适合你的目标硬件平台和编译器的版本。 2. 阅读文档:FreeRTOS 官方网站提供了详细的文档和用户指南,包括任务管理、内存管理、同步机制等方面的说明。阅读文档可以帮助你更好地理解系统的设计和使用方法。 3. 理解核心结构:FreeRTOS 的核心结构包括任务控制块 (TCB)、调度器、时间片和内核对象等。深入理解这些结构的作用和相互关系,可以帮助你分析系统的运行原理。 4. 调试和跟踪:使用适合你的开发环境和硬件平台的调试工具,可以对 FreeRTOS 进行调试和跟踪。你可以设置断点、监视任务状态、查看任务堆栈和中断处理等信息,以便更好地理解系统的运行过程。 5. 逐步分析代码:从 FreeRTOS任务入口点开始,逐步分析代码的执行流程。重点关注任务创建、调度、挂起和恢复等关键操作。通过阅读代码和调试,你可以更深入地了解 FreeRTOS 的实现细节。 6. 查阅社区资源:FreeRTOS 社区有许多活跃的开发者和用户,他们在论坛上分享了大量的问题解答、示例代码和优化技巧。查阅社区资源可以帮助你更好地理解 FreeRTOS 的使用和调试技巧。 请注意,由于 FreeRTOS 是一个相对复杂的系统,源码分析可能需要一定的时间和经验。建议你先从简单的示例程序开始,逐步深入研究源码。另外,参考官方文档和社区资源也是非常有帮助的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yvee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值