SATA协议概述:从版本演进到三层架构

好,咱们直接开始。SATA链路Bring-up,说白了就是让硬盘和主机正确握手、正常跑起来。但你要想搞定它,得先知道SATA到底是个什么东西。

我早期做Bring-up那会儿,总想着直接上手调寄存器,结果问题查来查去,根因在协议理解上。后来我学乖了——必须先搞清楚协议框架,再动手。

SATA标准版本历史

SATA联盟从2000年成立到现在,发布了多个版本。我个人习惯把SATA分成三代来看:

迭代版本 发布年份 速率 编码 备注
SATA 1.0 2000 1.5 Gbps 8b/10b 第一版,替代PATA
SATA 2.0 2004 3.0 Gbps 8b/10b 多了原生指令队列(NCQ)
SATA 3.0 2009 6.0 Gbps 8b/10b 主流版本,我在项目中遇到最多
SATA 3.2 2013 6.0 Gbps 8b/10b 引入SATA Express、microSSD
SATA 3.3~3.4 2016~2018 6.0 Gbps 8b/10b 主要做特性增强、功耗优化
SATA 3.5 2020 6.0 Gbps 8b/10b 最新的兼容性修订版

你可能会问,怎么速率到6Gbps就停了?因为8b/10b编码的开销,实际有效数据带宽只有约600 MB/s。嗯,再往上走成本不划算——大家后来都转向PCIe/NVMe了。

避坑提醒:我曾经遇到过项目对标称SATA 3.0的盘,握手只跑到1.5Gbps。查了一下午,结果是SATA线缆质量不达标——信号衰减太大,降速协商了。所以选线缆别贪便宜。

SATA协议的三层架构

SATA协议分为物理层、链路层、传输层三层。很多人只关注链路层和传输层,觉得物理层是硬件的事。我一开始也这想法,直到一次调试时发现示波器上眼图全闭了……

所以,每一层都不能轻视。

SATA协议三层架构 物理层(Physical Layer) 信号生成 | 眼图调优 | 电气特性 | OOB带外信号 差分对 TX+/RX- · Gen1~Gen3速率协商 链路层(Link Layer) 原语控制 | CRC校验 | 数据流控 | 加扰/去扰 ALIGNp · SYNCp · X_RDY/W_RRM · 8b/10b 传输层(Transport Layer) FIS封装 | 帧序列管理 | 命令/数据调度 寄存器FIS · DMA FIS · PIO FIS · 帧头帧尾 数据从上往下传:Host → Transport → Link → Phy → 线缆

物理层:最容易被忽略的层面

物理层说白了就是管信号的。差分对TX+/-、RX+/-,加上Gen1/Gen2/Gen3的速率协商。这东西在Bring-up阶段你必须搞定——因为上电首先就是物理层的OOB(Out-Of-Band)信号握手。

OOB信号包含COMRESET、COMINIT、COMWAKE三个事件。只有它们走通了,链路层才能开始工作。

我的经验:拜Bring-up时,第一件事就是抓OOB信号。很多新手以为先配寄存器,其实应该先看示波器。我曾经不抓OOB就调,浪费了两天。——示波器挂上,10分钟就发现物理层没起来。

链路层:通信的“规矩”

链路层我花了最多时间。它管的是通信的规矩——原语(Primitive)控制、CRC校验、流控、加扰/去扰。

原语是什么?就是一串特殊的Dword。比如ALIGNp用来对齐边界,SYNCp用来维持空闲状态,X_RDY表示“我想发数据”。Bring-up时你得盯着这些原语的状态机看——它们必须一个不漏地跑通。

状态机跑不对?那就是链路没建立。我在调试中遇到的很多“死机”问题,根因都在链路层原语交换失败。

  • ALIGNp:连续发送,帮接收端找到边界
  • SYNCp:链路空闲时维持同步
  • X_RDY:声明“我有数据要发”
  • R_RDY:响应“我准备好收了”

链路层核心指标:

  • CRC-32校验,保证数据完整性
  • 8b/10b编码,保证直流平衡
  • 加扰多项式:G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

传输层:数据怎么组织

传输层说白了就是管数据从哪里来到哪里去的。它负责把命令打包成FIS(Frame Information Structure),往下传。

常见的FIS类型包括:

FIS类型 用途
寄存器FIS 主机发送命令,设备返回状态
DMA FIS DMA传输——设备直接读写内存
PIO FIS 程序控制I/O,老式传输,现在少见
SDB FIS 释放命令,设备说“我干完了”

传输层还要管理帧序列。每个FIS都由帧头和帧尾包着——帧头加CRC,帧尾加CRC校验。这层错了,命令就发不出去。

我记得有一次调试,磁盘一直不响应读命令。查来查去,原来是传输层把DMA FIS的type字段写错了。所以啊,传输层的每个FIS字段都得核对清楚。

再提醒一次:Bring-up不是“调通就行”。你要从头到尾理解这三层的配合。物理层管信号,链路层管传输规矩,传输层管数据封装。一层出问题,整个链路就起不来。——我见过太多工程师在物理层卡死的例子了。