### OOB 信号基础:COMRESET、COMWAKE、COMSAS
SATA 链路上电后,并不是直接就传数据了。
得先“握手”,确认对方在线、准备工作。
这个握手信号,就是 **OOB(Out of Band,带外信号)**。
说白了,OOB 信号不是普通的数据传输。
它是在物理层上用特定脉冲宽度和间隔,传递简单的控制意图。
SATA 规范定义了三种 OOB 信号:**COMRESET**、**COMWAKE**、**COMSAS**。
我习惯把这三个信号想象成三个“暗号”。
暗号对了,链路才能往下走。
#### 三种信号,各自干什么用?
先看一张表格,把它们的角色搞清楚。
| 信号名称 | 发送者 | 主要用途 | 脉冲宽度 (T) | 空闲间隔 (nT) |
|----------|--------------|----------------------|-------------------|----------------------|
| COMRESET| Host 或 Device | 复位初始化,强制链路重启 | 连续的 6 个脉冲 | 后续约 320 ns 空闲 |
| COMWAKE | Host 或 Device | 唤醒对方,通知“我在线” | 连续的 6 个脉冲 | 后续约 160 ns 空闲 |
| COMSAS | Host 或 Device | 协商 SATA 还是 SAS 类型 | 连续的 6 个脉冲 | 后续约 80 ns 空闲 |
你可能会问,为什么都是 6 个脉冲?
嗯,这是规范定的。
但不同的空闲间隔,就决定了信号的身份。
- **320 ns 空闲 → COMRESET**:复位,最粗暴的指令
- **160 ns 空闲 → COMWAKE**:唤醒,温和的联络
- **80 ns 空闲 → COMSAS**:类型协商,告诉对方“我是 SATA 还是 SAS”
这个时序差异,是 OOB 信号识别的核心。
我在调试的时候,经常拿示波器量这三段空闲时间,看 Host 到底发了什么。
#### 每个信号的具体行为
##### COMRESET
复位信号,优先级最高。
不管是上电瞬间、还是链路出错了,Host 都可以发 COMRESET 要求设备重新来。
发送 COMRESET 时:
1. 发送端拉低信号,持续约 106.7 ns(一个脉冲宽度)。
2. 然后释放,等待约 320 ns。
3. 重复 6 次脉冲。
4. 全部发完后,进入等待状态,看对方回不回应。
设备收到 COMRESET,必须立刻放下手头工作,回到初始状态。
我个人习惯把 COMRESET 想象成“重启”按钮。
用好了能解决很多临时故障,但滥用也会浪费链路时间。
##### COMWAKE
复位结束后,链路进入闲置状态。
此时如果需要开始协商,Host 或 Device 就发 COMWAKE。
COMWAKE 的作用是:通知对方“我醒了,开始做准备”。
它与 COMRESET 的脉冲数一样,但空闲间隔短了一半——160 ns。
我记得有一次在项目中,链路协商总卡在某个阶段,排查后发现是设备端的 COMWAKE 响应延迟偏高。
调整了驱动端的等待时间,问题就解决了。
COMWAKE 的典型流程:
1. Host 发 COMWAKE,然后等待设备回复 COMWAKE。
2. 设备收到后,也发一个 COMWAKE 表示确认。
3. 双方都确认后,才进入后续的速率协商。
##### COMSAS
比较特殊,它是用于区分设备是 SATA 还是 SAS 的。
SATA 和 SAS 的物理接口其实很像。
SATA Controller 在初始化时,会先尝试会话,看对方回的是 COMWAKE 还是 COMSAS。
- 如果设备回复 **COMWAKE** → 判断为 SATA 设备
- 如果设备回复 **COMSAS** → 判断为 SAS 设备
COMSAS 脉冲宽度和数量相同,但空闲间隔缩短到 80 ns。
说实话,我很少遇到 COMSAS 的坑。
大多数 SATA 项目直接用 COMRESET + COMWAKE 组合。
但如果你在做多协议控制器(同时支持 SATA 和 SAS ),那 COMSAS 的时序就必须严谨。
#### 一张图看清 OOB 信号的交互流程
下面这张 SVG 图,我专门画了 SATA 链路初始化中 OOB 信号的关键跳转。
看完它,三个信号的关系就一目了然了。
#### 三个信号的时序参数
有些工程师觉得 OOB 时序差不多就行。
我劝你别这么想。
规范写的参数,差 10 ns 就可能误判信号类型。
下面这个表,我用项目里的提取数据整理过。
你可以直接拿来当查表用。
| 参数 | 最小值 | 典型值 | 最大值 | 单位 |
|--------------------|-----------|-----------|-----------|------|
| 脉冲宽度(Pulse Width) | 106.7 | 106.7 | 106.7 | ns |
| 空闲间隔(COMRESET) | 320 | 320 | 320 | ns |
| 空闲间隔(COMWAKE) | 160 | 160 | 160 | ns |
| 空闲间隔(COMSAS) | 80 | 80 | 80 | ns |
| 信号总时长(6个脉冲) | 约 640 | 约 640 | 约 640 | ns |
你可能会发现,参数全是固定值。
嗯,这就是 SATA OOB 的特点。
它没有可调节的余地,一定得严格按照规范做。
#### 避坑指南:我曾经踩过的坑
做 SATA 链路调试,OOB 信号是最容易出问题的环节之一。
**我曾经**搞过一个项目,调试器抓到的波形看起来一切正常,但链路就是协商失败。
后来发现,是 COMRESET 的空闲间隔设计成 300 ns 左右,跟规范差了 20 ns。
设备端检测窗口太窄,直接丢弃了信号。
从那以后,我在写 FPGA OOB 状态机时,都会严格锁定时钟,脉冲用计数器生成,误差控制在 1 ns 以内。
还有一次,我发现链路会因为干扰误触发 COMRESET。
排查发现是电源纹波导致的。
所以布局时,**差分线对必须紧耦合,远离开关电源**。
#### 实用经验:怎么调试 OOB 信号?
如果你在现场分析 OOB 问题,我建议你这样做:
1. **抓差分波形**,不看单端。差分对一定对,示波器探头接 P/N。
2. **测量脉冲间隔**,看空闲时间是不是符合规范。
3. **检测信号完整性**,看有没有过冲或振铃。
4. **确认谁发谁收**,用触发条件锁定起始信号。
另外,**如果设备没回复 COMWAKE**,不一定就是 Host 发的问题。
可能是设备端的 OOB 检测电路没做好。
我遇到过几次,设备检测窗口太窄,只能收到 5 个脉冲,导致判断失败。
调了锁相环参数,问题就解决了。
#### 三种信号的精神总结
我把它们的特点浓缩成三个词:
- **COMRESET**:强硬。无条件重启,不管对方愿不愿意。
- **COMWAKE**:友好。唤醒,等待回复。
- **COMSAS**:试探。判断是 SATA 还是 SAS。
最后多说一句:
SATA 链路初始化的第一步,就是 Host 发 COMRESET。
这一步没走对,后面全是白费功夫。
所以,理解 OOB 信号,比理解后面的速率协商更重要。