zoukankan      html  css  js  c++  java
  • uC/OS-II源码分析(二)

    在真正开始分析源代码前,先来看使用uC/OS-II的三个例子

    1)使用信号量

    #define  TASK_STK_SIZE                 512       /* 每个任务堆栈的大小(以字计算)*/
    #define  N_TASKS                        10       /* 任务数*/

    OS_STK        TaskStk[N_TASKS][TASK_STK_SIZE];        /*任务堆栈*/
    OS_STK        TaskStartStk[TASK_STK_SIZE];            //开始任务的堆栈    
    char          TaskData[N_TASKS];                      /*传给每个任务的数据*/
    OS_EVENT     *RandomSem;                            //互斥型信号量

    void  main (void)
    {
        PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK);      /*清空屏幕*/

        OSInit();                                              /* 初始化uC/OS-II*/

        PC_DOSSaveReturn();                                    /* 保存环境以便稍后可以返回DOS环境*/
        PC_VectSet(uCOS, OSCtxSw);                             /*设置uC/OS-II的切换处理函数*/
        RandomSem   = OSSemCreate(1);                          /* 建立一个信号量*/
        OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);//创建第一个任务,优先级设置为最大值
        OSStart();                                             /* 开始多任务*/
    }
    void  TaskStart (void *pdata)
    {
    #if OS_CRITICAL_METHOD == 3                                /* 为CPU的状态寄存器分配内存*/
        OS_CPU_SR  cpu_sr;
    #endif
        char       s[100];
        INT16S     key;
        pdata = pdata;                                         /* 这步是为了防止编译错误*/
        TaskStartDispInit();                                   /* 初始化显示屏*/
        OS_ENTER_CRITICAL();
        PC_VectSet(0x08, OSTickISR);                           /*替换机器的时钟中断函数为uC/OS-II所需要的中断函数*/
        PC_SetTickRate(OS_TICKS_PER_SEC);                      /* 调整时钟频率*/
        OS_EXIT_CRITICAL();
        OSStatInit();                                          /* 初始化统计任务*/
        TaskStartCreateTasks();                                /*创建其他任务*/
        for (;;) {
            TaskStartDisp();                                


            if (PC_GetKey(&key) == TRUE) {                     /* 是否按键*/
                if (key == 0x1B) {                             /* ESCAPE按下了*/
                    PC_DOSReturn();                            /* 返回DOS*/
                }
            }

            OSCtxSwCtr = 0;                                    /* 切换次数计数器清零*/
            OSTimeDlyHMSM(0, 0, 1, 0);                         /*挂起秒,让给其他任务运行*/
        }
    }
    static  void  TaskStartCreateTasks (void)
    {
        INT8U  i;
        for (i = 0; i < N_TASKS; i++) {                        /* 创建N_TASKS个任务*/
            TaskData[i] = '0' + i;                             /* 每个任务显示其数据*/
            OSTaskCreate(Task, (void *)&TaskData[i], &TaskStk[i][TASK_STK_SIZE - 1], i + 1);
        }
    }

    void  Task (void *pdata)
    {
        INT8U  x;
        INT8U  y;
        INT8U  err;
        for (;;) {
            OSSemPend(RandomSem, 0, &err);           /* 获取信号量*/
            x = random(80);                          /* 计算X坐标*/
            y = random(16);                          /* 计算Y坐标*/
            OSSemPost(RandomSem);                    /* 释放信号量*/
            /* Display the task number on the screen              */
            PC_DispChar(x, y + 5, *(char *)pdata, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
            OSTimeDly(1);                            /* 挂起秒,让给其他任务运行*/
        }
    }

    2)使用消息邮箱


    #define          TASK_STK_SIZE     512               
    #define          TASK_START_ID       0                /* 任务ID*/
    #define          TASK_CLK_ID         1
    #define          TASK_1_ID           2
    #define          TASK_2_ID           3
    #define          TASK_3_ID           4
    #define          TASK_4_ID           5
    #define          TASK_5_ID           6

    #define          TASK_START_PRIO    10                /* 任务优先级*/
    #define          TASK_CLK_PRIO      11
    #define          TASK_1_PRIO        12
    #define          TASK_2_PRIO        13
    #define          TASK_3_PRIO        14
    #define          TASK_4_PRIO        15
    #define          TASK_5_PRIO        16
    OS_STK        TaskStartStk[TASK_STK_SIZE];            
    OS_STK        TaskClkStk[TASK_STK_SIZE];             
    OS_STK        Task1Stk[TASK_STK_SIZE];                
    OS_STK        Task2Stk[TASK_STK_SIZE];                
    OS_STK        Task3Stk[TASK_STK_SIZE];               
    OS_STK        Task4Stk[TASK_STK_SIZE];              
    OS_STK        Task5Stk[TASK_STK_SIZE];               
    OS_EVENT     *AckMbox;                                /* 任务和使用的消息邮箱*/
    OS_EVENT     *TxMbox;

    void main (void)
    {
        OS_STK *ptos;
        OS_STK *pbos;
        INT32U  size;
        PC_DispClrScr(DISP_FGND_WHITE);                       
        OSInit();                                            
        PC_DOSSaveReturn();                                  
        PC_VectSet(uCOS, OSCtxSw);                            
        PC_ElapsedInit();                                     
        ptos        = &TaskStartStk[TASK_STK_SIZE - 1];        
        pbos        = &TaskStartStk[0];
        size        = TASK_STK_SIZE;
        OSTaskStkInit_FPE_x86(&ptos, &pbos, &size);            
        OSTaskCreateExt(TaskStart,
            (void *)0,
            ptos,
            TASK_START_PRIO,
            TASK_START_ID,
            pbos,
            size,
            (void *)0,
            OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
        OSStart();                                             
    }
    void  TaskStart (void *pdata)
    {
    #if OS_CRITICAL_METHOD == 3                               
        OS_CPU_SR  cpu_sr;
    #endif
        INT16S     key;
        pdata = pdata;                                       
        TaskStartDispInit();                                
        OS_ENTER_CRITICAL();                                
        PC_VectSet(0x08, OSTickISR);
        PC_SetTickRate(OS_TICKS_PER_SEC);                    
        OS_EXIT_CRITICAL();
        OSStatInit();                                          
        AckMbox = OSMboxCreate((void *)0);                     /* 创建两个消息邮箱*/
        TxMbox  = OSMboxCreate((void *)0);
        TaskStartCreateTasks();                               
        for (;;) {
            TaskStartDisp();                                 

            if (PC_GetKey(&key)) {                           
                if (key == 0x1B) {                            
                    PC_DOSReturn();                           
                }
            }
            OSCtxSwCtr = 0;                                    
            OSTimeDly(OS_TICKS_PER_SEC);                      
        }
    }
    void  Task1 (void *pdata)
    {
        INT8U       err;
        OS_STK_DATA data;                       /* 任务堆栈数据*/
        INT16U      time;                      
        INT8U       i;
        char        s[80];
        pdata = pdata;
        for (;;) {
            for (i = 0; i < 7; i++) {
                PC_ElapsedStart();
                err  = OSTaskStkChk(TASK_START_PRIO + i, &data);//执行堆栈检查
                time = PC_ElapsedStop();
                if (err == OS_NO_ERR) {
                    sprintf(s, "%4ld        %4ld        %4ld        %6d",
                        data.OSFree + data.OSUsed,
                        data.OSFree,
                        data.OSUsed,
                        time);
                    PC_DispStr(19, 12 + i, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
                }
            }
            OSTimeDlyHMSM(0, 0, 0, 100);                       /* 挂起mS*/
        }
    }
    void  Task4 (void *data)
    {
        char   txmsg;
        INT8U  err;
        data  = data;
        txmsg = 'A';
        for (;;) {
            OSMboxPost(TxMbox, (void *)&txmsg);      /* 发消息给Task #5*/
            OSMboxPend(AckMbox, 0, &err);            /* 等待Task #5的应答消息*/
            txmsg++;                                 /*下一个要发的消息数据*/
            if (txmsg == 'Z') {
                txmsg = 'A';                         /* 循环发送A-Z*/
            }
        }
    }
    void  Task5 (void *data)
    {
        char  *rxmsg;
        INT8U  err;
        data = data;
        for (;;) {
            rxmsg = (char *)OSMboxPend(TxMbox, 0, &err); /* 等待来自Task #4的数据*/
            PC_DispChar(70, 18, *rxmsg, DISP_FGND_YELLOW + DISP_BGND_BLUE);
            OSTimeDlyHMSM(0, 0, 1, 0); /* 挂起秒,让给其他任务运行*/
            OSMboxPost(AckMbox, (void *)1); /*发送接收到数据的应答消息*/
        }
    }

    运行结果:

    3)使用消息队列

    #define          TASK_STK_SIZE     512               
    #define          TASK_START_ID       0               
    #define          TASK_CLK_ID         1
    #define          TASK_1_ID           2
    #define          TASK_2_ID           3
    #define          TASK_3_ID           4
    #define          TASK_4_ID           5
    #define          TASK_5_ID           6
    #define          TASK_START_PRIO    10               
    #define          TASK_CLK_PRIO      11
    #define          TASK_1_PRIO        12
    #define          TASK_2_PRIO        13
    #define          TASK_3_PRIO        14
    #define          TASK_4_PRIO        15
    #define          TASK_5_PRIO        16
    #define          MSG_QUEUE_SIZE     20                /* 消息队列大小*/
    typedef struct {
        char    TaskName[30];
        INT16U  TaskCtr;
        INT16U  TaskExecTime;
        INT32U  TaskTotExecTime;
    } TASK_USER_DATA;
    OS_STK          TaskStartStk[TASK_STK_SIZE];         
    OS_STK          TaskClkStk[TASK_STK_SIZE];            
    OS_STK          Task1Stk[TASK_STK_SIZE];              
    OS_STK          Task2Stk[TASK_STK_SIZE];            
    OS_STK          Task3Stk[TASK_STK_SIZE];             
    OS_STK          Task4Stk[TASK_STK_SIZE];            
    OS_STK          Task5Stk[TASK_STK_SIZE];             
    TASK_USER_DATA  TaskUserData[7];
    OS_EVENT       *MsgQueue;                             /*消息队列指针*/
    void           *MsgQueueTbl[20];                      /*消息存储*/
    void  main (void)
    {
        PC_DispClrScr(DISP_BGND_BLACK);                        
        OSInit();                                            
        PC_DOSSaveReturn();                                    
        PC_VectSet(uCOS, OSCtxSw);                            
        PC_ElapsedInit();                                      
        strcpy(TaskUserData[TASK_START_ID].TaskName, "StartTask");
        OSTaskCreateExt(TaskStart,
            (void *)0,
            &TaskStartStk[TASK_STK_SIZE - 1],
            TASK_START_PRIO,
            TASK_START_ID,
            &TaskStartStk[0],
            TASK_STK_SIZE,
            &TaskUserData[TASK_START_ID],
            0);
        OSStart();                                          
    }
    void  TaskStart (void *pdata)
    {
    #if OS_CRITICAL_METHOD == 3                                
        OS_CPU_SR  cpu_sr;
    #endif
        INT16S     key;
        pdata = pdata;                                      
        TaskStartDispInit();                                
        OS_ENTER_CRITICAL();                                  
        PC_VectSet(0x08, OSTickISR);
        PC_SetTickRate(OS_TICKS_PER_SEC);                    
        OS_EXIT_CRITICAL();
        OSStatInit();                                         
        MsgQueue = OSQCreate(&MsgQueueTbl[0], MSG_QUEUE_SIZE); /*创建消息队列,大小为*/
        TaskStartCreateTasks();
        for (;;) {
            TaskStartDisp();                               
            if (PC_GetKey(&key)) {                           
                if (key == 0x1B) {                         
                    PC_DOSReturn();                         
                }
            }
            OSCtxSwCtr = 0;                                   
            OSTimeDly(OS_TICKS_PER_SEC);                      
        }
    }
    void  Task1 (void *pdata)
    {
        char  *msg;
        INT8U  err;
        pdata = pdata;
        for (;;) {
            msg = (char *)OSQPend(MsgQueue, 0, &err);//从消息队列中取消息
            PC_DispStr(70, 13, msg, DISP_FGND_YELLOW + DISP_BGND_BLUE);
            OSTimeDlyHMSM(0, 0, 0, 100);
        }
    }
    void  Task2 (void *pdata)
    {
        char  msg[20];
        pdata = pdata;
        strcpy(&msg[0], "Task 2");
        for (;;) {
            OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中
            OSTimeDlyHMSM(0, 0, 0, 500);
        }
    }
    void  Task3 (void *pdata)
    {
        char  msg[20];
        pdata = pdata;
        strcpy(&msg[0], "Task 3");
        for (;;) {
            OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中
            OSTimeDlyHMSM(0, 0, 0, 500);
        }
    }
    void  Task4 (void *pdata)
    {
        char  msg[20];
        pdata = pdata;
        strcpy(&msg[0], "Task 4");
        for (;;) {
            OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中
            OSTimeDlyHMSM(0, 0, 0, 500);
        }
    }
    void  OSTaskStatHook (void)
    {
        char    s[80];
        INT8U   i;
        INT32U  total;
        INT8U   pct;
        total = 0L;                                          /* Totalize TOT. EXEC. TIME for each task 
        for (i = 0; i < 7; i++) {
            total += TaskUserData[i].TaskTotExecTime;
            DispTaskStat(i);                                 /* Display task data                      
        }
        if (total > 0) {
            for (i = 0; i < 7; i++) {                        /* Derive percentage of each task         */
                pct = 100 * TaskUserData[i].TaskTotExecTime / total;
                sprintf(s, "%3d %%", pct);
                PC_DispStr(62, i + 11, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
            }
        }
        if (total > 1000000000L) {                           /* Reset total time counters at 1 billion 
            for (i = 0; i < 7; i++) {
                TaskUserData[i].TaskTotExecTime = 0L;
            }
        }
    }

    void  OSTaskSwHook (void)
    {
        INT16U           time;
        TASK_USER_DATA  *puser;
        time  = PC_ElapsedStop();                    /* This task is done                                  
        PC_ElapsedStart();                           /* Start for next task                                
        puser = OSTCBCur->OSTCBExtPtr;               /* Point to used data                                 
        if (puser != (TASK_USER_DATA *)0) {
            puser->TaskCtr++;                        /* Increment task counter                             
            puser->TaskExecTime     = time;          /* Update the task's execution time                   
            puser->TaskTotExecTime += time;          /* Update the task's total execution time             
        }
    }

    运行结果:

    作者:洞庭散人

    出处:http://phinecos.cnblogs.com/    

    本博客遵从Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。
  • 相关阅读:
    php 处理并发问题
    phpstudy 版本切换注意的问题
    php读取文件内容的三种方法
    防止重复提交表单的两种方法
    php 压缩函数gzencode gzdeflate gzcompress
    回调函数解析
    回调函数
    如何卸载红蜘蛛
    无法启动此程序,因为计算机中丢失MSVCR110.dll的解决方法
    mysql 去除重复 Select中DISTINCT关键字的用法
  • 原文地址:https://www.cnblogs.com/xumaojun/p/8541665.html
Copyright © 2011-2022 走看看