USB2.0集线器HUB
+ -

USB集线器的位时间与帧/微帧定时器

2026-04-22 本文链接为:http://www.usbzh.com/article/detail-1622.html ,欢迎转载,转载请附上本文链接。

位时间

传输1比特数据所需的时间,是USB规范中描述时间间隔的基本逻辑单位

它可以理解为USB信号的一个基本时间单位。由于USB是串行通信协议,数据是一个比特接着一个比特在线上传输的,因此用“传输一个比特花费多久”作为衡量时间的尺度非常自然和方便。

位时间的长度取决于USB的工作速度。速度越快,传输一个比特所需的时间就越短。

  • 高速 (High-Speed, 480 Mbps)
    • 位时间 = 1 / 480,000,000 秒 ≈ 2.083 纳秒 (ns)
  • 全速 (Full-Speed, 12 Mbps)
    • 位时间 = 1 / 12,000,000 秒 ≈ 83.33 纳秒 (ns)
  • 低速 (Low-Speed, 1.5 Mbps)
    • 位时间 = 1 / 1,500,000 秒 ≈ 666.67 纳秒 (ns)

USB集线器定时器

每个集线器都有一个(微)帧定时器,其定时源自集线器的本地时钟,并通过USB主机生成的帧起始包(SOF)与主机同步到主机的(微)帧周期。

集线器的(微)帧定时器必须跟踪主机的(微)帧周期,并且即使连续错过两个SOF令牌,也必须能够保持与主机的同步。

由于USB上游集线器会检测下游设备的总线活动,当USB集线器的下游设备“喋喋不休”进行总线活动,会自动禁用下游端口设备,这样下游设备与总线断开。(微)帧定时器提供定时参考,用于让集线器检测“喋喋不休”的设备,并防止集线器被上游集线器禁用。

喋喋不休”是对英文 “Babbling” 的直译,在USB规范里,它特指一种设备故障状态,指一个USB设备在应该停止发送数据的时候,却依然在不停地往总线上发送数据。

  • 主机无法发出新的指令:主机想说“停下”,但总线一直被故障设备占着,主机的命令发不出去。
  • 其他所有设备都无法工作:因为总线被这一个“话痨”设备完全霸占了。

USB集线器的同步

USB集线器复位或恢复后,集线器的(微)帧定时器处于未同步状态。每当集线器接收到两个连续的SOF包时,其(微)帧定时器必须被同步。”同步”等同于”锁定”。

  • 同步后的USB集线器,即便SOF包偶尔丢失,也能依靠“惯性”保持一段时间的同步。
  • USB集线器未同步时,强制禁用所有下行端口的连接建立功能。当USB集线器现步后,才允许下行端口设备的连接功能。这时主机主动发起正常的设备枚举过程。

同步的三个核心组件

USB集线器在进行时间同步时,有三个部分:

  • current_frame_timer (当前帧定时器):一个递增计数器。它从0开始,每个位时间加1,像一个不间断运行的“秒表”,持续测量连续两个SOF之间的实际间隔。
  • next_frame (下一帧寄存器):一个只读寄存器。它就像一个“备胎”或“缓存”,存储着下一次定时器归零时应该加载的值。
  • frame_timer (帧定时器):一个递减计数器。它从某个值开始倒计时,归零时触发帧结束事件。这是真正控制集线器行为的“闹钟”。

2. 同步流程的四个步骤

时间间隔 关键事件 current_frame_timer (递增计数器) next_frame (寄存器) frame_timer (递减计数器) 同步状态
间隔1 系统复位/唤醒 停止/无效 无效/未知 无效/停止 ❌ 未同步
间隔2 收到第1个SOF 从0开始递增 仍为无效 仍为停止 ❌ 未同步
间隔3 收到第2个SOF 锁定同步 重置为0,重新递增 加载为60000 加载为60000,开始递减 ✅ 已同步
间隔4 正常SOF校准 重置为0,重新递增 刷新为60000 重新加载60000 ✅ 已同步
间隔5 丢失1个SOF 继续递增至60000+ 保持60000(未刷新) 从next加载60000,递减归零 ✅ 已同步(惯性)
间隔6 连续丢失第2个SOF 继续递增,超过溢出阈值(>60096) 保持60000 再次从next加载60000 ❌ 失锁

第一步:初始状态 (未同步)

复位或唤醒后,系统设置一个标志,告知所有模块:“帧定时器未同步,所有依赖它的功能(如EOF检测)暂不启用”。

第二步:捕获第一个SOF

集线器收到复位后的第一个SOF包

  • 硬件立刻执行:current_frame_timer 从0开始,每个位时间加1。
  • frame_timer 暂时不加载新值。
  • 状态:仍未同步。

第三步:锁定同步 (关键步骤)

集线器收到第二个连续的SOF包

此时,current_frame_timer 的值恰好等于主机发送两个SOF的间隔(例如高速下的60000位时间)。

硬件执行以下原子操作:

  1. 加载缓存:将 current_frame_timer 的当前值(比如60000)复制到 next_frame 寄存器中。
  2. 启动闹钟:将同样的值(60000)加载到 frame_timer 中,frame_timer 开始从60000向下递减。
  3. 重置秒表:将 current_frame_timer 重置为0,并继续递增,为测量下一个帧间隔做准备。
  4. 设置标志:将状态标志设置为“已同步”。

此时,frame_timer 正在倒计时,它将在大约60000个位时间后归零,触发帧结束。

第四步:正常运行与丢失恢复

这是该方法最精妙的部分,它处理了SOF包丢失的情况。

  • 情况A:正常收到下一个SOF
    frame_timer 还在倒计时时,第三个SOF到达。硬件会检查 current_frame_timer(它正在测量上一个SOF到当前时刻的时间)。如果它没有溢出,说明主机正常,硬件会刷新 next_frameframe_timer,用最新的测量值校准定时器。

  • 情况B:丢失一个SOF (关键机制)
    如果主机因为噪声等原因发送了一个SOF,但集线器没收到。此时:

    • frame_timer 会继续倒计时,直到归零。归零时,它会从 next_frame 寄存器中加载上次保存的那个旧值
    • 这意味着定时器会按照上一次成功的间隔再运行一个周期。
    • 如果下一个SOF仍然丢失,frame_timer 归零后会再次加载 next_frame 的旧值。但由于 next_frame 没有被新数据刷新,这个值保持不变
    • 这导致定时器以恒定且可能已过时的间隔运行。
  • 情况C:丢失两个以上SOF
    如果连续丢失的SOF超过两个,定时器会继续使用那个“陈旧”的 next_frame 值无限期运行。此时,虽然硬件还在工作,但由于没有SOF来校准,它实际上已经与主机“失锁”了。

定时器范围

  1. 高速微帧间隔 = 60,000( 60000 ± 96) 位时间

    • 这意味着每传输60,000个比特,就是一个微帧。换算成实际时间就是:60,000 × 2.083ns ≈ 125微秒 (µs)。这正是USB 2.0高速模式下微帧的标准长度。
  2. 高速EOF2点 = EOF前64位时间

    • 这意味着在微帧结束前,留出传输64个比特的时间(约 64 × 2.083ns ≈ 133纳秒)作为处理“喋喋不休”设备的缓冲。
  3. 全速帧间隔 = 12,000( 12000 ± 42) 位时间

    • 换算成全速模式下的实际时间:12,000 × 83.33ns ≈ 1毫秒 (ms)。这正是USB 1.x全速模式下帧的标准长度。
本文链接为:http://www.usbzh.com/article/detail-1622.html ,欢迎转载,转载请附上本文链接。

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936     USB技术交流3:1031974172

0 篇笔记 写笔记

关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • CDC
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!