USB集线器的位时间与帧/微帧定时器
位时间
传输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位时间)。
硬件执行以下原子操作:
- 加载缓存:将
current_frame_timer的当前值(比如60000)复制到next_frame寄存器中。 - 启动闹钟:将同样的值(60000)加载到
frame_timer中,frame_timer开始从60000向下递减。 - 重置秒表:将
current_frame_timer重置为0,并继续递增,为测量下一个帧间隔做准备。 - 设置标志:将状态标志设置为“已同步”。
此时,frame_timer 正在倒计时,它将在大约60000个位时间后归零,触发帧结束。
第四步:正常运行与丢失恢复
这是该方法最精妙的部分,它处理了SOF包丢失的情况。
情况A:正常收到下一个SOF
当frame_timer还在倒计时时,第三个SOF到达。硬件会检查current_frame_timer(它正在测量上一个SOF到当前时刻的时间)。如果它没有溢出,说明主机正常,硬件会刷新next_frame和frame_timer,用最新的测量值校准定时器。情况B:丢失一个SOF (关键机制)
如果主机因为噪声等原因发送了一个SOF,但集线器没收到。此时:frame_timer会继续倒计时,直到归零。归零时,它会从next_frame寄存器中加载上次保存的那个旧值。- 这意味着定时器会按照上一次成功的间隔再运行一个周期。
- 如果下一个SOF仍然丢失,
frame_timer归零后会再次加载next_frame的旧值。但由于next_frame没有被新数据刷新,这个值保持不变。 - 这导致定时器以恒定且可能已过时的间隔运行。
情况C:丢失两个以上SOF
如果连续丢失的SOF超过两个,定时器会继续使用那个“陈旧”的next_frame值无限期运行。此时,虽然硬件还在工作,但由于没有SOF来校准,它实际上已经与主机“失锁”了。
定时器范围
高速微帧间隔 = 60,000( 60000 ± 96) 位时间
- 这意味着每传输60,000个比特,就是一个微帧。换算成实际时间就是:60,000 × 2.083ns ≈ 125微秒 (µs)。这正是USB 2.0高速模式下微帧的标准长度。
高速EOF2点 = EOF前64位时间
- 这意味着在微帧结束前,留出传输64个比特的时间(约 64 × 2.083ns ≈ 133纳秒)作为处理“喋喋不休”设备的缓冲。
全速帧间隔 = 12,000( 12000 ± 42) 位时间
- 换算成全速模式下的实际时间:12,000 × 83.33ns ≈ 1毫秒 (ms)。这正是USB 1.x全速模式下帧的标准长度。
USB2.0集线器HUB





