uCosII 从 OSStart开始到思维定势··········

我们先看我们的任务代码 TEST.C

 1 /******************************Test*******************************/
 2 #include "includes.h"
 3 #define  TASK_STK_SIZE   512            //任务堆栈长度
 4 
 5 OS_STK   MyTaskStk[TASK_STK_SIZE];        //定义任务堆栈区
 6 OS_STK   YouTaskStk[TASK_STK_SIZE];        //定义任务堆栈区
 7 INT16S   key;                    //用于退出uCOS_II的键
 8 INT8U     x=0,y=0;                //字符显示位置
 9 void  MyTask(void *data);            //声明任务
10 void  YouTask(void *data);
11 char* s_M="M";                        
12 /************************主函数*********************************/
13 void  main (void)
14 {
15                         //定义要显示的字符
16     OSInit( );                    //初始化uCOS_II
17     PC_DOSSaveReturn( );            //保存Dos环境
18     PC_VectSet(uCOS, OSCtxSw);            //安装uCOS_II中断
19     OSTaskCreate(
20         MyTask,                //创建任务MyTask
21         s_M,                //给任务传递参数
22         &MyTaskStk[TASK_STK_SIZE - 1],    //设置任务堆栈栈顶指针
23         4                //任务的优先级别为0
24         );                
25     OSStart( );                    //启动多任务管理
26 }
27 
28 /*******************任务MyTask**********************************/
29 
30 void  MyTask (void *pdata)
31 {
32 
33 
34     char* s_Y="Y";                //定义要显示的字符
35 #if OS_CRITICAL_METHOD == 3
36     OS_CPU_SR  cpu_sr;
37 #endif
38     pdata = pdata; 
39     OS_ENTER_CRITICAL( );
40     PC_VectSet(0x08, OSTickISR);        //安装时钟中断向量
41     PC_SetTickRate(OS_TICKS_PER_SEC);        //设置时钟频率
42     OS_EXIT_CRITICAL( );
43     OSStatInit( );                //初始化统计任务
44     OSTaskCreate(
45         YouTask,            //创建任务MyTask
46         s_Y,                //给任务传递参数
47         &YouTaskStk[TASK_STK_SIZE - 1],    //设置任务堆栈栈顶指针
48         5                // MyTask的优先级别为2
49         );                
50     for (;;) 
51     {
52         if (x>50) 
53         {
54            x=0;
55            y+=2; 
56             }                                                 
57         PC_DispChar(x, y,            //字符的显示位置
58         *(char*)pdata, 
59         DISP_BGND_BLACK+DISP_FGND_WHITE );
60                x += 1;   
61         //如果按下Esc键则退出uCOS_II
62         if (PC_GetKey(&key) == TRUE) 
63         {
64             if (key == 0x1B) 
65             {
66                 debug31();
67                 PC_DOSReturn( );        //恢复Dos环境
68             }
69         }
70         OSTimeDlyHMSM(0, 0, 3, 0);        //等待3秒
71 }
72 }
73 
74 /************************任务YouTask******************************/
75 
76 void  YouTask (void *pdata)
77 {
78 #if OS_CRITICAL_METHOD == 3
79     OS_CPU_SR  cpu_sr;
80 #endif
81     pdata = pdata; 
82     for (;;) 
83     { 
84         if (x>50) 
85         {
86            x=0;
87            y+=2; 
88         }                                                 
89         PC_DispChar(
90             x, y,            //字符的显示位置
91             *(char*)pdata, 
92             DISP_BGND_BLACK+DISP_FGND_WHITE 
93             );
94                x += 1;    
95         OSTimeDlyHMSM(0, 0, 1, 0);        //等待1秒
96     }
97 }
98 
99 /************************End************************************/
TEST.C

OK,让我们从 MAIN 函数里面,的 OSStart();开始吧······

 1 void  OSStart (void)
 2 {
 3     INT8U y;
 4     INT8U x;
 5 
 6 
 7     if (OSRunning == FALSE) {
 8         y             = OSUnMapTbl[OSRdyGrp];        /* Find highest priority's task priority number   */
 9         x             = OSUnMapTbl[OSRdyTbl[y]];
10         OSPrioHighRdy = (INT8U)((y << 3) + x);
11         OSPrioCur     = OSPrioHighRdy;
12         OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
13         OSTCBCur      = OSTCBHighRdy;
14         OSStartHighRdy();                            /* Execute target specific code to start task     */
15     }
16 }
OSStart

第零拍(0 Tick)
  1 分析MyTask代码发现初始化Stat Task,<OSStatInit()>  中OSTimeDly(2),第一次切换Mytask->OS_TaskStat(统计任务)

  2 OS_TaskStat也不省心,他发现还不知道IDLEtask到底全速运行一秒中能记多少数,OSTimeDly(2ticks),第二次切换OS_TaskStat->OS_TaskIdle(空闲任务)

 1 #if OS_TASK_STAT_EN > 0
 2 void  OSStatInit (void)
 3 {
 4 #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
 5     OS_CPU_SR  cpu_sr;
 6 #endif    
 7     
 8     
 9     OSTimeDly(2);                                /* Synchronize with clock tick                        */
10     OS_ENTER_CRITICAL();
11     OSIdleCtr    = 0L;                           /* Clear idle counter                                 */
12     OS_EXIT_CRITICAL();
13     OSTimeDly(OS_TICKS_PER_SEC);                 /* Determine MAX. idle counter value for 1 second     */
14     OS_ENTER_CRITICAL();
15     OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1 second       */
16     OSStatRdy    = TRUE;
17     OS_EXIT_CRITICAL();
18 }
19 #endif
OSStatInit

note

OK,利己利人····贴上OSTimeDly的代码

 1 void  OSTimeDly (INT16U ticks)
 2 {
 3 #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
 4     OS_CPU_SR  cpu_sr;
 5 #endif    
 6 
 7 
 8     if (ticks > 0) {                                                      /* 0 means no delay!         */
 9         OS_ENTER_CRITICAL();
10         if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {  /* Delay current task  取消就绪态      */
11             OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
12         }
13         OSTCBCur->OSTCBDly = ticks;                                       /* Load ticks in TCB         */
14         OS_EXIT_CRITICAL();
15         OS_Sched();                                                       /* Find  next task to run!    */
16     }
17 }
OSTimeDly

第二拍(2 Tick)
  3 Idle Task会执行到第二个Tick,此时MyTask醒来,故OS_TaskIdle->MyTask:虽然ostimedly(2)以后,有好多行的初始化OS_TaskIdle的代码,但是我们      呀相信,计算机一个tick能完成很多事情,所以忽略不计,大概认为,OS_TaskIdle运行了2 ticks ;
  4 很不幸,OSStatInit()又要求延时一秒去计算IDLE全速运行的计数值,即  OSTimeDly(OS_TICKS_PER_SEC); 这句话。MyTask->OS_TaskIdle,接下来的一秒中,        只有IDLE task在运行,而且傻傻地干一件事情,去加它视为宝贝的OSIdleCtr(以上还得详见 OSStatInit)

第202 Tick (OSTimeDly(2)+OSTimeDly(OS_TICKS_PER_SEC))
  5 MyTask醒来,OS_TaskIdle->MyTask
  6 干完自己事,创建了Youtask,显示了一个M,OSTimeDly(3秒),MyTask->YouTask
  7 Youtask显示了一个Y,OSTimeDly(1秒),YouTask->OS_TaskIdle

  OK,说了这么半天OS_TaskStat 

 1 #if OS_TASK_STAT_EN > 0
 2 void  OS_TaskStat (void *pdata)
 3 {
 4 #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
 5     OS_CPU_SR  cpu_sr;
 6 #endif    
 7     INT32U     run;
 8     INT32U     max;
 9     INT8S      usage;
10 
11 
12     pdata = pdata;                               /* Prevent compiler warning for not using 'pdata'     */
13     while (OSStatRdy == FALSE) {
14         OSTimeDly(2 * OS_TICKS_PER_SEC);         /* Wait until statistic task is ready      也就说等到2秒哦亲···           */
15     }
16     max = OSIdleCtrMax / 100L;
17     for (;;) {
18         OS_ENTER_CRITICAL();
19         OSIdleCtrRun = OSIdleCtr;                /* Obtain the of the idle counter for the past second */
20         run          = OSIdleCtr;
21         OSIdleCtr    = 0L;                       /* Reset the idle counter for the next second         */
22         OS_EXIT_CRITICAL();
23         if (max > 0L) {
24             usage = (INT8S)(100L - run / max);
25             if (usage >= 0) {                    /* Make sure we don't have a negative percentage      */
26                 OSCPUUsage = usage;
27             } else {
28                 OSCPUUsage = 0;
29             }
30         } else {
31             OSCPUUsage = 0;
32             max        = OSIdleCtrMax / 100L;
33         }
34         OSTaskStatHook();                        /* Invoke user definable hook                         */
35         OSTimeDly(OS_TICKS_PER_SEC);             /* Accumulate OSIdleCtr for the next second           */
36     }
37 }
38 #endif
OS_TaskStat

第400 Tick
  8 在0tick睡去的OS_TaskStat终于醒来了(初始化会后会等待,SStatRdy 为 true 哦),OS_TaskIdle->OS_TaskStat
  9 OS_TaskStat做完统计后,OSTimeDly(1秒),OS_TaskStat->OS_TaskIdle

第402 Tick
  10 在202tick睡去的YouTask醒来,OS_TaskIdle->YouTask
  11 显示了一个Y,OSTimeDly(1秒),YouTask->OS_TaskIdle

  402 ticks 已经很接近500 ticks了,后面的先不管了,至少分析出了第一个500tick。
  我是用仿造直尺刻度的方法,在白纸上画了三遍时间轴分析出的这个结果。

,具体的继续分析,见任哲的  3-1 现象分析 txt·····然后,结论里面,有几个特别重要的·····

NOTE:1  从上面的两处时间轴,和11次与10的讨论,不难发现,Stat执行时,不会有其他任务执行的,除非MyTask或Youtask故意延时比如198Ticks,但是用户一般会用正秒数的延时也许这正是OSStatInit中OSTimeDly(2)的好处,避免和其他任务冲撞而影响stat任务的执行。其实上面画的时间轴是系统时间轴和用户时间轴的重合,用户时间轴的刻度上总有个尾数2。  OS_TaskStat 不会和其他任务重合的

    2.

(任务切换时OSPrioHighRdy会大于OSPrioCur,我曾经有思维定势,OSPrioHighRdy肯定是最小的)!!!!!!!

  任务切换时OSPrioHighRdy是不是总是小于OSPrioCur要分情况考虑中断级任务调度时,肯定是优先级高任务的取代当先被中断的任务。即OSPrioHighRdy<OSPrioCur。但任务级调度时,一般是先执行优先级高的,高的执行完延时或挂起时让给优先级低的去执行,此时OSPrioHighRdy>OSPrioCur

原文地址:https://www.cnblogs.com/kalo1111/p/3314848.html