电子技术 对于今天复杂的嵌入式应用来说,采用实时操作系统(RTOS)作为软件基础平台是一个良好抉择。RTOS 中有一个核心负责处理器专项任务,例如CPU 的分配与调度、寄存器上下文变换和存储器管理。核心的周围是完成RTOS 服务的例行程序库,它们执行各种系统级功能,在应用程序运行时发挥一定的作用。应用程序被分解为一组任务;RTOS 调度器根据某些多任务调度算法让这些任务得以控制CPU。一个应用任务(通常使用汇编语言以外的其他语言写成)为了得到RTOS 服务,需调用相应的应用程序界面(API)功能。应用程序假如是用C 语言或其它语言写成的,则RTOS 及其API 库实际上掩盖了处理器的内部工作机理(不管它是CISC 还是RISC,是8 位、16 位、还是32 位,等等),因而应用软件工程师不必太多地考虑实际使用的处理器。 上述是从外部看到的情景。但到内部去看,从RTOS 的角度观察,情景就大不相同。 RISC 机器不同于CISC 微处理器和微控制器,这些差别往往要求对有关的操作系统给与一些特殊考虑。RISC 机器是为高速度而发明的,它们运行于很高的时钟速度,通常是在一个周期内执行完指令。他们往往采用多极流水线,因而在指令流出该流水线而进入执行单元的同时,还可以进行指令与数据的预取以及转移地址的估算。当流水线的流动被打断时,比如遇到某些转移指令或跳跃指令时,其性能便受到伤害。所以,如果把这种情况减少到最低程度,就可以达到最大的性能。简而言之,RISC 机器就像是1 级方程式赛车,在笔直的车道上跑得很快,但在拐角处必须减速。 在采用多任务RTOS 时应用程序中有许多“拐角”,这是因为“笔直的”应用程序或RTOS 可能引起正常的处理流发生改变。例如在多任务应用中,许多个任务都共用处理器,它们都调用RTOS 服务,使RTOS 在其内部做许多工作(并非都是“笔直车道”),以便完成所请求的操作,并决定接着应运行哪个任务,再把CPU 的控制权交给该任务。所有这些都会引起处理流发生改变,而外部中断则更易引起这种改变。由此可见,高速笔直应用程序开足马力一直运行下去的希望落空了。如果RTOS 在通过“拐角”时减速,应用程序的性能也要遭殃。因此,RISC 处理器上的RTOS 成功的一个关键是有能力迅速通过这些“拐角”。每当RTOS 服务请求或中断引起任务的处理流发生改变时,CPU 的寄存器上下文就必须进行相应的管理,以保证同一任务重现获得CPU 的控制权时处理工作能正确继续下去。 RISC 机器通常采用数量很大的寄存器,这要求RTOS 设计时给与特殊考虑。当应用任务调用一个RTOS 服务时,RTOS 究竟需要多少个寄存器来保存上下文?RTOS 中的功能需用多少个寄存器?中断需用多少个?如果保存用的寄存器太少,RTOS 显然就会出错;这是设计 RTOS 之初的唯一考虑。反过来,如果要处理的寄存器太多,虽然问题不太明显,但性能肯定要下降。幸运的是,RTOS 设计师在作出这些决定时可以从处理器的应用二进制界面(ABI)技术规范得到帮助。 ABI 通常是在RISC 处理器厂商的支持下写成的(例如PowerPC 嵌入式ABI 就是在 Motorola 公司的赞助下写成的),它是对编译器、汇编器和调试器以及RTOS 构件等软件工具的开发人员很有用的一套规则。ABI 中含有:在函数调用期间用于传递变量的寄存器用途,堆栈帧规则,留用的寄存器,以及对编译器或调试器设计师有用的其他信息的定义。对于 RTOS 时基本上自给自足的软件,因此ABI 中的大部分规范不考虑RTOS 设计师的需要。但是,堆栈帧规则和保留寄存器定义对于设计高效的RTOS 很有用。 以保留寄存器为例。他们是非易失性的,在上下文保存与恢复操作期间需要由RTOS 管理的处理器上下文部分就不必把保留寄存器考虑进去。由于只需保存和恢复易失性的寄存器,所以每当RTOS 在处理器的上下文进行操作时,RTOS 可节省几个周期。鉴于每秒钟发生的上下文管理操作达数万次之多,因而即使节省几个周期也可使CPU 有更多的时间去做其它工作。 RTOS 设计师将乐意利用ABI 的堆栈帧规则来确保:任务栈定界于正确的边界上,栈指示器被调整到正确的数值,在保存上下文期间RTOS 建立的帧反映了ABI 所规定的格式。遵守ABI 规范会得到重大的好处:可以用遵循ABI 标准的调试器去查看堆栈。按照处理器的ABI 规范来实现RTOS 还会带来另一个看不到的好处:可与各种工具互操作。遵循ABI 标准的RTOS 应兼容于任何ABI 标准的工具链。这样的兼容性会使RTOS 开发者和用户感到高兴。RTOS 开发者之所以高兴,是因为再也不必为了与所有的非兼容工具配合工作而被迫进行软件移植。用户之所以高兴,是因为RTOS、运行库和调试器现在可以浑然一体进行工作。双方都节省了时间,提高了工作效率。 选择语言在开发RISC 处理器上的RTOS 时,RTOS 设计师还必须选用最佳的语言。RISC 处理器是很复杂的,它们的汇编语言往往最适合不怕反复调试的人使用。那些爱闹情绪的人往往改用较简单的解决方法,例如使用编译器来轻松地产生程序码。不管采用哪一种语言,选择编译器是非常重要的,因为编译器决定了产生的RTOS 程序码在RISC 处理器上运行的好坏。例如,循环的编写方法可能影响到指令流水线的连续性。流水线的处理流中断将需要清理和重新注入处理流,引起处理效率下降,其积累效应会极大地降低效能。RTOS 设计师在为 RISC 处理器编写程序时通常要采用不同于应用程序开发者的方法,使流水线只在万不得已时才中断。使处理流发生中断的另一个途径是通过中断或其它类型的例外操作。中断不仅会引起正常处理流中断,还要求为它进行中断服务,因而会使系统性能变差,如果处理不当的话还会影响其响应速度。虽然几乎每种系统都是如此,但基于RISC 处理器的系统尤为明显,这是因为它们很大的处理器上下文和硬件中断设计对软件来说是很不友好的。中断是正常处理的一种例外情况;流行的RTOS 设计都尽可能快地去处理中断,但对于运行RTOS 的RISC 处理器来说,要定义“快捷”的含义并不总是轻而易举。每当发生中断时,有关的中断服务例程(ISR)必须保存某些或全部的处理器上下文,辨认中断源,向引起中断的设备提供服务,再恢复正常的处理通路。在ISR 处理工作中,保存处理器上下文的这部分工作通常是这样完成的;先禁止处理器的中断系统,使可恢复的状态可以顺利保存而不会被破坏。但是,由于中断被禁止,其它的设备就不能请求服务,必须等到ISR 重新启动中断,允许新的中断被识别。当处理器有大量的寄存器需要保存时(典型的RISC 机器就是如此),保存上下文所需的时间要占用很多的机器周期,增加了系统的中断等待时间,降低了中断响应的速度。在理想情况下,一旦处理器的上下文保存好了,就应当允许接受新的中断,但是,这会带来一种复杂局面:已经激活的ISR 可能被另一个设备所中断。如果系统有中断优先级或分开的向量,则很容易管理多个中断。但是,如果像PowerPC 或ARM 中那样,所有的外部中断都要通过一个或两个向量输入,则重入式中断服务就是不得不面对的实际问题。虽然允许中断肯定可以改善对其他中断请求的响应速度,但处理重入式中断是复杂的任务,RTOS 必须能适应这种情况,不让任一中断只得到部分的服务。那么,哪一种方法能更快完成中断服务呢?是采用较简单的RTOS,在ISR 工作期间一直禁止中断,完全避免重入式中断的出现?还是及时允许中断输入,让ISR 和RTOS 有处理重入式中断的能力。对于上述的问题有可能没有一个恰当的答案,这是因为在决定快与慢是应用软件的考虑起着主要作用。为了让操作系统知道中断引起的事件,ISR 可能需要调用一个或多个RTOS 服务。那么,在第一种处理方法中是否需要在RTOS 服务期间也禁止中断?如果这么做的话,中断等待时间肯定会明显加长,使系统响应明显变差。简而言之,中断响应的快慢最终可能要看究竟需要哪一类系统响应。如果采用简单的RTOS,则ISR 程序可能较简单,但代价是系统响应较差。如果采用智能的RTOS 和较复杂的ISR 程序,则系统响应性能可能较好。最终的分析意见如下:对于使用RISC 处理器的嵌入式应用来说,应用需要与所选择的 RTOS 存在千丝万缕的联系。但有一点需要牢记,非常适合于应用软件和RISC 处理器的 RTOS 将能在笔直通道上快跑,还能以较快速度通过拐角。反之,如果配合不好的话,他在直道上仍然像一条猎狗,但在拐角处就变成一支普通狗。 UDN2944W UDN2954W UDN2961W UDN2962W UDN2962W-1 UDN2966W-2 UDN2974W UDN2981A UDN2982LW UDN2993LB UDN5714M UDN6118A UDN6118A-2 UDQ2543B ULN2001A ULN2001AN ULN2002AN ULN2003 ULN2003A ULN2003L ULN2004A ULN2004A(C) ULN2004AN ULN2033A ULN2064B ULN2067NE ULN2076B ULN2204A-2B ULN2802A ULN2803 ULN2803A ULN2803LW ULN2804A ULN2804LW ULN3782M ULN3839A-1 ULN3839A-2 ULN3839R-1 ULN3859A ULQ2003A ULQ2437M ULQ2803A
[此贴子已经被作者于2005-12-30 0:21:54编辑过] |