关于μCOS的7个问题

转载 2013年12月02日 11:04:31

1、   μC/OS-Ⅱ是怎样处理临界段代码的?

    μC/OS-Ⅱ为了处理临界段代码,避免同时有其它任务或中断服务进入临界段代码,因此需要关中断,处理完毕后再开中断。μC/OS-Ⅱ在文件 OS_CPU.H 中定义两个宏(macros)来关中断和开中断,以便避开不同 C 编译器厂商选择不同的方法来处理关中断和开中断。μC/OS-Ⅱ中的这两个宏调用分别是:OS_ENTER_CRITICAL() OS_EXIT_CRITICAL()。这两个宏的定义取决于所用的微处理器。

2、   什么是任务,怎样把用户的任务交给μC/OS-Ⅱ?

    一个任务看起来像其它 C 的函数,通常是一个无限的循环。这里要强调的是任务是没有返回值的,故返回参数必须定义成 void。还有一点,任务可以自我删除 ,当任务完成以后,任务可以自我删除,代码并非真的删除了,只是简单地不再理会这个任务了,这个任务的代码也不会再运行。

3、   任务是怎样调度的?

    μC/OS-Ⅱ总是运行进入就绪态任务中优先级最高的那一个任务。 确定哪个任务优先级最高是由调度器(Scheduler)完成的,在程序代码中任务级的调度是由函数OSSched()完成的,中断级的调度是由另一个函数 OSIntExt()完成的。

void OSSched (void)

{

    INT8U y;

    OS_ENTER_CRITICAL();

    if ((OSLockNesting | OSIntNesting) == 0) {                               (1)

        y = OSUnMapTbl[OSRdyGrp];                                     (2)

        OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); (2)

        if (OSPrioHighRdy != OSPrioCur) {                                  (3)

            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];                  (4)

            OSCtxSwCtr++;                                            (5)

            OS_TASK_SW();                                            (6)

        }

    }

    OS_EXIT_CRITICAL();

}

    首先关中断,再有个判断条件:如果在中断服务子程序中调用 OSSched(),此时中断嵌套层数 OSIntNesting>0,或者由于用户至少调用了一次给任务调度上锁函数 OSSchedLock(),使OSLockNesting>0。如果不是在中断服务子程序调用 OSSched(),并且任务调度是允许的,即没有上锁,则任务调度函数将找出那个进入就绪态且优先级最高的任务[L3.8(2)],进入就绪态的任务在就绪任务表中有相应的位置位。一旦找到那个优先级最高的任务,OSSched()检验这个优先级最高的任务是不是当前正在运行的任务,以此来避免不必要的任务调度[L3.8(3)]

    注意,在μC/OS 中曾经是先得到 OSTCBHighRdy 然后和 OSTCBCur 做比较。因为这个比较是两个指针型变量的比较,在 8 位和一些 16 位微处理器中这种比较相对较慢。而在μC/OS-Ⅱ中是两个整数的比较。并且,除非用户实际需要做任务切换,在查任务控制块优先级表 OSTCBPrioTbl[]3-10时,不需要用指针变量来查 OSTCBHighRdy。综合这两项改进,即用整数比较代替指针的比较和当需要任务切换时再查表,使得μC/OS-Ⅱ比μC/OS  8 位和一些16 位微处理器上要更快一些。

为实现任务切换,OSTCBHighRdy 必须指向优先级最高的那个任务控制块 OS_TCB,这是通过将以OSPrioHighRdy为下标的OSTCBPrioTbl[]数组中的那个元素赋给OSTCBHighRdy来实现的[L3.8(4)]。接着,统计计数器 OSCtxSwCtr  1,以跟踪任务切换次数[L3.8(5)]

最后宏调用 OS_TASK_SW()来完成实际上的任务切换[L3.8(6)]。(任务切换很简单,由以下两步完成:将被挂起任务的微处理器寄存器推入堆栈,然后将较高优先级的任务的寄存器值从栈中恢复到寄存器中。在μC/OS-Ⅱ中,就绪任务的栈结构总是看起来跟刚刚发生过中断一样,所有微处理器的寄存器都保存在栈中。换句话说,μC/OS-Ⅱ运行就绪态的任务所要做的一切, 只是恢复所有的 CPU 寄存器并运行中断返回指令。为了做任务切换,运行OS_TASK_SW(),人为模仿了一次中断。多数微处理器有软中断指令或者陷阱指令 TRAP 来实现上述操作。中断服务子程序或陷阱处理(Trap hardler ,也称作事故处理(exception handler ,必须提供中断向量给汇编语言函数 OSCtxSw()OSCtxSw()除了需要OS_TCBHighRdy 指向即将被挂起的任务,还需要让当前任务控制块 OSTCBCur 指向即将被挂起的任务,参见第 8 章,移植μC/OS-Ⅱ,有关于 OSCtxSw()的更详尽的解释。)

         OSSched()的所有代码都属临界段代码。在寻找进入就绪态的优先级最高的任务过程中,为防止中断服务子程序把一个或几个任务的就绪位置位,中断是被关掉的。为缩短切换时间,OSSched()全部代码都可以用汇编语言写。为增加可读性,可移植性和将汇编语言代码最少化,OSSched()是用写的。

4、   应用程序 CPU 的利用率是多少,μC/OS-Ⅱ是怎样知道的?

                  usage = (INT8S)(100L - 100L * run / OSIdleCtrMax);通过调用统计任务 OSTaskStat()知道的。

具体过程可以参考邵贝贝那本μC/OS-Ⅱ书第三章。

5、   怎样写中断服务子程序?

用户中断服务子程序:                                                            

    1、保存全部CPU寄存器;                                      (1)                       

2、调用OSIntEnterOSIntNesting直接加1                    (2) 

    3、执行用户代码做中断服务;                                  (3)                  

    4、调用OSIntEnter                                          (4)                     

    5、恢复所有CPU寄存器;                                     (5)                      

        6、执行中断返回指令;                                        (6)

以下列出 OSIntEnter OSIntEnter中断开始和推出函数代码。

通知μC/OS-Ⅱ,中断服务子程序开始了:

void OSIntEnter (void)

{

    OS_ENTER_CRITICAL();

    OSIntNesting++;

    OS_EXIT_CRITICAL();

}

通知μC/OS-Ⅱ,脱离了中断服务:

void OSIntExit (void)

{

    OS_ENTER_CRITICAL();                                        (1)

    if ((--OSIntNesting | OSLockNesting) == 0) {                        (2)

        OSIntExitY    = OSUnMapTbl[OSRdyGrp];                        (3)

        OSPrioHighRdy = (INT8U)((OSIntExitY << 3) +

                        OSUnMapTbl[OSRdyTbl[OSIntExitY]]);

        if (OSPrioHighRdy != OSPrioCur) {

            OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];

            OSCtxSwCtr++;

            OSIntCtxSw();                                             (4)

        }

    }

    OS_EXIT_CRITICAL();

}

< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" /> 

6、   什么是时钟节拍,μC/OS-Ⅱ是怎样处理时钟节拍的?

    μC/OS 需要用户提供周期性信号源,用于实现时间延时和确认超时。而这个信号源所给其提供的时钟信号,时钟节拍源可以是专门的硬件定时器,也可以是来自 50/60Hz 交流电源的信号。

用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用 OSStart()之后。换

句话说,在调用 OSStart()之后做的第一件事是初始化定时器中断。μC/OS-Ⅱ中的时钟节拍服务是通过在中断服务子程序中调用 OSTimeTick()实现的。程序清单 L3.20 时钟节拍中断服务子程序的示意代码:

void OSTickISR(void)

{

    保存处理器寄存器的值;

    调用OSIntEnter()或是将OSIntNesting1;

    调用OSTimeTick();

 

    调用OSIntExit();

    恢复处理器寄存器的值;

    执行中断返回指令;

}

7、   μC/OS-Ⅱ是怎样初始化的,以及怎样启动多任务?

先调用系统初始化函数OSIint(),初始化μC/OS-Ⅱ所有的变量和数据结构(见 OS_CORE.C)。详细讲解请参看邵贝贝编写的μC/OS-Ⅱ书中第三章相关内容。

多任务的启动是用户通过调用 OSStart()实现的。值得注意的是:启动μC/OS-Ⅱ之前,用户至少要建立一个应用任务。以下是一个程序清单:

void main (void)

{

    OSInit();           /* 初始化uC/OS-II  */

    .

    .

    通过调用OSTaskCreate()OSTaskCreateExt()创建至少一个任务;

    .

    .

    OSStart();          /* 开始多任务调度!OSStart()永远不会返回 */

}

OSStart()的代码如程序清单:

void OSStart (void)

{

    INT8U y;

    INT8U x;

 

    if (OSRunning == FALSE) {

        y             = OSUnMapTbl[OSRdyGrp];

        x             = OSUnMapTbl[OSRdyTbl[y]];

        OSPrioHighRdy = (INT8U)((y << 3) + x);

        OSPrioCur     = OSPrioHighRdy;

        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy];                (1)

        OSTCBCur      = OSTCBHighRdy;

        OSStartHighRdy();                                          (2)

    }

}

         OSStart()从任务就绪表中找出那个用户建立的优先级最高任务的任务控制块[L3.25(1)]。然后,OSStart()调用高优先级就绪任务启动函数 OSStartHighRdy()[L3,25(2)](见汇编语言文件OS_CPU_A.ASM),这个文件与选择的微处理器有关。实质上,函数 OSStartHighRdy()是将任务栈中保存的值弹回到 CPU 寄存器中,然后执行一条中断返回指令,中断返回指令强制执行该任务代码。注意OSStartHighRdy()将永远不返回到 OSStart()。下面是调用OSStart()之后的数据结构图:

2011年10月02日 - a232346261 - 弓手称菜

(以上是自己针对邵贝贝μC/OS-Ⅱ第三章七个问题的分析,大部分内容均摘自于那本书上)

μCOS-II系统之事件(event)的使用规则及Semaphore的互斥量用法

在实时多任务系统中,信号量被广泛用于:任务间对共享资源的互斥、任务和中断服务程序之间的同步、任务之间的同步。...
  • wavemcu
  • wavemcu
  • 2014年05月31日 10:45
  • 1518

μCOS消息队列的使用

1.建立一个指向消息数组的指针和数组的大小,该指针数组必须申明为void类型: void*  HostMsgRecvQ[HOST_MSG_QUEUE_LEN];   2.声明一个OS_EVENT...

μCOS-II源码文件之OS_MBOX.C

/* *************************************************************************************************...

μCOS动态内存管理

μCOS动态内存管理 定义一个内存分区及其内存块: INT8U hostSmallRecvBuf[HOST_SMALL_RECV_BUF_CNT][HOST_SMALL_RECV_BUF_LEN]...

μCOS-II源码文件之OS_TASK.C

/* *************************************************************************************************...

μCOS-II源码文件之OS_TIME.C

/* *************************************************************************************************...

浅谈μCOS-III关于系统延时函数

嵌入式操作系统μCOS-III中涉及很多的系统延时函数,本文列举几个常用延时函数展开讨论,如有错误,望路过的各位大神不吝指点 一、系统延时函数–OSTimeDly() void OSTimeDl...
  • kada936
  • kada936
  • 2016年10月27日 19:10
  • 576

μCOS-II源码文件之OS_CORE.C

/* *************************************************************************************************...

μCOS-II源码文件之OS_FLAG.C

/* *************************************************************************************************...

嵌入式实时操作系统的基本概念——μ/COS-II读书笔记

硬件,操作系统与应用程序之间的关系:        应用软件 ACDSee。。。        系统软件 编译程序,汇编程序,编辑程序,。。。,数据库        操...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于μCOS的7个问题
举报原因:
原因补充:

(最多只允许输入30个字)