首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ucos在s3c2410上运行过程整体剖析--创建任务到多任务调度及运行

ucos在s3c2410上运行过程整体剖析--创建任务到多任务调度及运行

直接开始说明ucos创建任务时的步骤:
1,  初始化任务堆栈
2,  初始化任务控制块
3,  把刚创建的任务设置为就绪态(即置位就绪表)
上面提到的任务堆栈,控制块,就绪表我们前面已经说过了,下面就直接看代码。
INT8U  OSTaskCreate (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio)
{
    OS_STK    *psp;
    INT8U      err;
#if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */
    OS_CPU_SR  cpu_sr;
    cpu_sr = 0;                              /* Prevent compiler warning                               */
#endif   
#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 (OSIntNesting > 0) {                  /* Make sure we don't create the task from within an ISR  */
        OS_EXIT_CRITICAL();
        return (OS_ERR_TASK_CREATE_ISR);
    }
    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, p_arg, 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) {
            if (OSRunning == TRUE) {         /* Find highest priority task if multitasking has started */
                OS_Sched(); //如果创建任务时ucos已经开始任务调度,那么创建完任务后需要进行任务调度
            }
        } 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);
}
下面是初始化堆栈的函数:
OS_STK * OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{//函数需要4个参数,一个指向任务函数的指针,任务运行时需要的参数,堆栈指针,扩展参数
    unsigned int * stk;

    stk    = (unsigned int *)ptos;          /* Load stack pointer */
    //USE_ARG(opt);
    opt++;

    /* build a stack for the new task */
    *--stk = (unsigned int) task;      /* pc */
    *--stk = (unsigned int) task;      /* lr */
    *--stk = 12;                       /* r12 */
    *--stk = 11;                       /* r11 */
    *--stk = 10;                       /* r10 */
    *--stk = 9;                        /* r9 */
    *--stk = 8;                        /* r8 */
    *--stk = 7;                        /* r7 */
    *--stk = 6;                        /* r6 */
    *--stk = 5;                        /* r5 */
    *--stk = 4;                        /* r4 */
    *--stk = 3;                        /* r3 */
    *--stk = 2;                        /* r2 */
    *--stk = 1;                        /* r1 */
    *--stk = (unsigned int) pdata;     /* r0 */
    *--stk = (SUPMODE);                          /* cpsr */
    *--stk = (SUPMODE);                          /* spsr */

    return ((OS_STK *)stk);
}
关于堆栈,我们前面已经讲过,这里用的即递减的满堆栈。
对于任务,其实就是一个无限循环的函数,那怎么控制它的运行那,这就是操作系统要干的活,操作系统根据调度算法实现对任务的调度以及任务的切换。实现了多个任务共享cpu。
我们已经知道,堆栈对任务的重要性,一:c语言执行需要堆栈空间。二:当发生任务切换时需要把程序运行的现场保存到任务的堆栈中。
也就是说,任务堆栈中应该保存的是任务运行时函数调用的情况以及被打断时的状态信息,可是问题来了,我们刚创建一个任务时,这个任务并没有运行过呀。这个好办,我们就模拟这个任务被打断过的迹象,任务没执行过,那么这个函数调用栈帧就不复存在。我们只模拟函数运行环境的保存。看上面代码,我们首先保存的是PC和LR,因为任务函数还没有执行过,因此这个PC和LR就应该是函数的首地址,也就是函数的名称指针。比如说你定义了一个任务函数
void Task1(void *Id)
{
       for(;;
              printf("run task1\n");
              OSTimeDly(1000);
       }
}
继承事业,薪火相传
返回列表