广东南海海域水深:uCOS/ii 学习心得及体会

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 00:20:03

信号量多用于任务间同步,和互斥. 
邮箱用于大数据的传送. 
队列多用于处理有序的事件.
 

信号量就是中央政府发给官人做一方大员的官印,有很多种官印但是不能一印多发,得到官印者才能掌权鱼肉一方百姓(任务得到信号量才能运行),否则你就只要等官跑官。 
邮箱,就好给比当差的下达的抄家、拆房、收监等红头文件,拿到啥样的文件就干啥。 
消息队列,就是给任务发了一连串的邮件,官员(任务)拿到这一大摞文件,可以从底部或者顶部(LIFO or FIFO)一个一个拆开处理。 

 1、任哲的《嵌入式实时操作系统uCOS-II原理及应用》 
      这本书非常适合初学者学习 uCOS-ii   
  
 2、   请问:空闲任务和统计任务是否建立任务控制块呢?
            任务块链表中是否存在空闲任务和统计任务的任务控制块呢?如果没有的话,操作系统如何调度呢?
        标准答案:
            在uCOS/ii内核中,调用OSInit()函数中会首先创建空闲任务,同时当用户“允许”统计任务时,也会接着创建统计任务。
            因此任务块链表中存在空闲任务和统计任务的任务控制块。 

 3、   请问:为什么有了正在使用任务控制块链表OSTCBList和空闲任务控制块链表OSTCBFreeList,还要再定义OSTCBPrioTbl[]呢?
       标准答案:
             数组OSTCBPrioTbl[]是以任务号为索引,里面保存的任务0到最大任务的任务控制块(TCB)的首地址,据此可以通过任务优先级号(任务号)快速找到当前任务在任务控制块中的首指针,而不必到任务控制块链表中一步一步的查找,加快访问时间。加快任务切换时间。
    

 4、   uCOS/II中,能够引起任务调度的系统函数有哪些?

         (1)、OSStart() uCOS/II启动
         (2)、OSTaskSuspend()挂起任务
         (3)、OSTaskResume()恢复任务
          OSTimeDly()/OSTimeDlyHMSM()、等待一个事件的发生(包括OSSemPend(), OSMutexPend, OSFlagPend, OSMboxPend(), OSQPend(),

 5、   请问:既然有了任务就绪表INT8U OSRdyTbl[64],为什么还要再定义
           INT8U  OSRdyGrp[8]呢?这样做的好处是什么?
       标准答案:
          OSRdyTbl[64]是任务就绪表,当表中 元素的值=1时,表示 任务处于就绪状态。 例如: OSRdyTbl[0]= 1,则表示:任务级别号=0的任务处于就绪状态,可以被调度器立即置于“运行态”。
        为了节省查找时间(如果让操作系统每次查找处于就绪状态的最高优先级别的任务时,都从下标0开始查找,有点太浪费时间了),因此又专门定义了一个数组OSRdyGrp[8]。

     其中:
         (1)、OSRdyGrp[0]对应OSRdyTb[0]~OSRdyTbl[7]
         (2)、OSRdyGrp[1]对应OSRdyTb[8]~OSRdyTbl[15]
         (3)、OSRdyGrp[2]对应OSRdyTb[16]~OSRdyTbl[23]
       这样,每次查找就绪表中最高优先级别的任务,就可以这样查找,首先查找依次从OSRdyGrp[0]~OSRdyGrp[7]开始查找不等于0的项,假如OSRdyGrp[1] >=1,则表示任务号8到任务号15有级别最高的就绪任务。
      最终查找范围从0-64缩小到8-15。最终节省了查找时间。

  6、 请问:任务调度的核心是什么?
      标准答案:
              在多任务操作系统中,命令CPU中止当前正在运行的任务转而去运行另外一个任务的工作叫做任务切换。
       任务调度主要完成两个工作:
      (1)、在任务就绪表中查找具有最高优先级别的就绪任务。
      (2)、实现任务切换
        说的更明白一些,就是将找到的的最高优先级别的任务的“任务号”---> “当前任务的任务号OSPrioCur”;从OSTCBPrioTbl[]取出最高优先级别任务的任务控制块首地址---> “当前任务的任务控制块指针OSTCBCur”
       最后调用OS_TASK_SW()完成现场切换(即将CPU的寄存器信息保存到当前正运行任务的私栈中,然后从待运行的高优先级别的任务私栈中弹出原先保存寄存器信息到CPU)。

//-----------------------------------
     OSPrioCur 是全局变量,用于保存当前正在运行任务的任务号
     OSTCBCur是全局变量,用于指向当前正在运行任务的任务控制块首地址。 

 7、任务切换的关键:其实是堆栈的切换。
        切换时:
            (1)、第一步:将当前CPU的SP寄存器的值保存到“待中止任务”的任务控制块中。即保存到结构体OS_TCB的OSTCBStkPtr成员中。  
            (2)、第二步:从“待运行任务”的任务控制块的OSTCBStkPtr成员中取出待运行任务的堆栈指针,然后送给CPU的SP寄存器。 

  8、(OSTCB *)1 是什么意思


 (原文件名:OSTCB_1是什么意思.JPG) 
引用图片


 9、 启动任务函数OSStart()之前必须遵守的约定:

        uCOS/II运行之前,必须调用系统函数OSStart()。▲▲▲此时切记:
        调用系统函数OSStart()之前,“必须”已经创建了一个任务,并赋予它最高优先级别,从而使它成为起始任务;然后在这个起始任务中,再创建其它“低优先级别”的任务。


10、 什么时候开启全局中断?

        (1)、由于启动任务函数OSStart()之前必须遵守的约定:
        在调用系统函数OSStart()之前,先创建一个任务,并赋予它最高优先级别,从而使它成为起始任务;然后在这个起始任务中,再创建其它任务。
        (2)、因此执行系统函数OSStart()后,uCOS/II会自动调度用户创建的最高优先级别的任务,所有在这个“最高优先级别的任务”中开启全局中断最合适。
         例如:下面的例子为:在系统函数OSStart()之前,创建了一个“最高优先级别的任务”TaskStart()--->
         OSTaskCreate(TaskStart,......)
         因此在TaskStart()任务首次被调度时,开启全局中断。

        注意:千万不要在系统函数OSStart()之前开启全局中断,否则操作系统会崩溃。因为此时uCOS/II内部环境还没有完全初始化完成。


 (原文件名:什么时候开启全局中断.JPG) 
引用图片




 


 (原文件名:OS_EXIT_CRITICAL()就是开启全局中断.JPG) 
引用图片





11、 执行系统函数OSStart()的时候,为什么还要增加如下的条件:

          if (OSRunning == FALSE)
          {
                          ,,,,,,,,,,,,,,,,
          }
   
          此时应该没有任务被调度呀(即:OSRunning 应该等于 FALSE)!
          只有当执行了系统函数OSStartHighRdy()的时候,即调度最高优先级别任务的时候,才置   OSRunning = TRUE。   
       难道我的理解错了吗?
       为什么呀!


 (原文件名:执行OSStart()的时候,为什么需要判断 if (OSRunning == FALSE) 呢?.JPG) 
引用图片

对于问题11:我觉得它这样检查是因为防止你在任务启动前已经开启了全局中断!
还有对于这个问题,我补充一点,并非在多任务启动之前开启了全局中断OS就一定会崩溃!而是可能!这个我做过实验!



12、uCOS/II中所说的中断服务程序调度,是否仅仅是指时钟节拍中断服务程序呢?
        例如:是否仅仅时钟节拍中断服务程序中才能调用OSIntExit(),串口中断服务中不允许调用OSIntExit()进行任务调度呢?

       一般用户程序,例如:串口中断服务程序是否
                (1)、不能调用系统函数 : OSIntExit()进行任务调度
                (2)、可以调用系统函数 : OSIntExit()进行任务调度,也可以不调用系统函数 : OSIntExit()进行任务调度。

问题12:其他中断中也可以放入  OSIntExit()进行任务调度 ,因为你的中断可能使优先级更高的任务进入就绪状态!比如发送一个信号量、消息邮箱、消息队列之类的!所以退出中断需要调用任务调度函数