中断yuanli

上传人:子 文档编号:43985970 上传时间:2018-06-07 格式:DOC 页数:12 大小:23.03KB
返回 下载 相关 举报
中断yuanli_第1页
第1页 / 共12页
中断yuanli_第2页
第2页 / 共12页
中断yuanli_第3页
第3页 / 共12页
中断yuanli_第4页
第4页 / 共12页
中断yuanli_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《中断yuanli》由会员分享,可在线阅读,更多相关《中断yuanli(12页珍藏版)》请在金锄头文库上搜索。

1、中断中断 yuanliyuanli中断使能/禁止inUnlock()与 intLock()转2008-03-18 15:14VxWorks 提供两个重要 API: (1)intLock():使中断禁止 (2)intUnlock():开中断 可以用 intLock/intUnlock 提供最高级别的互斥机制以保护临界区域不被打断,例如: oldlevel = intLock(); /* 写 XXX 寄存器 */ XXX_REG_WRITE(pChan, XXX_UBRDIV, XXX_CNT0_115200 | XXX_CNT1_VAL); intUnlock(oldlevel);用 intLo

2、ck()禁止中断后,当前执行的任务将一直继续,中断处理和任务调度得不到执行,直到该任务主动调用 intUnLock 解锁中断为止。对于 intLock 和 unLock 的使用,我们要注意如下几点: (1)不要在中断禁止期间调用 vxWorks 系统函数,否则有可能意外使能中断,违反临界代码的设计意图。另外,intLock 也不能屏蔽调度,如果在中断禁止代码区使用系统调用,就可能出现任务调度,其他任务的运行可能会解锁中断; (2)中断禁止对系统的实时性有很大的影响,在解决执行代码和中断处理互斥问题才可使用,并且应使中断禁止时间尽可能的短。对于任务间的互斥问题,可以使用 taskLock()和

3、taskUnLock()来解决;(3)有些 CPU 中断是分级,我们可以用 intLockLevelSet()和intLockLevelGet()来操作中断闭锁的级别。缺省情况下,taskLock禁止所有等级的中断。 至此,我们可以对“互斥”问题进行一个系统的总结,主要有如下几种方法: (1)intLock 禁止中断:解决任务和 ISR 之间的互斥问题; int lock = intLock(); /. . critical region that cannot be interrupted intUnlock(lock); (2)taskLock 禁止优先级抢占调度:当当前任务正在运行时,除

4、了中断服务程序外,高优先级的任务也不允许抢占 CPU; taskLock(); /. . critical region that cannot be interrupted . taskUnlock(); (3)二进制信号量或互斥信号量。 semTake (semMutex, WAIT_FOREVER); /. . critical region, only accessible by a single task at a time . semGive (semMutex); 总的来说,在实时系统中采取“禁止中断”的方法会影响系统对外部中断及时响应和处理的能力;而“禁止优先级抢占调度”方法阻

5、止了高优先级的任务抢先运行,在实时系统中也是不适合的。因此,信号量无疑是解决互斥问题的最好方法。wasuke 大虾确实很严谨。争辩也没有关系呀,论坛本来就是通过讨论,达到相互学习,共同成长的目的嘛。不过我对于你提出的一些观点有一些不解。下面做一些分析。把 tick 设置成 1ms 再用 tick 进行延时 1ms 确实是不准确。但对于命题来说:是“获得毫秒级时间” ,我的理解是:精确到若干个毫秒,比如说 8ms,大概也就是 7.x 到 8.x 个毫秒。大致精确了。所以我对“获得毫秒级时间”的理解是:允许误差容限是 1ms,这叫做 ms级,如果要获得精确的 1ms 时间(或延时) ,这种做法就不

6、行了。当然,绝对精确的 1ms,用软件方法,特别是有操作系统、中断源不止 1 个的情况下,是很难实现的,就看对 1ms 到底有多少允许的误差,比如说允许 100us,还是 50us。所以,我认为,要获得严格的1ms 时间(延时) ,就不应该叫做“获得毫秒级时间”了。理解错误的话,还请指点。关于 taskDelay(1)还是 taskDelay(2),我确实没有这样的经验。通常,对于程序员来说,调用 taskDelay(1)的真实想法类似于“让本任务(线程)停止(挂起)1 个 tick 之后再接着往下运行” ,简单地说就是“延时 1 个 tick”,现在分析一下从调用taskDelay(1)开始

7、,对于 VxWorks 操作系统来说,究竟做了些什么:我们假设调用 taskDelay(1)的任务为 TaskA,TaskA 任务(线程)调用 taskDelay(1),系统登记当前 tick 数目,保护好任务(线程)的上下文环境,把任务(线程)放置到等待(delayed)任务(线程)列表,执行调度器,看有没有其它事情可做(就绪列表中还有任务) ,有就做,没有就执行 Idle 状态的语句。我们可以假设从 0 时刻开始,且 tick 数目可以用小数表示,调用 taskDelay(1)的精确时刻是tick 1000.9,那么登记到的 tick 应该是 1000。过了 0.1 个 tick之后,主时

8、钟中断发生了,关中断,保护现场,开中断,进主时钟中断,tick 加 1,变成 1001,执行调度器,而 TaskA 的延时已经到了(延时启动时登记的 tick 数目与现在的 tick 数目差值等于延时设置的数目) ,那么 taskA 就进入就绪(ready)队列,假设此时没有更高优先级的任务就绪(ready) ,那么 TaskA 就得到执行,因为从主时钟中断发生到调度器最终决定让 TaskA 执行这个时间(对于1 个 tick 来说)是非常短的(否则系统开销就太大了) ,假设为0.01 个 tick,当前时间点(以 tick 为单位)就是 1001.01。那么相当于说 TaskA 从调用 Ta

9、skDelay(1)开始,到延时结束,又被执行的时间是从 1000.9 到 1001.01 这段时间。显然,这个时间只有1001.01-1000.9 0.11tick 这么长,根本就是不是我们想要的1ms,而且可以说是“差远了” 。假如当初我们调用的是 taskDelay(2)而不是 taskDelay(1)。继承上面的分析中的假设,时间应该是 1002.01 - 1000.9 1.11tick。差别还要小一些。不过,这种情况不总成立,因为我们做的假设,比如从 1000.9 时间点调用 taskDelay(1) ,有可能是从 1000.03 就开始了,那么 taskDelay(1)带来的误差就

10、比 taskDelay(2)小些。另外,TaskA 进入就绪队列就马上得到执行也不一定,有可能系统中存在更高优先级的任务也就绪了,且执行需要 0.7 个 tick 之如此长,那么 taskDelay(1)带来的误差也比 taskDelay(2)要小一些。从上面可以看出,用 taskDelay 这种方式做很小时间(tick)的延时,带来的误差是有不确定性的,且与系统的负荷强相关。通常,含有调用 taskDelay(x)这种语句,而且是用于延时目的的情况,都与某种事务处理的循环执行有关(也可以是其它) 。从宏观角度来看,taskDelay(1)可以大致使得任务在 1 个 tick 内就绪一次(至于

11、在 1个 tick 内的哪个时间点执行,就不一定了),当然也不绝对正确,例如,TaskA 执行需要 0.7 个 tick 才能完成,它的执行有可能被主时钟打断(中断比任务优先级要高,是“不得不处理”的事情,而且主时钟中断永远是最高优先级的) ,那么 TaskA 跨 tick 执行的可能性是很大的,如果调用 taskDelay(1),肯定会出现就绪次数与tick 数目不相等(肯定是小于)的情况。而 taskDelay(2),在宏观上的效果,大致(不是绝对,原因同上,taskA 执行本身需要时间,还有负荷导致的执行机会问题)是两个 tick 就绪一次,同样,上面的例子,虽然第一次调用 taskDe

12、lay()的时间点处于 1 个 tick 的尾端(可以说不合理了) ,但是它下次执行,在系统轻载的情况下,就到了前端,再下一次也是前端,如此下去就成了真正的 2 个 tick 就绪一次了。所以,总得来看,如果从设计目的上是需要 taskDelay(1),那么在通常情况下(系统负荷不是很满,且 task 的执行在 1 次调用taskDelay(x)之间执行的其它代码不需要很长时间) ,使用taskDelay(1)比使用 taskDelay(2)更加能够达到(宏观上的)真实目的。但评价依据还得根据这个 task 到底需要执行多么频繁,task的自身特点,以及系统的负荷,特别是比这个 task 优先

13、级更高的事务(包括中断和任务)的总负荷。所以,我并没有弄清楚,你提出来的最好使用 taskDelay(2)是出于什么考虑?关于“有些操作系统甚至不能在几个 ms 内完成完整中断处理”的说法,按我的了解,应该来说还是非常罕见的。首先,中断处理到底要多长时间才能完成,与硬件的性能强相关,操作系统来说,有差别,但不会特别大,或者说,特别是用 ms 来描述的情况。我们来对 CPU 的性能做一个了解,看在 1ms 内,CPU 到底能干多少活执行多少指令。首先来个低速的极端:以 8 位机,没有缓存,接 11.0592M 的晶振最基本的 MCS-51(没有 4 分频,3 分频等功能的)的情况为例,12 分频

14、位 1 个指令周期,设指令平均周期位 2,那么 1s 内,可以执行的指令数目大致为 460,800 条(0.46MIPS) ,1ms 就可以执行 460 条指令。那么在这样的机器上运行复杂的操作系统(衡量复杂,最起码,中断由操作系统来管理,且有多任务调度器) ,那么中断处理在 1ms之内就非常难于完成,因为 1 个中断管理程序,和 1 个任务调度器,用 460 个指令完成困难太大了。所以这种性能水平的硬件,通常并不会运行复杂的操作系统(换而运行一些简单的操作系统,中断不由操作系统管) ,也不会把主时钟设成那么快,多数情况下,程序员选择了裸机编程。啊,需要说明的是,现在的 51 系列单片机性能,

15、通常远比上述情况要高,在指令周期分频系数,外接晶振的允许频率都大大提高了。再看我们通常用的系统,在这里以通常大家用来运行 VxWorks 操作系统的 CPU 来看,均 32 位机,其中 ARM、x86、68K、CodFire,PPC较为常见。ARM 的性能高高低低有很多档,以 MIPS 来衡量性能(浮点在嵌入式系统中,无论从系统还是应用角度对性能评价来说毕竟不是最主要因素) ,ARM 最小的也有 20 个 MIPS 以上,通常超过 100个 MIPS。1 个 60M 的 ARM,MIPS 数目大概在 70 左右。1 个 70M 的MPC860,MIPS 数目大概在 150 左右,一个 333M

16、 的 PowerPC603 核的CPU,MIPS 数目大概在 630 左右,而通常的 x86 系列,MIPS 数目均超过了 500(以上关于 MIPS 数目的估计,不一定准确但不至于有数量级差别) 。以 MPC860 为例,性能为 70MIPS,1ms 可以执行的指令数目大约为 70K(7 万)条,对于执行中断处理,调度器已经足够用了。当然,从微观角度来说,MIPS 是一个宏观量,我们不能单独用简单的 MIPS 数目来判断指令执行的确切的微观时间,现代的一些性能较高的 CPU 大多采用了高速缓存,支持指令、数据的预取,采用指令流水线技术和分支预测技术,在取指令、执行指令的这个过程中,遇到流水线冲突、分支预测失败等不期望的事情出现了,是要消耗一定时间来处理的。这个情况出现后,处理时间最大是多少,最小需要多少,发生多么频繁就跟 CPU 的设计架构有关了,与代码本身也有一定的关系,特别是程序的分支复杂的情况下,分支预测失败就发生频繁了。关于哪种 CPU 的架构好不好,流水线深度对CPU 性能的影响,网上资源很多,我就不多说了。而关于“完成中断处理” ,其时间通常由

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号