• 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

  • 相关阅读:
    INI配置文件的格式
    UserControl图片显示报错问题
    CornerRadius圆角属性
    Stretch属性
    [WPF]The type name ‘App’ does not exist in the type '...'的问题
    [Word]解决Word中执行输入操作时后面字符自动被删除的问题
    MATLAB中的取整函数(fix、round、floor、ceil)
    [数据库][C#]几个常用的正则表达式
    [数据库][C#]提取字符串中的数字
    springmvc注解知识点汇总
  • 原文地址:https://www.cnblogs.com/kalo1111/p/3314848.html
Copyright © 2020-2023  润新知