FreeRTos----创建任务

任务块结构

typedef struct tskTaskControlBlock
{
    volatile StackType_t * pxTopOfStack;//栈顶指针
    ListItem_t xStateListItem;//状态列表项
    ListItem_t xEventListItem;//事件列表项
    UBaseType_t uxPriority;//任务优先级
    StackType_t * pxStack;//指向起始栈
    char pcTaskName[ configMAX_TASK_NAME_LEN ];//任务名称
    ......
} tskTCB;

//任务就绪列表
List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
//延时列表1
List_t xDelayedTaskList1;
//延时列表2,使用2个列表,1个正常延时,另一个当延时超过当前的tick计数值使用
List_t xDelayedTaskList2;
//指向当前延时任务列表
List_t * volatile pxDelayedTaskList;
//指向当前延时溢出任务列表
List_t * volatile pxOverflowDelayedTaskList;
//挂起任务列表 
List_t xPendingReadyList; 

1、动态创建任务函数xTaskCreate

    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName,
                            const configSTACK_DEPTH_TYPE uxStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )
    {
        TCB_t * pxNewTCB;
        BaseType_t xReturn;

        //创建新任务
        pxNewTCB = prvCreateTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask );

        if( pxNewTCB != NULL )
        {
            //创建成功,添加新的任务块到就绪列表
            prvAddNewTaskToReadyList( pxNewTCB );
            //返回成功
            xReturn = pdPASS;
        }
        else
        {
            //创建失败,返回失败
            xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
        }

        return xReturn;
    }
    static TCB_t * prvCreateTask( TaskFunction_t pxTaskCode,
                                  const char * const pcName,
                                  const configSTACK_DEPTH_TYPE uxStackDepth,
                                  void * const pvParameters,
                                  UBaseType_t uxPriority,
                                  TaskHandle_t * const pxCreatedTask )
    {
        TCB_t * pxNewTCB;

        //判断栈增长方向,STM32栈向上增长
        {
            StackType_t * pxStack;

            //分配uxStackDepth 长度的栈空间,给新建的任务使用
            pxStack = pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );

            if( pxStack != NULL )
            {
                //分配内存空间
                pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );

                if( pxNewTCB != NULL )
                {
                     //清空TCB_T结构空间
                     ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );

                    //任务控制块的pxStack指向新分配的栈空间
                    pxNewTCB->pxStack = pxStack;
                }
                else
                {
                    //任务控制块创建失败,释放pxStack 栈空间
                    vPortFreeStack( pxStack );
                }
            }
            else
            {
                pxNewTCB = NULL;
            }
        }

        if( pxNewTCB != NULL )
        {
            //初始化新任务
            prvInitialiseNewTask( pxTaskCode, pcName, uxStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
        }

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

    {
        //栈顶指针指向新创建的任务的函数起始栈空间
        pxTopOfStack = pxNewTCB->pxStack;
        pxTopOfStack = ( StackType_t * ) ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) + portBYTE_ALIGNMENT_MASK ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );


        //任务函数起始地址+函数分配栈大小-1,指向endOfStack
        pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( uxStackDepth - ( configSTACK_DEPTH_TYPE ) 1 );
    }

    //存储任务名称到任务控制块的pcTaskName
    if( pcName != NULL )
    {
        for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
        {
            pxNewTCB->pcTaskName[ x ] = pcName[ x ];

            /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
             * configMAX_TASK_NAME_LEN characters just in case the memory after the
             * string is not accessible (extremely unlikely). */
            if( pcName[ x ] == ( char ) 0x00 )
            {
                break;
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }

        //名字最后追加字符串'\0'
        pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1U ] = '\0';
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    //优先级检测
    configASSERT( uxPriority < configMAX_PRIORITIES );

    //设置优先级
    pxNewTCB->uxPriority = uxPriority;


    vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
    vListInitialiseItem( &( pxNewTCB->xEventListItem ) );

    /* Set the pxNewTCB as a link back from the ListItem_t.  This is so we can get
     * back to  the containing TCB from a generic item in a list. */
    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );

    /* Event lists are always in priority order. */
    listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority );
    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );


    if( pxCreatedTask != NULL )
    {
        /* Pass the handle out in an anonymous way.  The handle can be used to
         * change the created task's priority, delete the created task, etc.*/
        *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }
}

添加任务:void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )

static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
{
        //进入临界区,添加任务时不允许被中断打断
        taskENTER_CRITICAL();
        {
            //当前任务总数加1
            uxCurrentNumberOfTasks++;

            if( xSchedulerRunning == pdFALSE )
            {
                if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
                {
                    //创建第1个任务prvCreateIdleTasks()
                    prvInitialiseTaskLists();
                }
                .....................
            }
            
            //添加任务到就绪列表,新任务默认初始化后处于就绪状态
            prvAddTaskToReadyList( pxNewTCB );

            portSETUP_TCB( pxNewTCB );

            if( xSchedulerRunning != pdFALSE )
            {
                //新任务的优先级高于当前正在运行任务的优先级,直接切换当前任务到运行状态
                taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxNewTCB );
            }

        }
        //退出临界保护区
        taskEXIT_CRITICAL();
    }
#define prvAddTaskToReadyList( pxTCB )                                                                     
    do {  
        //在ready列表里面添加新的任务块                                                                                                                                             
        listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) );                                                  
    } while( 0 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值