原文链接:蛋蛋读UFS之三:UFS数据包UPIU
UFS中流淌的数据包叫做UPIU(UFS Protocol Information Unit,UFS协议信息单元),它是固定格式的数据结构,用以传输应用层发来的命令或者请求,以及跟它们相关的数据或者状态信息。它就是SATA中的FIS,PCIe中的TLP。
我们看看UFS中命令或请求是怎么执行的。
UFS采用“客户-服务器”或者说主从的命令架构,UFS主机(Client,命令发起者,Initiator,他们都是一个意思)发送命令或者请求(Request)给UFS设备(服务器,Target),然后UFS设备执行命令并返回命令状态(Response)。
一个命令或者请求的执行包含下面几个阶段:
命令阶段:主机发起命令或请求给设备,这是“因”;
数据阶段:传输跟命令相关的数据,比如读写命令,都涉及到数据的传输;有些命令不涉及数据的传输,所以这个阶段并不是总是存在的,跟具体命令和请求相关。
状态阶段:设备执行完命令,必须给主机返回命令执行状态信息。这个是“果”,必不可少的。在PCIe中,有Posted和Non-posted的TLP。对前者,命令执行者无需返回命令执行状态给命令发起者,对后者,命令执行者必须返回状态给命令发起者。对UFS来说,它的命令总是non-posted,即设备必须返回命令状态给主机。
在命令执行过程中,无论是处在哪个阶段,UFS主机和设备间都是通过UPIU进行信息的交互。
1. UFS主机通过命令或者请求UPIU发命令请求给设备;
2. UFS主机或者设备通过UPIU传输数据;
3. UFS设备通过UPIU返回命令状态信息给主机。
下面我们看看UFS当中都有哪些UPIU。
命令或者请求UPIU
前一章看到,应用层包括UFS命令、设备管理器和任务管理器三个模块,传输层根据不同模块发来的命令或者请求,分别产生不同类型的UPIU。
UFS命令模块发送简化版本的SCSI命令,当传输层收到命令请求后,它会生成:COMMAND UPIU,把命令封装起来。
应用层通过任务管理器来管理任务队列,比如终止(Abort)和查询命令队列中的命令。当传输层收到来自任务管理器中的请求后,它会生成:TASK MANAGEMENT REQUEST UPIU,把请求封装起来。
UFS通过设备管理器来管理UFS设备,比如设置和查询UFS设备的配置(Configuration)。当传输层收到来自设备管理器发来的请求后,它会生成:QUERY REQUEST UPIU,把请求封装起来。
数据传输相关UPIU
当主机发送了类似读命令给设备之后,设备需要返回数据给主机,设备通过DATA IN UPIU向主机传输数据。
当主机发送了类似写命令给设备之后,主机需要往设备写数据,主机通过DATA OUT UPIU向设备传输数据。
UFS的主机是个暖男,它在向设备写数据的时候,会考虑到设备这个时候能不能接收数据(因为设备可能这个时候没有足够的空间接收主机数据),它在向设备发了写命令之后,不会立刻把数据传输给设备,而是在那里等设备的通知。当设备准备好接收数据,以及接收多少数据,设备通过READY TO TRANSFER UPIU (RTT)告知主机。当主机接收到该RTT后,才开始按照RTT的信息传输数据。至于每次传输数据的多少,RTT中包含这信息,主机根据RTT进行传输。
所以,主机只有在收到设备的RTT,才能发DATA OUT UPIU!
注意,读命令无需这种机制。因为设备从闪存中获得数据后,是设备控制数据的传输。对主机来说,它在发读命令之前,已经准备好足够的空间用以接收数据,所以不存在主机没有空间接收数据的情况。
状态UPIU
前面看到,主机有三种请求:SCSI命令,任务管理器发出的Task Management Request,以及设备管理器发出的Query request。针对不同的命令或者请求,设备在执行完相应的任务后,分别返回对应的状态UPIU给主机。
其它UPIU
除了以上常规的UPIU,还有其它一些UPIU作为他用。
设备上电后,主机检测是否与之连接,会发NOP OUT UPIU给设备。我们平时想看看跟某个电脑或者网站能否连接上,会发一个ping命令。NOP OUT UPIU跟ping命令作用类似。
当设备收到NOP OUT UPIU后,会返回NOP IN UPIU。主机收到该UPIU后,确认与设备连接,然后可以进行后续操作。
最后一个UPIU就是REJECT UPIU。当设备收到一个无效的UPIU时,它会发REJECT UPIU拒绝无效的UPIU。
UPIU汇总
偷个懒,我就直接把UFS spec这张表贴这里。数了数,一共12个UPIU。经过我之前的解释,读者现在应该清楚每个UPIU的作用了。
读写命令中UPIU交互例子
前面我们都是单个来看UPIU,现在我们以读写命令为例,看看他们是如何组合完成命令处理的。
首先是一个“主机往设备读取96KB数据”的例子。
首先,主机发送读96KB数据的命令给设备,然后设备执行命令,分了三批把数据返回给主机,最后返回命令执行状态给主机。
然后是一个“主机往设备写64KB数据”的例子。
主机发送写64KB数据的命令给设备,然后在那里等设备响应。很快,设备说,你可以传24KB数据下来了,于是主机写24KB数据给设备;接着,设备又来通知说可以继续传32KB数据,主机照做。最后,设备通知说可以把最后8KB数据也传过来,主机于是写最后8KB数据。最后,主机收到设备命令执行完成的响应。
我们看到,主机必须等收到RTT后才能启动数据传输!