当前位置: 首页 > Windows7 > 正文

【μCOS-II】分析任务控制块的实现原理

一 实验目的

1 熟悉μCOS-II任务管理机制

2 掌握μCOS-II任务使用方法

二 实验内容

分析任务控制块的实现原理

三 实验步骤

1 在OS_Core.c中分析OSInit函数的功能;

2 在OS_Core.c中分析OS_InitTCBList函数的功能;

3 在OS_Task.c中分析OSTaskCreate函数的功能;

四 实验要求

提交实验报告

Creative Commons License本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。

本文固定链接: http://www.cuijinlin.com/2008/10/analysis-of-the-task-control-block-the-realization-of-the-principle-of.html | 崔金林的博客

该日志由 Nothing! 于2008年10月22日发表在 Windows7 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 【μCOS-II】分析任务控制块的实现原理 | 崔金林的博客
关键字:
  1. 3.建立任务,OSTaskCreate()
    想让µC/OS-Ⅱ管理用户的任务,用户必须要先建立任务。用户可以通过传递任务地址和其它参数到以下两个函数之一来建立任务:OSTaskCreate () 或 OSTaskCreateExt()。OSTaskCreate()与µC/OS是向下兼容的,OSTaskCreateExt()是 OSTaskCreate()的扩展版本,提供了一些附加的功能。用两个函数中的任何一个都可以建立任务。任务可以在多任务调度开始前建立,也可以在其它 任务的执行过程中被建立。在开始多任务调度(即调用OSStart())前,用户必须建立至少一个任务。任务不能由中断服务程序(ISR)来建立。

    OSTaskCreate ()的代码如程序清单 L4.1所述。从中可以知道,OSTaskCreate()需要四个参数:task是任务代码的指针,pdata是当任务开始执行时传递给任务的参数的指 针,ptos是分配给任务的堆栈的栈顶指针(参看4.02,任务堆栈),prio是分配给任务的优先级。

    程序清单 L4.1 OSTaskCreate()
    INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
    {
    void *psp;
    INT8U err;

    if (prio > OS_LOWEST_PRIO) { (1)
    return (OS_PRIO_INVALID);
    }
    OS_ENTER_CRITICAL();
    if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { (2)
    OSTCBPrioTbl[prio] = (OS_TCB *)1; (3)
    OS_EXIT_CRITICAL(); (4)
    psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); (5)
    err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); (6)
    if (err == OS_NO_ERR) { (7)
    OS_ENTER_CRITICAL();
    OSTaskCtr++; (8)
    OSTaskCreateHook(OSTCBPrioTbl[prio]); (9)
    OS_EXIT_CRITICAL();
    if (OSRunning) { (10)
    OSSched(); (11)
    }
    } else {
    OS_ENTER_CRITICAL();
    OSTCBPrioTbl[prio] = (OS_TCB *)0; (12)
    OS_EXIT_CRITICAL();
    }
    return (err);
    } else {
    OS_EXIT_CRITICAL();
    return (OS_PRIO_EXIST);
    }
    }

    OSTaskCreate ()一开始先检测分配给任务的优先级是否有效[L4.1(1)]。任务的优先级必须在0到OS_LOWEST_PRIO之间。接着, OSTaskCreate()要确保在规定的优先级上还没有建立任务[L4.1(2)]。在使用µC/OS-Ⅱ时,每个任务都有特定的优先级。如果某个优 先级是空闲的,µC/OS-Ⅱ通过放置一个非空指针在OSTCBPrioTbl[]中来保留该优先级[L4.1(3)]。这就使得 OSTaskCreate()在设置任务数据结构的其他部分时能重新允许中断[L4.1(4)]。
    然后,OSTaskCreate()调用 OSTaskStkInit()[L4.1(5)],它负责建立任务的堆栈。该函数是与处理器的硬件体系相关的函数,可以在OS_CPU_C.C文件中找 到。有关实现OSTaskStkInit()的细节可参看第8章——移植µC/OS-Ⅱ。如果已经有人在你用的处理器上成功地移植了µC/OS-Ⅱ,而你 又得到了他的代码,就不必考虑该函数的实现细节了。OSTaskStkInit()函数返回新的堆栈栈顶(psp),并被保存在任务的0S_TCB中。注 意用户得将传递给OSTaskStkInit()函数的第四个参数opt置0,因为OSTaskCreate()与OSTaskCreateExt()不 同,它不支持用户为任务的创建过程设置不同的选项,所以没有任何选项可以通过opt参数传递给OSTaskStkInit()。

  2. 1.在使用uCOS提供的任何功能之前,必须调用OSInIt()函数进行初始化。

  3. INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
    {
    #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
    OS_CPU_SR cpu_sr;
    #endif
    OS_STK *psp;
    INT8U err;

    #if OS_ARG_CHK_EN > 0
    if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */
    return (OS_PRIO_INVALID);
    }
    #endif
    OS_ENTER_CRITICAL();
    if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn’t already exist at this priority */
    OSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing … */
    /* … the same thing until task is created. */
    OS_EXIT_CRITICAL();
    psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); /* Initialize the task’s stack */
    err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
    if (err == OS_NO_ERR) {
    OS_ENTER_CRITICAL();
    OSTaskCtr++; /* Increment the #tasks counter */
    OS_EXIT_CRITICAL();
    if (OSRunning == TRUE) { /* Find highest priority task if multitasking has started */
    OS_Sched();
    }
    } else {
    OS_ENTER_CRITICAL();
    OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */
    OS_EXIT_CRITICAL();
    }
    return (err);
    }
    OS_EXIT_CRITICAL();
    return (OS_PRIO_EXIST);
    }
    #endif

  4. static void OS_InitTCBList (void)
    {
    INT8U i;
    OS_TCB *ptcb1;
    OS_TCB *ptcb2;

    OSTCBList = (OS_TCB *)0; /* TCB Initialization */
    for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) { /* Clear the priority table */ OSTCBPrioTbl[i] = (OS_TCB *)0; } ptcb1 = &OSTCBTbl[0]; ptcb2 = &OSTCBTbl[1]; for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { /* Init. list of free TCBs */ ptcb1->OSTCBNext = ptcb2;
    ptcb1++;
    ptcb2++;
    }
    ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */
    OSTCBFreeList = &OSTCBTbl[0];
    }

  5. void OSInit (void)
    {
    #if OS_VERSION >= 204
    OSInitHookBegin(); /* Call port specific initialization code */
    #endif

    OS_InitMisc(); /* Initialize miscellaneous variables */

    OS_InitRdyList(); /* Initialize the Ready List */
    OS_InitTCBList(); /* Initialize the free list of OS_TCBs */
    OS_InitEventList(); /* Initialize the free list of OS_EVENTs */

    #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
    OS_FlagInit(); /* Initialize the event flag structures */
    #endif

    #if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
    OS_MemInit(); /* Initialize the memory manager */
    #endif

    #if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
    OS_QInit(); /* Initialize the message queue structures */
    #endif

    OS_InitTaskIdle(); /* Create the Idle Task */
    #if OS_TASK_STAT_EN > 0
    OS_InitTaskStat(); /* Create the Statistic Task */
    #endif

    #if OS_VERSION >= 204
    OSInitHookEnd(); /* Call port specific init. code */
    #endif
    }