RTL8762C BLE 学习

最近开发8762c 遇到了一个问题。关于蓝牙流控的问题。查了一下资料,发现8762C的流控设置为10,就是RTL8762C 的蓝牙 TX 缓存深度有 10 层,每调用一次 send 接口会消耗 1 层,当对端收到数
据并且 LL 层返回 ACK 才恢复。
继续查资料。

关于流控:
1、流量控制是用来确保在接收者无法接收 TLP 时,发送方不会再继续发送 TLP。这避免了接收 Buffer 溢出,也消除了原本 PCI 工作方式中的一些低效行为,比如断开(disconnect)、重试(retry)和等待态(wait-state)。
2、流量控制机制使用一种基于信用(Credit-based)的机制,使得发送端口可以知道接收端口有多少可用的 Buffer 空间。作为它们初始化的一部分,每个接收者都要将自己的 Buffer 大小报告给链路对端的发送者,并在运行过程中使用 DLLP 来定期地更新这个“信用值”。技术上来说,DLLP 显然是一种开销,因为它并不携带任何数据荷载,但是 DLLP 开销很小(始终为 8 个符号大小),这样可以使其对性能的影响最小。
3、
设备报告可用的 Buffer 空间:接收者的每个端口都要报告自己的流量控制 Buffer 的大小,单位为 credit(信用)。一个 Buffer 中 credit 的数量会从自身接收侧事务层发送至发送侧数据链路层(如图 6‑1)。在合适的时间,数据链路层将会产生一个流量控制 DLLP 来将这个 credit 信息转发至每个流量控制 Buffer 的链路对端的接收者的。
接收者寄存 Credit:接收者收到流量控制 DLLP,并将 credit 值传输至自身发送侧事务层。这就完成了 credit 从链路的一端到对端的传输。这些操作是双向进行的,直到所有的流量控制信息都完成了交换。
发送者检查 Credit:在发送者可以发送一个 TLP 之前,它需要检查流量控制计数器(Flow Control Counter),以此来知道对方是否有足够的 credit。如果 credit 数量足够,那么就将 TLP 转发至数据链路层,但是如果 credit 不足,那么 TLP 的发送操作就会被阻塞直至获知的更多的足够的流量控制 credit。
4、在流控的初始化过程中,PCIe 设备们会通过对 Buffer 空间的流控 Credit 进行“advertising 通告”的方式,来相互传达各自的 Buffer 大小。PCIe 也专门定义了一些 Buffer 需要的流控 Credit 初始值。一个通告过自己的初始 Buffer 空间的接受者,可以有效的保证它的 Buffer 空间永远不会溢出。

关于LL ACK:
1、LL Data PDU的Header中,有NESN(Next Expected Sequence Number)和SN(Sequence Number)两个标记,利用它们,可以很轻松的在Link Layer实现应答、重传、流控等机制。为了实现这些功能,Link Layer会为每个连接创建两个变量,transmitSeqNum和nextExpectedSeqNum(为了和packet的SN/NESN bit区分,我们将它们简称为sn和nesn),并在连接建立的时候,它们都被初始化为0。
sn用于标识本地设备(Link Layer)发送出去的packets。
nesn是对端设备(Link Layer)用来应答本地设备发送的packet,或者请求本地设备重发packet。

1)无论是Master还是Slave,发送packet的时候,都会将当前的sn和nesn copy到packet的SN和NESN bit中。
2)无论是Master还是Slave,当接收到一个packet的时候,会将该packet的NESN bit和本地的sn比较:如果相同,说明该packet是对端设备发来的NAK packet(请求重发),则需要将旧的packet重新发送出去;如果不同,说明是对端设备发来的ACK packet(数据被正确接收),则需要将本地的sn加1,接着发送新的packet。
3)无论是Master还是Slave,当接收到一个packet的时候,会将该packet的SN bit和本地的nesn比较:如果相同,则说明是一个新的packet,接收即可,同时将本地的nesn加1;如果不同,则说明是一个旧的packet,什么都不需要处理。
)上面2)和3)两个步骤,是相互独立的,因此一个NAK packet,也可能携带新的数据,反之亦然。
5)当一个设备无法接收新的packet的时候(例如RX buffer已满),它可以采取不增加nesn的方式,发送NAK packet。对端设备收到该类型的packet之后,会发送旧的packet。该设备收到这样旧的packet的时候,不会做任何处理。这就是Link Layer的流控机制(Flow control)

好了,现在可以猜测一下为什么8762C的credit是10了。
1、随便写的一个10。
2、credit不能太大,假设发送队列为2k,如果不限制,那么调用2000次send接口,需要用2000个标识位来保存ack状态,并且没收到ack的数据还不能free。所以为了防止上层调用次数太多,直接写个固定的数值(向上管理)。

参考:
https://zhuanlan.zhihu.com/p/509861647
https://blog.csdn.net/m0_52447591/article/details/124390982?spm=1001.2014.3001.5502

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值