UC/OS-II-2.1

信号量常被用过了头。处理简单的共享变量也使用信号量则是多余的。请求和释放信号量的过程是要花相当的时间的。有时这种额外的负荷是不必要的。用户可能只需要关中断、开中断来处理简单共享变量,以提高效率。(参见2.18.0.1 关中断和开中断)。假如两个任务共享一个32位的整数变量,一个任务给这个变量加1,另一个任务给这个变量清0。如果注意到不管哪种操作,对微处理器来说,只花极短的时间,就不会使用信号量来满足互斥条件了。每个任务只需操作这个任务前关中断,之后再开中断就可以了。然而,如果这个变量是浮点数,而相应微处理器又没有硬件的浮点协处理器,浮点运算的时间相当长,关中断时间长了会影响中断延迟时间,这种情况下就有必要使用信号量了。< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />

2.0         死锁(或抱死)Deadlock (or Deadly Embrace)

死锁也称作抱死,指两个任务无限期地互相等待对方控制着的资源。设任务T1正独享资源R1,任务T2在独享资源T2,而此时T1又要独享R2T2也要独享R1,于是哪个任务都没法继续执行了,发生了死锁。最简单的防止发生死锁的方法是让每个任务都:

 

l          先得到全部需要的资源再做下一步的工作

l          用同样的顺序去申请多个资源

l          释放资源时使用相反的顺序

 

内核大多允许用户在申请信号量时定义等待超时,以此化解死锁。当等待时间超过了某一确定值,信号量还是无效状态,就会返回某种形式的出现超时错误的代码,这个出错代码告知该任务,不是得到了资源使用权,而是系统错误。死锁一般发生在大型多任务系统中,在嵌入式系统中不易出现。

2.1         同步

    可以利用信号量使某任务与中断服务同步(或者是与另一个任务同步,这两个任务间没有数据交换)。如图2.13所示。注意,图中用一面旗帜,或称作一个标志表示信号量。这个标志表示某一事件的发生(不再是一把用来保证互斥条件的钥匙)。用来实现同步机制的信号量初始化成0,信号量用于这种类型同步的称作单向同步(unilateral rendezvous)。一个任务做I/O操作,然后等信号回应。当I/O操作完成,中断服务程序(或另外一个任务)发出信号,该任务得到信号后继续往下执行。

< xmlnamespace prefix ="v" ns ="urn:schemas-microsoft-com:vml" />

2.13 用信号量使任务与中断服务同步

    如果内核支持计数式信号量,信号量的值表示尚未得到处理的事件数。请注意,可能会有一个以上的任务在等待同一事件的发生,则这种情况下内核会根据以下原则之一发信号给相应的任务:

 

l          发信号给等待事件发生的任务中优先级最高的任务,或者

l          发信号给最先开始等待事件发生的那个任务

 

根据不同的应用,发信号以标识事件发生的中断服务或任务也可以是多个。

    两个任务可以用两个信号量同步它们的行为。如图2.14所示。这叫做双向同步(bilateral rendezvous)。双向同步同单向同步类似,只是两个任务要相互同步。

    例如则程序清单2.10中,运行到某一处的第一个任务发信号给第二个任务[L22.10(1)],然后等待信号返回[L2.10(2)]。同样,当第二个任务运行到某一处时发信号给第一个任务[2.10(3)]等待返回信号[L2.10(4)]。至此,两个任务实现了互相同步。在任务与中断服务之间不能使用双向同步,因为在中断服务中不可能等一个信号量。

2.14 两个任务用信号量同步彼此的行为

 

 

程序清单2.10  双向同步

Task1()

{

    for (;;) {

        Perform operation;

        Signal task #2;                                                    (1)

        Wait for signal from task #2;                                    (2)

        Continue operation;

    }

}

 

Task2()

{

    for (;;) {

        Perform operation;

        Signal task #1;                                                    (3)

        Wait for signal from task #1;                                    (4)

        Continue operation;

    }

}

2.2         事件标志(Event Flags)

当某任务要与多个事件同步时,要使用事件标志。若任务需要与任何事件之一发生同步,可称为独立型同步(即逻辑或关系)。任务也可以与若干事件都发生了同步,称之为关联型(逻辑与关系)。独立型及关联型同步如图2.15所示。

2.15独立型及关联型同步

    可以用多个事件的组合发信号给多个任务。如图2.16所示,典型地,8个、16个或32个事件可以组合在一起,取决于用的哪种内核。每个事件占一位(bit),以32位的情况为多。任务或中断服务可以给某一位置位或复位,当任务所需的事件都发生了,该任务继续执行,至于哪个任务该继续执行了,是在一组新的事件发生时辨定的。也就是在事件位置位时做辨断。

    内核支持事件标志,提供事件标志置位、事件标志清零和等待事件标志等服务。事件标志可以是独立型或组合型。μC/OS-Ⅱ目前不支持事件标志.

2.3         任务间的通讯(Intertask Communication)

    有时很需要任务间的或中断服务与任务间的通讯。这种信息传递称为任务间的通讯。任务间信息的传递有两个途径:通过全程变量或发消息给另一个任务。

    用全程变量时,必须保证每个任务或中断服务程序独享该变量。中断服务中保证独享的唯一办法是关中断。如果两个任务共享某变量,各任务实现独享该变量的办法可以是关中断再开中断,或使用信号量(如前面提到的那样)。请注意,任务只能通过全程变量与中断服务程序通讯,而任务并不知道什么时候全程变量被中断服务程序修改了,除非中断程序以信号量方式向任务发信号或者是该任务以查询方式不断周期性地查询变量的值。要避免这种情况,用户可以考虑使用邮箱或消息队列。

2.16事件标志

2.4         消息邮箱(Message Mail boxes)

通过内核服务可以给任务发送消息。典型的消息邮箱也称作交换消息,是用一个指针型变量,通过内核服务,一个任务或一个中断服务程序可以把一则消息(即一个指针)放到邮箱里去。同样,一个或多个任务可以通过内核服务接收这则消息。发送消息的任务和接收消息的任务约定,该指针指向的内容就是那则消息。

每个邮箱有相应的正在等待消息的任务列表,要得到消息的任务会因为邮箱是空的而被挂起,且被记录到等待消息的任务表中,直到收到消息。一般地说,内核允许用户定义等待超时,等待消息的时间超过了,仍然没有收到该消息,这任务进入就绪态,并返回出错信息,报告等待超时错误。消息放入邮箱后,或者是把消息传给等待消息的任务表中优先级最高的那个任务(基于优先级),或者是将消息传给最先开始等待消息的任务(基于先进先出)。图2.17示意把消息放入邮箱。用一个I字表示邮箱,旁边的小砂漏表示超时计时器,计时器旁边的数字表示定时器设定值,即任务最长可以等多少个时钟节拍(Clock Ticks),关于时钟节拍以后会讲到。

内核一般提供以下邮箱服务:

 

l          邮箱内消息的内容初始化,邮箱里最初可以有,也可以没有消息

l          将消息放入邮箱(POST)

l          等待有消息进入邮箱(PEND)

l          如果邮箱内有消息,就接受这则消息。如果邮箱里没有消息,则任务并不被挂起(ACCEPT),用返回代码表示调用结果,是收到了消息还是没有收到消息。

 

消息邮箱也可以当作只取两个值的信号量来用。邮箱里有消息,表示资源可以使用,而空邮箱表示资源已被其它任务占用。

2.17 消息邮箱

2.5         消息队列(Message Queue)

消息队列用于给任务发消息。消息队列实际上是邮箱阵列。通过内核提供的服务,任务或中断服务子程序可以将一条消息(该消息的指针)放入消息队列。同样,一个或多个任务可以通过内核服务从消息队列中得到消息。发送和接收消息的任务约定,传递的消息实际上是传递的指针指向的内容。通常,先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的消息,即先进先出原则(FIFO)。然而μC/OS-Ⅱ也允许使用后进先出方式(LIFO)

像使用邮箱那样,当一个以上的任务要从消息队列接收消息时,每个消息队列有一张等待消息任务的等待列表(Waiting List)。如果消息队列中没有消息,即消息队列是空,等待消息的任务就被挂起并放入等待消息任务列表中,直到有消息到来。通常,内核允许等待消息的任务定义等待超时的时间。如果限定时间内任务没有收到消息,该任务就进入就绪态并开始运行,同时返回出错代码,指出出现等待超时错误。一旦一则消息放入消息队列,该消息将传给等待消息的任务中优先级最高的那个任务,或是最先进入等待消息任务列表的任务。图2.18示意中断服务子程序如何将消息放入消息队列。图中两个大写的I表示消息队列,“10”表示消息队列最多可以放10条消息,沙漏旁边的0表示任务没有定义超时,将永远等下去,直至消息的到来。

 

典型地,内核提供的消息队列服务如下:

 

l          消息队列初始化。队列初始化时总是清为空。

l          放一则消息到队列中去(Post)

l          等待一则消息的到来(Pend)

l          如果队列中有消息则任务可以得到消息,但如果此时队列为空,内核并不将该任务挂起(Accept)。如果有消息,则消息从队列中取走。没有消息则用特别的返回代码通知调用者,队列中没有消息。

2.18 消息队列

2.6         中断

    中断是一种硬件机制,用于通知CPU有个异步事件发生了。中断一旦被识别,CPU保存部分(或全部)现场(Context)即部分或全部寄存器的值,跳转到专门的子程序,称为中断服务子程序(ISR)。中断服务子程序做事件处理,处理完成后,程序回到:

 

l          在前后台系统中,程序回到后台程序

l          对不可剥夺型内核而言,程序回到被中断了的任务

l          对可剥夺型内核而言,让进入就绪态的优先级最高的任务开始运行

 

中断使得CPU可以在事件发生时才予以处理,而不必让微处理器连续不断地查询(Polling)是否有事件发生。通过两条特殊指令:关中断(Disable interrupt)和开中断(Enable interrupt)可以让微处理器不响应或响应中断。在实时环境中,关中断的时间应尽量的短。关中断影响中断延迟时间(2.26中断延迟)。关中断时间太长可能会引起中断丢失。微处理器一般允许中断嵌套,也就是说在中断服务期间,微处理器可以识别另一个更重要的中断,并服务于那个更重要的中断,如图2.19所示。

2.7         中断延迟

    可能实时内核最重要的指标就是中断关了多长时间。所有实时系统在进入临界区代码段之前都要关中断,执行完临界代码之后再开中断。关中断的时间越长,中断延迟就越长。中断延迟由表达式[2.2]给出。

 

[2.2]  中断延迟 = 关中断的最长时间 + 开始执行中断服务子程序的第一条指令的时间

2.19中断嵌套

2.8         中断响应

    中断响应定义为从中断发生到开始执行用户的中断服务子程序代码来处理这个中断的时间。中断响应时间包括开始处理这个中断前的全部开销。典型地,执行用户代码之前要保护现场,将CPU的各寄存器推入堆栈。这段时间将被记作中断响应时间。

    对前后台系统,保存寄存器以后立即执行用户代码,中断响应时间由[2.3]给出。

 

[2.3]  中断响应时间 = 中断延迟 + 保存CPU内部寄存器的时间

 

对于不可剥夺型内核,微处理器保存内部寄存器以后,用户的中断服务子程序代码全立即得到执行。不可剥夺型内核的中断响应时间由表达式[2.4]给出。

 

[2.4]  中断响应时间 = 中断延迟 + 保存CPU内部寄存器的时间

 

对于可剥夺型内核,则要先调用一个特定的函数,该函数通知内核即将进行中断服务,使得内核可以跟踪中断的嵌套。对于 μC/OS-Ⅱ说来,这个函数是OSIntEnter(),可剥夺型内核的中断响应时间由表达式[2.5]给出:

 

[2.5]  中断响应 = 中断延迟 + 保存CPU内部寄存器的时间 + 内核的进入中断服务函数的执行时间

 

    中断响应是系统在最坏情况下的响应中断的时间,某系统100次中有99次在50μs之内响应中断,只有一次响应中断的时间是250μs,只能认为中断响应时间是250μs

2.9         中断恢复时间(Interrupt Recovery)

    中断恢复时间定义为微处理器返回到被中断了的程序代码所需要的时间。在前后台系统中,中断恢复时间很简单,只包括恢复CPU内部寄存器值的时间和执行中断返回指令的时间。中断恢复时间由[2.6]式给出。

 

[2.6]  中断恢复时间 = 恢复CPU内部寄存器值的时间 + 执行中断返回指令的时间

 

    和前后台系统一样,不可剥夺型内核的中断恢复时间也很简单,只包括恢复CPU内部寄存器值的时间和执行中断返回指令的时间,如表达式[2.7]所示。

 

[2.7]  中断恢复时间 = 恢复CPU内部寄存器值的时间 + 执行中断返回指令的时间

 

对于可剥夺型内核,中断的恢复要复杂一些。典型地,在中断服务子程序的末尾,要调用一个由实时内核提供的函数。在μC/OS-Ⅱ中,这个函数叫做OSIntExit(),这个函数用于辨定中断是否脱离了所有的中断嵌套。如果脱离了嵌套(即已经可以返回到被中断了的任务级时),内核要辨定,由于中断服务子程序ISR的执行,是否使得一个优先级更高的任务进入了就绪态。如果是,则要让这个优先级更高的任务开始运行。在这种情况下,被中断了的任务只有重新成为优先级最高的任务而进入就绪态时才能继续运行。对于可剥夺型内核,中断恢复时间由表达式[2.8]给出。

 

[2.8]  中断恢复时间 = 判定是否有优先级更高的任务进入了就绪态的时间 + 恢复那个优先级更高任务的CPU内部寄存器的时间 + 执行中断返回指令的时间

 

2.10    中断延迟、响应和恢复

2.20到图2.22示意前后台系统、不可剥夺性内核、可剥夺性内核相应的中断延迟、响应和恢复过程。

       注意,对于可剥夺型实时内核,中断返回函数将决定是返回到被中断的任务[2.22A],还是让那个优先级最高任务运行。是中断服务子程序使那个优先级更高的任务进入了就绪态[2.22B]。在后一种情况下,恢复中断的时间要稍长一些,因为内核要做任务切换。在本书中,我做了一张执行时间表,此表多少可以衡量执行时间的不同,假定μC/OS-Ⅱ是在33MHZ Intel 80186微处理器上运行的。此表可以使读者看到做任务切换的时间开销。(见表9.3,在33MHZ 80186上μC/OS-Ⅱ服务的执行时间).

2.11    中断处理时间

    虽然中断服务的处理时间应该尽可能的短,但是对处理时间并没有绝对的限制。不能说中断服务必须全部小于100μS500μS1mS。如果中断服务是在任何给定的时间开始,且中断服务程序代码是应用程序中最重要的代码,则中断服务需要多长时间就应该给它多长时间。然而在大多数情况下,中断服务子程序应识别中断来源,从叫中断的设备取得数据或状态,并通知真正做该事件处理的那个任务。当然应该考虑到是否通知一个任务去做事件处理所花的时间比处理这个事件所花的时间还多。在中断服务中通知一个任务做时间处理(通过信号量、邮箱或消息队列)是需要一定时间的,如果事件处理需花的时间短于给一个任务发通知的时间,就应该考虑在中断服务子程序中做事件处理并在中断服务子程序中开中断,以允许优先级更高的中断打入并优先得到服务。

2.20中断延迟、响应和恢复(前后台模式)

 

2.12    非屏蔽中断(NMI)

    有时,中断服务必须来得尽可能地快,内核引起的延时变得不可忍受。在这种情况下可以使用非屏蔽中断,绝大多数微处理器有非屏蔽中断功能。通常非屏蔽中断留做紧急处理用,如断电时保存重要的信息。然而,如果应用程序没有这方面的要求,非屏蔽中断可用于时间要求最苛刻的中断服务。下列表达式给出如何确定中断延迟、中断响应时间和中断恢复时间。

 

[2.9] 中断延迟时间 = 指令执行时间中最长的那个时间 + 开始做非屏蔽中断服务的时间

 

[2.10] 中断响应时间 = 中断延迟时间 + 保存CPU寄存器花的时间

 

[2.11] 中断恢复时间 = 恢复CPU寄存器的时间 + 执行中断返回指令的时间。

 

    在一项应用中,我将非屏蔽中断用于可能每150μS发生一次的中断。中断处理时间在80125μS之间。所使用的内核的关中断时间是45μS。可以看出,如果使用可屏蔽中断的话,中断响应会推迟20μS

    在非屏蔽中断的中断服务子程序中,不能使用内核提供的服务,因为非屏蔽中断是关不掉的,故不能在非屏蔽中断处理中处理临界区代码。然而向非屏蔽中断传送参数或从非屏蔽中断获取参数还是可以进行的。参数的传递必须使用全程变量,全程变量的位数必须是一次读或写能完成的,即不应该是两个分离的字节,要两次读或写才能完成。

2.21中断延迟、响应和恢复(不可剥夺型内核)

2.22中断延迟、响应和恢复(可剥夺型内核)

 

    非屏蔽中断可以用增加外部电路的方法禁止掉,如图2.23所示。假定中断源和非屏蔽中断都是正逻辑,用一个简单的“与”门插在中断源和微处理器的非屏蔽中断输入端之间。向输出口(Output Port)0就将中断关了。不一定要以这种关中断方式来使用内核服务,但可以用这种方式在中断服务子程序和任务之间传递参数(大的、多字节的,一次读写不能完成的变量)

2.23非屏蔽中断的禁止

假定非屏蔽中断服务子程序每40次执行中有一次要给任务发信号,如果非屏蔽中断150μS执行一次,则每6mS(40*150μS)给任务发一次信号。在非屏蔽中断服务子程序中,不能使用内核服务给任务发信号,但可以使用如图2.24所示的中断机制。即用非屏蔽中断产生普通可屏蔽中断的机制。在这种情况下,非屏蔽中断通过某一输出口产生硬件中断(置输出口为有效电平)。由于非屏蔽中断服务通常具有最高的优先级,在非屏蔽中断服务过程中不允许中断嵌套,普通中断一直要等到非屏蔽中断服务子程序运行结束后才能被识别。在非屏蔽中断服务子程序完成以后,微处理器开始响应这个硬件中断。在这个中断服务子程序中,要清除中断源(置输出口为无效电平),然后用信号量去唤醒那个需要唤醒的任务。任务本身的运行时间和信号量的有效时间都接近6mS,实时性得到了满足。

                  2.24非屏蔽中断产生普通可屏蔽中断

2.13    时钟节拍(Clock Tick)

    时钟节拍是特定的周期性中断。这个中断可以看作是系统心脏的脉动。中断之间的时间间隔取决于不同的应用,一般在10mS200mS之间。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,以及当任务等待事件发生时,提供等待超时的依据。时钟节拍率越快,系统的额外开销就越大。

    各种实时内核都有将任务延时若干个时钟节拍的功能。然而这并不意味着延时的精度是1个时钟节拍,只是在每个时钟节拍中断到来时对任务延时做一次裁决而已。

    2.25到 图2.27示意任务将自身延迟一个时钟节拍的时序。阴影部分是各部分程序的执行时间。请注意,相应的程序运行时间是长短不一的,这反映了程序中含有循环和条件转移语句(if/else, switch, ? : 等语句)的典型情况。时间节拍中断服务子程序的运行时间也是不一样的。尽管在图中画得有所夸大。

    第一种情况如图2.25所示,优先级高的任务和中断服务超前于要求延时一个时钟节拍的任务运行。可以看出,虽然该任务想要延时20mS,但由于其优先级的缘故,实际上每次延时多少是变化的,这就引起了任务执行时间的抖动。

    第二种情况,如图2.26所示,所有高优先级的任务和中断服务的执行时间略微小于一个时钟节拍。如果任务将自己延时一个时钟节拍的请求刚好发生在下一个时钟节拍之前,这个任务的再次执行几乎是立即开始的。因此,如果要求任务的延迟至少为一个时钟节拍的话,则要多定义一个延时时钟节拍。换句话说,如果想要将一个任务至少延迟5个时钟节拍的话,得在程序中延时6个时钟节拍。

 

2.25将任务延迟一个时钟节拍(第一种情况)

2.26将任务延迟一个时钟节拍(第二种情况)

2.27将任务延迟一个时钟节拍(第三种情况)

 

第三种情况,如图2.27所示,所有高优先级的任务加上中断服务的执行时间长于一个时钟节拍。在这种情况下,拟延迟一个时钟节拍的任务实际上在两个时钟节拍后开始运行,引起了延迟时间超差。这在某些应用中或许是可以的,而在多数情况下是不可接受的。

    上述情况在所有的实时内核中都会出现,这与CPU负荷有关,也可能与系统设计不正确有关。以下是这类问题可能的解决方案:

 

l          增加微处理器的时钟频率

l          增加时钟节拍的频率

l          重新安排任务的优先级

l          避免使用浮点运算(如果非使用不可,尽量用单精度数)

l          使用能较好地优化程序代码的编译器

l          时间要求苛刻的代码用汇编语言写

l          如果可能,用同一家族的更快的微处理器做系统升级。如从808680186升级,从6800068020升级等

l           

不管怎么样,抖动总是存在的。

2.14    对存储器的需求

       如果设计是前后台系统,对存储器容量的需求仅仅取决于应用程序代码。而使用多任务内核时的情况则很不一样。内核本身需要额外的代码空间(ROM)。内核的大小取决于多种因素,取决于内核的特性,从1K100K字节都是可能的。8CPU用的最小内核只提供任务调度、任务切换、信号量处理、延时及超时服务约需要1K3K代码空间。代码空间总需求量由表达式[2.12]给出。

 

[2.12]  总代码量 = 应用程序代码 + 内核代码

 

       因为每个任务都是独立运行的,必须给每个任务提供单独的栈空间(RAM)。应用程序设计人员决定分配给每个任务多少栈空间时,应该尽可能使之接近实际需求量 (有时,这是相当困难的一件事)。栈空间的大小不仅仅要计算任务本身的需求 (局部变量、函数调用等等),还需要计算最多中断嵌套层数(保存寄存器、中断服务程序中的局部变量等)。根据不同的目标微处理器和内核的类型,任务栈和系统栈可以是分开的。系统栈专门用于处理中断级代码。这样做有许多好处,每个任务需要的栈空间可以大大减少。内核的另一个应该具有的性能是,每个任务所需的栈空间大小可以分别定义(µC/OSII可以做到)。相反,有些内核要求每个任务所需的栈空间都相同。所有内核都需要额外的栈空间以保证内部变量、数据结构、队列等。如果内核不支持单独的中断用栈,总的RAM需求由表达式[2.13]给出。

 

[2.13] RAM总需求 = 应用程序的RAM需求 + (任务栈需求 + 最大中断嵌套栈需求) * 任务数

 

       如果内核支持中断用栈分离,总RAM需求量由表达式[2.14]给出

 

[2.14]=RAM总需求 = 应用程序的RAM需求 + 内核数据区的RAM需求 + 各任务栈需求之总和 + 最多中断嵌套之栈需求

 

除非有特别大的RAM空间可以所用,对栈空间的分配与使用要非常小心。为减少应用程序需要的RAM空间,对每个任务栈空间的使用都要非常小心,特别要注意以下几点:

 

l          定义函数和中断服务子程序中的局部变量,特别是定义大型数组和数据结构

l          函数(即子程序)的嵌套

l          中断嵌套

l          库函数需要的栈空间

l          多变元的函数调用

 

       综上所述,多任务系统比前后台系统需要更多的代码空间(ROM)和数据空间(RAM)。额外的代码空间取决于内核的大小,而RAM的用量取决于系统中的任务数。

2.15    使用实时内核的优缺点

实时内核也称为实时操作系统或RTOS。它的使用使得实时应用程序的设计和扩展变得容易,不需要大的改动就可以增加新的功能。通过将应用程序分割成若干独立的任务,RTOS使得应用程序的设计过程大为减化。使用可剥夺性内核时,所有时间要求苛刻的事件都得到了尽可能快捷、有效的处理。通过有效的服务,如信号量、邮箱、队列、延时、超时等,RTOS使得资源得到更好的利用。

       如果应用项目对额外的需求可以承受,应该考虑使用实时内核。这些额外的需求是:内核的价格,额外的ROM/RAM开销,24百分点的CPU额外负荷。

       还没有提到的一个因素是使用实时内核增加的价格成本。在一些应用中,价格就是一切,以至于对使用RTOS连想都不敢想。

当今有80个以上的RTOS商家,生产面向8位、16位、32位、甚至是64位的微处理器的RTOS产品。一些软件包是完整的操作系统,不仅包括实时内核,还包括输入输出管理、视窗系统(用于显示)、文件系统、网络、语言接口库、调试软件、交叉平台编译(Cross-Platform compilers)RTOS的价格从70美元到30,000美元。RTOS制造商还可能索取每个目标系统的版权使用费。就像从RTOS商家那买一个芯片安装到每一个产品上,然后一同出售。RTOS商家称之为硅片软件(Silicon Software)。每个产品的版权费从5美元到250美元不等。同如今的其它软件包一样,还得考虑软件维护费,这部分开销为每年还得花1005,000美元!

2.16    实时系统小结

       三种类型的实时系统归纳于表2.2中,这三种实时系统是:前后台系统,不可剥夺型内核和可剥夺型内核。

 

 

. 2.2  实时系统小结

 

 

Foreground/
Background

Non-Preemptive Kernel

Preemptive Kernel

Interrupt latency (Time)

MAX(Longest instruction,
    User int. disable)
+ Vector to ISR

MAX(Longest instruction,
    User int. disable,
    Kernel int. disable)
+ Vector to ISR

MAX(Longest instruction,
    User int. disable,
    Kernel int. disable)
+ Vector to ISR

Interrupt response (Time)

Int. latency
+ Save CPU’s context

Int. latency
+ Save CPU’s context

Interrupt latency
+ Save CPU’s context
+ Kernel ISR entry function

Interrupt recovery (Time)

Restore background’s
    context
+ Return from int.

Restore task’s context
+ Return from int.

Find highest priority task
+ Restore highest priority
    task’s context
+ Return from interrupt

Task response (Time)

Background

Longest task
+ Find highest priority task
+ Context switch

Find highest priority task
+ Context switch

ROM size

Application code

Application code
+ Kernel code

Application code
+ Kernel code

RAM size

Application code

Application code
+ Kernel RAM
+ SUM(Task stacks
  + MAX(ISR stack))

Application code
+ Kernel RAM
+ SUM(Task stacks
  + MAX(ISR stack))

Services available?

Application code must
    provide

Yes

Yes

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值