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 );                             /*  挂起秒,让给其他任务运行 */
    }
}
2007112201.jpg

 

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 );  /* 发送接收到数据的应答消息 */
    }
}

 

运行结果:

2007112202.jpg

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             
    }
}

 

运行结果:

2007112204.jpg

你可能感兴趣的:(源码分析)