您的位置:控制工程论坛网论坛 » 教程与手册 » [转帖]浅析FreeRTOS_v4.5.0创建task任务函数---xTaskCreate()

cqs0088

cqs0088   |   当前状态:在线

总积分:-390  2024年可用积分:0

注册时间: 2008-07-12

最后登录时间: 2012-05-30

空间 发短消息加为好友

[转帖]浅析FreeRTOS_v4.5.0创建task任务函数---xTaskCreate()

cqs0088  发表于 2008/9/15 8:41:33      1037 查看 0 回复  [上一主题]  [下一主题]

手机阅读

[转帖]浅析FreeRTOS_v4.5.0创建task任务函数---xTaskCreate()

文章来源:http://gliethttp.cublog.cn


[注:以下为FreeRTOS_v4.5.0在at91sam7s64处理器上的task任务创建函数(gliethtp)]
signed portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask )
{
signed portBASE_TYPE xReturn;
tskTCB * pxNewTCB;
#if ( configUSE_TRACE_FACILITY == 1 )
//uxTaskNumber为任务id号,一般用来调试,每个任务会唯一对应一个处于[0,0xffffffff]范围之间的数值
//因为优先级并不能唯一表示一个task,所以为了能够唯一标识一个task,
//可以使用TCB或者TCB->uxTCBNumber
    static unsigned portBASE_TYPE uxTaskNumber = 0;
#endif
//动态申请tskTCB存储区和usStackDepth堆栈存储区
//FreeRTOS提供3中动态内存分配机制,具体可参见《浅析FreeRTOS_v4.5.0内存分配与回收及其改进方案》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_392500.html
    pxNewTCB = prvAllocateTCBAndStack( usStackDepth );

    if( pxNewTCB != NULL )
    {        
        portSTACK_TYPE *pxTopOfStack;
//对task的
//pxTCB->pcTaskName
//pxTCB->uxBasePriority
//pxTCB->xGenericListItem
//pxTCB->xEventListItem进行初始化,
//将xEventListItem->xItemValue值置为configMAX_PRIORITIES - ( portTickType ) uxPriority
//所以xEventListItem->xItemValue的最小值为1.(注:非0[gliethttp])
        prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority );

        #if portSTACK_GROWTH < 0
        {
            //堆栈是向下生长的,at91sam7s64就是以这种方式来生长堆栈
            pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
        }
        #else
        {
            pxTopOfStack = pxNewTCB->pxStack;    
        }
        #endif
        //初始化该task对应的堆栈空间
        //具体可参见《浅析FreeRTOS_v4.5.0的任务切换原理和栈结构》
        //文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html
        //需要注意的是pvTaskCode应该+4,即lr-4,这样来模拟IRQ,
        //pxNewTCB->pxTopOfStack存放了当前task使用到的sp栈顶值
        pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pvTaskCode, pvParameters );

        portENTER_CRITICAL();//原子操作
        {
            uxCurrentNumberOfTasks++;
            if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
            {
                //这是FreeRTOS系统创建的第1个任务,那么初始化FreeRTOS的一些基础量:
                //1.pxReadyTasksLists队列链表
                //2.xDelayedTaskList1队列链表
                //3.xDelayedTaskList2队列链表
                //4.xPendingReadyList队列链表
                //5.xTasksWaitingTermination队列链表
                //6.xSuspendedTaskList队列链表
                //7.pxDelayedTaskList = &xDelayedTaskList1;暂时的前台时间队列链表
                //8.pxOverflowDelayedTaskList = &xDelayedTaskList2;暂时的后台时间队列链表
                pxCurrentTCB = pxNewTCB;
                prvInitialiseTaskLists();
            }
            else
            {    
                if( xSchedulerRunning == pdFALSE )
                {//当前FreeRTOS还没有启动调度器,
                 //那么当前pxCurrentTCB需要是指向最高优先级任务
                    if( pxCurrentTCB->uxPriority <= uxPriority )
                    {
                        //比它高,所以pxNewTCB应该做当前任务
                        pxCurrentTCB = pxNewTCB;
                    }
                }
            }                

            if( pxNewTCB->uxPriority > uxTopUsedPriority )
            {
                uxTopUsedPriority = pxNewTCB->uxPriority;//在vTaskList()中使用到了
            }

            #if ( configUSE_TRACE_FACILITY == 1 )
            {
                pxNewTCB->uxTCBNumber = uxTaskNumber;//存储新创建的task的id号
                uxTaskNumber++;//id号+1,以便供下一个创建的task使用
            }
            #endif
//#define prvAddTaskToReadyQueue( pxTCB )                                       \
//{                                                                             \
//    if( pxTCB->uxPriority > uxTopReadyPriority )                              \
//    {                                                                         \
//        uxTopReadyPriority = pxTCB->uxPriority;                               \
//    }                                                                         \
//    vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) );\
//}
//把新创建的task添加到就绪运行队列链表中,
//本task会被插入到pxReadyTasksLists中自己优先级所对应的数组下
//这时本task对应优先级的数组可能已经有同优先级的任务在上边了,
//没关系,只需要将本task添加到轮转调度的最后位置即可,对于FreeRTOS轮转调度的理解,
//可以参见《浅析FreeRTOS_v4.5.0的任务切换原理和栈结构》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html
            prvAddTaskToReadyQueue( pxNewTCB );
            xReturn = pdPASS;//标示成功创建
        }
        portEXIT_CRITICAL();//原子操作结束
    }
    else
    {
        xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
    }

    if( xReturn == pdPASS )
    {
        if( ( void * ) pxCreatedTask != NULL )
        {
            *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
//把创建的TCB,传递到外界参数pxCreatedTask中
        }

        if( xSchedulerRunning != pdFALSE )
        {//os已经正常启动
            if( pxCurrentTCB->uxPriority < uxPriority )
            {
                //新创建的task-B的优先级比调用创建函数xTaskCreate()的task-A的优先级高
                //那么task-B立即抢占task-A,取得cpu的使用权
                //可以参见《浅析FreeRTOS_v4.5.0的任务切换原理和栈结构》
                //文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html
                taskYIELD();
            }
        }
    }
    return xReturn;//返回xTaskCreate()函数的执行结果
}

1楼 0 0 回复