RTOS 是一种软件,可以尽可能高效地管理中央处理单元 (CPU)、微处理单元 (MPU) 甚至数字信号处理器 (DSP) 的时间。大多数 RTOS 内核都是用 C 编写的,需要一小部分用 ASSEMBLY 语言编写的代码来使内核适应不同的 CPU 架构。
RTOS 内核为程序员提供了许多有用的服务,例如多任务处理、中断管理、通过消息队列的任务间通信、信令、资源管理、时间管理、内存分区管理等等。
应用程序(即最终产品)基本上分为多个任务,每个任务负责应用程序的一部分。任务是一个简单的程序,它认为它自己拥有 CPU。每个任务都根据任务的重要性分配一个优先级。
什么是消息队列?
如图 1 所示,消息队列是一个内核对象(即数据结构),消息通过它从中断服务例程 (ISR) 或任务发送(即,发布)到另一个任务(即,挂起)。一个应用程序可以有任意数量的消息队列,每个队列都有自己的用途。例如,消息队列可用于将从通信接口 ISR 接收到的数据包传递给任务,该任务又负责处理数据包。另一个队列可用于将内容传递给将负责正确更新显示的显示任务。
图 1.消息队列是用于将内容传递给任务的内核对象。
消息通常是指向包含实际消息的存储区域的空指针。但是,指针可以指向任何东西,甚至是接收任务要执行的函数。因此,消息的含义取决于应用程序。每个消息队列都可以配置其将容纳的存储量。可以将消息队列配置为保存单个消息(也称为邮箱)或N条消息。队列的大小取决于应用程序以及接收任务在队列填满之前处理消息的速度。
如果一个任务挂起(即等待)一条消息并且队列中没有消息,那么该任务将阻塞,直到一条消息被发布(即发送)到队列中。由于 RTOS 运行其他任务,因此等待任务在等待消息时不消耗 CPU 时间。如图 1 所示,挂起的任务可以指定一个超时时间。如果在指定的超时时间内没有收到消息,则当该任务成为最高优先级任务时,将允许该任务恢复执行(即解除阻塞)。当任务执行时,它基本上被告知它被恢复的原因是因为超时,因此没有收到消息。
消息队列通常实现为先进先出 (FIFO),这意味着接收到的第一条消息将是从队列中提取的第一条消息。但是,某些内核允许您发送被认为比其他内核更重要的消息,因此可以在队列的头部发布。换句话说,按照后进先出 (LIFO) 的顺序,使该消息成为任务提取的第一个消息。
消息队列的一个重要方面是消息本身需要从发送到处理期间保持在范围内。这意味着您不能将指针传递给堆栈变量、可以被其他代码更改的全局变量等等。为了使消息保持在范围内,您通常会填充从池中获取的结构如图 2 所示。发送消息的 ISR 或任务将从池中获取一个结构,填充该结构,并将指向该结构的指针发布到队列中。接收任务将从队列中提取指针,处理结构,完成后将结构返回到池中。当然,发送方和接收方都需要使用同一个池,除非数据结构中的字段指示使用了哪个池。
图 2.消息存储区池
在 RTOS 中消息队列的许多实现中,如果队列已满,发送到队列的消息将被丢弃。通常这不是问题,应用程序的逻辑可以从这种情况中恢复。但是,实现一种机制相当容易,这样发送任务将阻塞,直到接收方提取其中一条消息,如图 3 所示:
1.计数信号量初始化为队列可以接受的最大条目数对应的值。
2.在允许发送消息到队列之前,发送任务在信号量上挂起。如果信号量值为零,则发送方等待。
3.如果该值非零,则信号量计数递减,并且发送方将其消息发布到队列中。
4.消息的接收者像往常一样在消息队列中挂起一个。
5.当接收到消息时,接收者从队列中提取指向消息的指针并向信号量发出信号,表明队列中的条目已被释放。
图 3.如果队列已满,则阻止发送者。
如图所示,此机制仅适用于两个任务,因为不允许 ISR 挂在信号量上。
消息队列的其他用途
图 4 显示了消息队列的不同用途:
1-4。如前所述,消息队列通常用于将消息从 ISR 或任务发送到另一个任务。
5.但是,如果消息适合指针的字长,则不必发送实际消息并分配存储区域。例如,如果指针是 32 位宽,那么您可以将从 12 位 ADC 读取的模数转换器 (ADC) 转换为指针并通过消息队列发送它。只要接收者知道将值转换回整数,它就是完全合法的。
6-7。如果任务知道消息不会发送给它,它可以使用超时机制将自己延迟一段时间。在这种情况下,能够容纳单个条目的队列就足够了。事实上,如果另一个任务或 ISR 发送消息,延迟将被中止,这可能是您想要实现的行为。
8.消息队列可以用作信号量来简单地向任务发出事件发生的信号。在这种情况下,消息可以是任何东西。队列的大小取决于应用程序需要缓冲多少信号。
9-10。消息队列也可以用作二进制信号量或计数信号量以进行资源共享。对于二进制信号量,队列将包含单个消息,并且将在队列中放置一条消息(任何值)。要访问资源,任务将在队列中挂起。如果队列中有消息,则任务将获得对资源的访问权。一旦完成资源,队列将被发布,从而根据需要放弃资源以供其他任务使用。相同的机制适用于实现具有N个 资源的计数信号量,并且队列将预先填充N个 虚拟消息。
11.消息实际上可用于模拟事件标志,其中 32 位指针大小变量(转换为整数)的每一位都可以表示一个事件。
12.可以使用消息队列来实现栈结构。这基本上是 LIFO 机制的另一种用法。
图 4.消息队列的许多用途中的一些。
概括
消息队列可以以多种不同的方式使用。事实上,您可以编写可能只使用消息队列的相当复杂的应用程序。仅使用消息队列可以减少代码的大小(即占用空间),因为可以模拟许多其他服务(信号量、时间延迟和事件标志)。
审核编辑:郭婷
-
cpu
+关注
关注
68文章
10802浏览量
210776 -
MPU
+关注
关注
0文章
339浏览量
48694 -
RTOS
+关注
关注
21文章
809浏览量
119353
发布评论请先 登录
相关推荐
评论