uCOS-II的任务介绍2:

 

用户任务代码的一般结构:

 

   根据嵌入式系统任务的工作特点,任务的执行代码通常是一个无限循环结构,并且在这个循环中可以响应中断,这种结构也叫做超循环结构。

 

一个用C语言编写的任务(超循环结构的任务示意性代码):

void MyTask( void *pdata )

{

       for(;;)

       {

              可以被中断的用户代码;

              OS_ENTER_CRITICAL();    //进入临界段(关中断)

             不可以被中断的用户代码;

              OS_EXIT_CRITICAL();       //退出临界段(开中断)

              可以被中断的用户代码;

       }

}

 

     从程序设计的角度来看,一个uCOS-II任务的代码就是一个C语言函数.为了可以传递各种不同类型的数据甚至是函数,任务的参数是一个void类型的指针.

 

     为了有效地对中断进行控制,在任务的代码里可使用uCOS-II定义的宏OS_ENTER_CRITICAL()OS_EXIT_CRITICAL()来控制任务何时响应中断,何时屏蔽中断。在运行这两个宏之间的代码时是不会响应中断的,这种受保护的代码段叫做临界段。在具体应用中可以,根据实际需要在一个任务中使用这对宏设置多个临界段。

     因此可以说,uCOS-II任务的代码结构是一个带有临界段的无限循环。

 

用户应用程序的一般结构:

    从程序代码上来看,用户任务似乎就是一个C语言函数,但是这个函数不是一般的C语言函数,它是一个任务(线程)。因此,它不是被主函数或其他函数调用的,主函数main()只负责创建和启动它们,而由操作系统负责来调度运行它们。从代码上来看,用户应用程序的代码大体上如下面所示。

用户应用程序的结构。

   

  void MyTask1( void *pdata )     // 定义用户任务1

  {

       for(;;)

       {

              ......

       }

  }

 

 

  void MyTask2( void *pdata )     // 定义用户任务2

  {

       for(;;)

       {

              ......

       }

  }

 

 

  void MyTask3( void *pdata )     // 定义用户任务3

  {

       for(;;)

       {

              ......

       }

  } 

 

  void main()

  {

       ......

      OSInit();               //初始化uCOS-II

       ......

       OSTaskCreate(MyTask1,......);     //创建用户1

       OSTaskCreate(MyTask2,......);     //创建用户2

       OSTaskCreate(MyTask3,......);     //创建用户3

       ......

       OSStart();                    //启动任务

       ......

  }

 

 

 

系统任务:
     uCOS-II预定义了两个为应用程序服务的系统任务:空闲任务和统计任务。其中空闲任务是每个应用程序必须使用的,而统计任务则

是应用程序可以根据实际需要来选择使用的。

 

空闲任务:
      在多任务系统运行时,系统经常会在某个时间内无用户任务可运行而处于所谓的空闲状态。为了使CPU在没有用户任务可执行

时有事可做,uCOS-II提供了一个叫做空闲任务OSTaskIdle()的系统任务。空闲任务的代码如下:
   
    void OSTaskIdle( void *pdata)
    {
          #if OS_CRITICAL_METHOD == 3
            OS_CPU_SR cpu_sr;
         #endif
 
          pdata = pdata;  //防止某些编译器报错

          for(;;)
         {
            OS_ENTER_CRITICAL();  //关闭中断
            OSIdleCtr++;   //计数
            OS_EXIT_CRITICAL();  //开放中断
          }
    } 

 

 

这里有一行代码为 pdata = pdata,之所以安排了这样一行代码,是因为在这个任务中没有用到参数pdata。对于某些C编译器,在对代

码进行编译时会对这种情况报错(说定义了参数却没有使用),有了这行代码,编译器就不会报错了。
从上面的代码中可以看到,这个空闲任务几乎不做什么事情,只是对系统定义的一个空闲任务运行次数计数器OSIdleCtr进行加1操作。

当然,如果用户认为有必要,那么也可在空闲任务中编写一些做用户工作的代码。
   uCOS-II规定,一个用户应用程序必须使用这个空闲任务,而且这个任务是不能用软件来删除的。
 

 

统计任务:
      uCOS-II提供的另一个系统任务是统计任务OSTaskStat()。这个统计任务每秒计算一次CPU在单位时间内被使用的时间,并把计算结

果以百分比的形式存放在变量OSCPUUsage中,以便应用程序通过访问它来了解CPU的利用率,所以该系统任务OSTaskStat()叫做统计任

务。

     用户应用程序是否使用统计任务,用户可以根据应用程序的实际需要来进行选择。如果用户应用程序要使用这个统计任务,则必须把

定义在系统头文件OS_CFG.H中的系统配置常数OS_TASK_STAT_EN设置为1,并且必须在创建统计任务之前调用函数OSStatInit()对统计

任务进行初始化。

 

 
任务的优先权及优先级别
      前面已提及uCOS-II的每个任务都必须具有一个惟一的优先级别。uCOS-II把任务的优先权分为64个优先级别,每一个级别都用一个

数字来表示。数字0表示任务的优先级别最高;数字越大则表示任务的优先级别越低。
     通常一个应用程序的任务数小于64。为了节省内存,用户可以根据应用程序的需要,在文件OS_CFG.H中通过给表示最低优先级别的

常数OS_LOWEST_PRIO赋值的方法,来说明程序中任务优先级别的数目。该常数一旦被定义,就意味着系统中可供使用的优先级别为

0,1,2,...,OS_LOWEST_PRIO,共OS_LOWEST_PRIO+1个。同时也限制了应用程序中任务的总数最多不能超OS_LOWEST_PRIO+1个。固定地,系统总是把最低优先级别OS_LOWEST_PRIO自动赋给空闲任务。如果应用程序中还使用了统计任务,则系统会把优先级别

OS_LOWEST_PRIO-1自动赋给统计任务,因此用户任务可以使用的优先级别是0,1,2,...,OS_LOWEST_PRIO-2,

共OS_LOWEST_PRIO-1个。

 

 

 


例:如果希望应用程序中任务的优先级别为28个,则表示最低优先级别的常数OS_LOWEST_PRIO值应该是多少?如果应用程序中使用了系

统提供的空闲任务和统计任务,则该应用程序最多可以安排多少个任务?
 答:表示最低优先级别的常数OS_LOWEST_PRIO值应该为27,优先级别分别为0,1,2,3,...,27;由于系统空闲任务占用了优先级别27,统

计任务占用了优先级别26,则应用程序中最多可以安排优先级别分别为0,1,2,...,25的26个任务。
   给某一个用户任务的定义优先级别,需要在调用系统函数OSTaskCreate()来创建任务时,用该函数的第4个参数prio来指定。
  由于每个任务都具有惟一的优先级别,因此uCOS-II通常也用任务的优先级别来作为这个任务的标识。

你可能感兴趣的:(工作,OS,嵌入式,语言,任务,编译器)