### 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 信号的关键跳转。 看完它,三个信号的关系就一目了然了。

SATA OOB信号交互流程图 主机上电 / 复位 发送 COMRESET 等待设备 回复 COMWAKE 设备上电 / 复位 检测到 COMRESET 发送 COMWAKE 主机确认链接 设备确认链接 双方进入速率协商阶段 图例 COMRESET COMWAKE 检测 等待 脉冲数:6个 空闲间隔区分

#### 三个信号的时序参数 有些工程师觉得 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 信号,比理解后面的速率协商更重要。