电子产业一站式赋能平台

PCB联盟网

搜索
查看: 20|回复: 0
收起左侧

RTOS的Stream buffer通信机制

[复制链接]

540

主题

540

帖子

3901

积分

四级会员

Rank: 4

积分
3901
发表于 5 天前 | 显示全部楼层 |阅读模式

i1cfrls550q64020957717.gif

i1cfrls550q64020957717.gif


kgdg431emoy64020957817.png

kgdg431emoy64020957817.png


SAFERTOS中的流缓冲区(Stream buffer)机制,可以实现任务到任务或中断到任务之间的通信。字节流是由发送方写入缓冲区,接收方读取缓冲区数据。流缓冲区作为队列的轻量级级替代方案,适合单读单写场景,写者在流缓冲区中放置任意数量的字节,读者读取任意数量的字节。



流缓冲区

oghkrlh2gij64020957917.png

oghkrlh2gij64020957917.png



顾名思义,存储数据的结构是一个先进先出的缓冲区。通过调用xStreamBufferSend或xStreamBufferSendFromISR API写缓冲区,将数据添加到缓冲区末尾,可以使用任务通知发信号通知等待任务。
流缓冲区有一个触发级别,其值为流缓冲区必须写入的最小字节数,因此,触发级别值可以在1和流缓冲区的长度之间。缓冲区长度是有限的,这意味着如果从缓冲区读操作发生得不够快,缓冲区可能会满。
因此,对缓冲区的写入可以是阻塞的(非ISR函数可以阻塞),阻塞时间可以自定义。可以使用任务通知将缓冲区空闲空间通知写任务。否则,所有数据需在阻塞时间内发送。
大多数情况下,由于对发送数据的处理太慢(读任务的优先级太低,或者数据生成速度比预期的要快),缓冲区被尽可能多的字节填充,API将返回一个错误代码以及写入的数据量。
从流缓冲区中读取数据通过调用xStreamBufferReceive或xStreamBufferReceiveFromISR完成。如果操作成功,函数返回一个状态码及读取的数据。读取数据的数量取决于流缓冲区中的可用字节数和指定数组的大小,可以指定阻塞时间(只有非ISR函数可以阻塞),如果规定的时间内没有数据可用,或没有任务通知解除阻塞,则会超时。尽管发生了超时,但流缓冲区中可能有数据,但不足以达到触发级别(如果触发级别大于1)。读操作成功将返回可用数据。如果从满流缓冲区中读取数据,则发送任务通知给等待写数据但由于缓冲区满而阻塞的任务。

lkrlpkvuieu64020958018.png

lkrlpkvuieu64020958018.png

图1 Stream buffer示例
图1的流缓冲器示例应用是一个模数转换器,当数据可用时就会产生中断。转换后的数据在中断服务程序中发送到缓冲区。然后,通知使用数据的任务从流缓冲区中读取并处理数据,如过滤数据或计算控制器步长。



消息缓冲(message buffer)




消息缓冲区建立在流缓冲区上,用于交换离散的消息。消息具有定义的长度,其长度被附加到有效负载中。这意味着当发送10字节的消息时,消息的长度(数字10)首先添加到缓冲区中,因此接收方可以在读取消息之前读取该值,了解有多少字节的有效载荷。存储消息长度的字节数是可配置的,必须预先定义,以便接收方确切地知道从缓冲区读取多少字节以获得下一条消息的长度。如何配置存储消息长度的字节数取决于最大的消息长度,单个字节长度可用于最多255字节的消息,2字节长度字段可用于最多65535字节的消息。
缓冲区的大小应考虑最大消息长度和长度字段,例如,报文长度为10字节,长度字段2字节,每个消息的缓冲区中占用12字节。
在SAFERTOS中,流缓冲区和消息缓冲区使用相同的API函数。为了区分两者,在StreamBuffer结构体中使用了一个额外的标志,在创建流/消息缓冲区时指定。API函数的行为略有不同。
使用流缓冲区时,如果指定了阻塞时间(只有非ISR函数可以阻塞),读取和写入操作可以阻塞。消息缓冲区的行为与流缓冲区相似。如果消息缓冲区中没有消息,则消息缓冲区的读取操作将被阻塞,任务将阻塞,直到阻塞时间到或足够的数据被发送到消息缓冲区。因为消息不会部分发送,对于消息缓冲区,在大多数情况下触发级别为1字节是最有用的,单个字节消息将解除等待任务阻塞。
如果缓冲区不够用,写操作就会阻塞,直到足够的字节/消息从缓冲区中读取,或阻塞时间超时。

5r1trg44abp64020958118.png

5r1trg44abp64020958118.png

图2 stream buffer序列



多核应用




流缓冲区和消息缓冲区也可以将在一个核上数据发送到另一个核上执行的任务/中断中。在非对称多处理器配置中,每个处理器运行自己的RTOS实例。为了在核间共享数据,必须使用共享内存保存流缓冲区数据。
为了通知读核有新的数据产生,可以使用从一个核到另一个核的中断。
SAFERTOS API有多个函数处理多核流缓冲区的使用,但核心功能很大程度上依赖于处理器体系结构。因此这些函数为弱定义的桩,必须由应用程序实现特定于核的功能。
要通知读核一个缓冲区写入完成,可以使用API函数vStreamBufferSendCompletedMulticore和vStreamBufferSendCompletedFromISRMulticore。如果另一个核上的任务试图从空的流/消息缓冲区中读取数据并等待数据发送,则调用这些函数。使用这些函数来代替单核场景中的任务通知,并且可以触发等待核的中断,从而解除等待读取任务的阻塞。
使用vStreamBufferReceiveCompletedMulticore和StreamBufferReceiveCompletedFromISRMulticore函数通知写核可用的缓冲区空间。如果另一个核上的任务试图写满的缓冲区并等待发送数据,则调用这些函数。使用这些函数来代替单核场景中的任务通知,并且可以触发等待核的中断,从而解除等待写入任务的阻塞。
多核应用的一个重要方面是对流/消息缓冲区数据访问的协调。在单核设备上,一次只能有一个任务或中断处于活动状态,如果一个任务需要访问数据结构而不被中断,它可以在临界区内操作。当多个核同时处于活动状态时,必须防止对共享数据结构的并行访问。因此,必须使用锁定机制来确保核对缓冲区数据结构的独占访问。SAFERTOS提供xStreamBufferAttemptToLock和vStreamBufferReleaseLock函数实现此功能。这些函数也是弱定义的桩,应用程序必须基于特定于处理器的实现来协调访问。

cl4arnnvryn64020958218.png

cl4arnnvryn64020958218.png

图3 多核示例系统


基于流缓冲区机制可以实现任务间实时数据处理,有效地管理任务之间的数据流,确保RTOS应用程序中的高效通信和同步。
猜你喜欢:
一个非常轻量的嵌入式日志库!
一个面向对象的C语言框架!
一个非常轻量的嵌入式线程池库!
Github上热门 C 语言项目汇总!
实用 | 10分钟教你通过网页点灯
WiFi6+蓝牙+星闪,三合一开发板,真香!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表