注:具体参考文档《FreeRTOS实时内核使用指南-中文.PDF》 3.2 延迟中断处理 二值信号量可以在某个特殊的中断发生时,让任务解除阻塞,相当于让任务与中断 同步。这样就可以让中断事件处理量大的工作在同步任务中完成,中断服务例程(ISR) 中只是快速处理少部份工作。如此,中断处理可以说是被”推迟(deferred)”到一个”处理 (handler)”任务。 如果某个中断处理要求特别紧急,其延迟处理任务的优先级可以设为最高,以保证 延迟处理任务随时都抢占系统中的其它任务。这样,延迟处理任务就成为其对应的 ISR 退出后第一个执行的任务,在时间上紧接着 ISR 执行,相当于所有的处理都在 ISR 中 完成一样。这种方案在图 26 中展现。 延迟处理任务对一个信号量进行带阻塞性质的”take”调用,意思是进入阻塞态以等 待事件发生。当事件发生后,ISR 对同一个信号量进行”give”操作,使得延迟处理任务 解除阻塞,从而事件在延迟处理任务中得到相应的处理。 “获取(Taking,带走,按通常的说法译为获取)”和”给出(Giving)”信号量从概念上讲, 在不同的应用场合有不同的含义。在经典的信号量术语中,获取信号量等同于一个 P() 操作,而给出信号量等同于一个 V()操作。
译者注: P 源自荷兰语 Parsseren,即英语的 Pass;V 源自荷兰语 Verhoog,即英语 的 Increment。P(S)/V(S)操作是信号量的两个原子操作,S 为信号量 Semaphore,相 当于一个标志,可以代表一个资源,一个事件等等,初始值视应用场合而定。P(S)/V(S) 原子操作有如下行为: P(S) : IF (S <= 0) THEN 将本线程加入 S 的等待队列 S = S – 1 V(S) : S = S + 1 IF (S > 0) THEN 唤醒某个等待线程
在这种中断同步的情形下,信号量可以看作是一个深度为 1 的队列。这个队列由于 最多只能保存一个数据单元,所以其不为空则为满(所谓”二值”)。延迟处理任务调用 xSemaphoreTake()时,等效于带阻塞时间地读取队列,如果队列为空的话任务则进入 阻塞态。当事件发生后,ISR 简单地通过调用 xSemaphoreGiveFromISR()放置一个令 牌(信号量)到队列中,使得队列成为满状态。这也使得延迟处理任务切出阻塞态,并移 除令牌,使得队列再次成为空。当任务完成处理后,再次读取队列,发现队列为空,又 进入阻塞态,等待下一次事件发生。整个流程在图 27 中有所展现。 如图 27 所示,中断给出信号量,甚至是在信号量第一次被获取之前就给出;而任 务在获取信号量之后再也不给回来。这就是为什么说这种情况与读写队列相似。这也经 常会给大家造成迷惑,因为这种情形和其它信号量的使用场合大不相同。在其它场合下, 任务获得(Take)了信号量之后,必须得给(Give)回来——如同第四章描述一样。
3.3 计数信号量 例 12 演示了一个二值信号量被用于让任务和中断进行同步。整个执行流程可以描 述为: 1. 中断产生。 2. 中断服务例程启动,给出信号量以使延迟处理任务解除阻塞。 3. 当中断服务例程退出时,延迟处理任务得到执行。延迟处理任务做的第一件事便是 获取信号量。 4. 延迟处理任务完成中断事件处理后,试图再次获取信号量——如果此时信号量无效, 任务将切入阻塞待等待事件发生。 在中断以相对较慢的频率发生的情况下,上面描述的流程是足够而完美的。如果在 延迟处理任务完成上一个中断事件的处理之前,新的中断事件又发生了,等效于将新的 事件锁存在二值信号量中,使得延迟处理任务在处理完上一个事件之后,立即就可以处 理新的事件。也就是说,延迟处理任务在两次事件处理之间,不会有进入阻塞态的机会, 因为信号量中锁存有一个事件,所以当 xSempaphoreTake()调用时,信号量立即有效。 这种情形将在图 30 中进行展现。 在图 30 中可以看到,一个二值信号量最多只可以锁存一个中断事件。在锁存的事 件还未被处理之前,如果还有中断事件发生,那么后续发生的中断事件将会丢失。如果 用计数信号量代替二值信号量,那么,这种丢中断的情形将可以避免。 就如同我们可以把二值信号量看作是只有一个数据单元的队列一样,计数信号量可 以看作是深度大于 1 的队列。任务其实对队列中存储的具体数据并不感兴趣——其只关 心队列是空还是非空。 计数信号量每次被给出(Given),其队列中的另一个空间将会被使用。队列中的有 效数据单元个数就是信号量的”计数(Count)”值。
计数信号量有以下两种典型用法: 1.事件计数 在这种用法中,每次事件发生时,中断服务例程都会“给出(Give)”信号量——信号 量在每次被给出时其计数值加 1。延迟处理任务每处理一个任务都会”获取(Take)”一次 信号量——信号量在每次被获取时其计数值减 1。信号量的计数值其实就是已发生事件 的数目与已处理事件的数目之间的差值。这种机制可以参考图 31。 用于事件计数的计数信号量,在被创建时其计数值被初始化为 0。 2.资源管理 在这种用法中,信号量的计数值用于表示可用资源的数目。一个任务要获取资源的 控制权,其必须先获得信号量——使信号量的计数值减 1。当计数值减至 0,则表示没 有可用资源。当任务利用资源完成工作后,将给出(归还)信号量——使信号量的计数值 加 1。 用于资源管理的信号量,在创建时其计数值被初始化为可用资源总数。第四章涵盖 了使用信号量来管理资源。
4.3 互斥量(及二值信号量)
互斥量是一种特殊的二值信号量,用于控制在两个或多个任务间访问共享资源。单 词MUTEX(互斥量)源于”MUTual EXclusion”。 在用于互斥的场合,互斥量从概念上可看作是与共享资源关联的令牌。一个任务想 要合法地访问资源,其必须先成功地得到(Take)该资源对应的令牌(成为令牌持有者)。 当令牌持有者完成资源使用,其必须马上归还(Give)令牌。只有归还了令牌,其它任务 才可能成功持有,也才可能安全地访问该共享资源。一个任务除非持有了令牌,否则不 允许访问共享资源。这种机制在图 36 中展示。 虽然互斥量与二值信号量之间具有很多相同的特性,但图 36 展示的情形(互斥量用 于互斥功能)完全不同于图 30 展示的情形(二值信号量用于同步)。两者间最大的区别在 于信号量在被获得之后所发生的事情:- 用于互斥的信号量必须归还。
- 用于同步的信号量通常是完成同步之后便丢弃,不再归还。
标签:处理,中断,信号量,互斥,任务,延迟 From: https://www.cnblogs.com/wang-1962918321/p/18045772