一、SoundWire 概述:
SoundWire是MIPI提出的一个接口协议,与I2S,HDA一样,是音频接口协议。其特点是:
1. 通过一个 two-pin接口来传输音频data,控制命令等。
2. 其clock scaling 和可选的多条data lane给予data频率更高的灵活度以匹配系统要求。
3. 因为用了DDR(double data rate)数据传输方式,因此可以使用更低的时钟频率和功耗。
4. 单个master可以连接最多11个slave。
5. 支持slave to slave的数据传输方式。
6. 支持多负载传输机制(multiple payload transport mechanisms),包括同步或者异步的音频流。
7. 帧大小可以灵活配置,payload具有复杂性,支持PCM和PDM音频流。
8. 低延时,高采样率。
二、SoundWire 物理层接口(PHY):
SoundWire接口使用两根信号做设备之间的连接:
• Clock – 从master发送到全部slave的时钟信号。
• Data – 可以被所有设备驱动的data信号,并且可以配置没有设备驱动它的时候的空载值。
SoundWire 设备(device)与PHY:
上图为SoundWire的master interface和slave interface,内部的digital interface负责传送payload,command等,而PHY负责提供本设备与其他SoundWire设备的物理连接(两线接口)。
Data Signaling and Bitslots
1. SoundWire采用DDR(double data rate)进行数据传输。1个bit在上升沿的时候被驱动,并且在下降沿被采样,下一个bit在下降沿被驱动,在上升沿被采样。数据可以在上升沿和下降沿被采样,所以数据传输频率时时钟的两倍。
2. SoundWire帧内每一个bit叫做bitslot,帧内第一个bitslot叫bitslot[0],后面以此类推,bitslot[n]紧接着bitslot[n-1],所以bitslot[0]时紧跟着上一帧的最后一个bitslot。
3. Bitslot里面的的值,都是由0个,1个,甚至是多个SoundWire设备提供的。如果一个设备提供了这个bitslot的值,我们称为这个设备own了这个bitslot(这个设备就叫the owner of the Bitslot)。
SoundWire采用改进的NRZI进行数据编码(这段不是很懂)
NRZI编码:
下图为NRZI编码方式,当data值发生变化时,表示为1,当data值不变时,表示为0,如果要传输“1101011”,则最终data的值为“HLLHHLH”或者“LHHLLHL”,前者还是后者,取决于传输信号前,data的状态。
改进的NRZI编码:
SoundWire采用改进的NRZI编码,意味着如果设备想从SoundWire总线上抓取数据作为自己的input data(例如Bitslot[n]),则要根据时钟,采样两个点(例如Bitslot[n-1]和Bitslot[n])进行对比。同样,如果设备想从SoundWire总线上输出data(例如Bitslot[n]),则需要采样当前data的值(例如Bitslot[n-1])来确认输出的data应该是什么值。
这个改进的NRZI的不同点在于,只有在逻辑“1”的时候,data output信号被主动驱动起来,逻辑“0”的时候,data信号可以被被动驱动起来。
这样做有两个好处:
1. 如果当前的bitslot没有owner,或者是由于某些data原因没有被驱动,这个master的bus-keeper会让data保持逻辑0状态,这有利于检查出丢失的设备和某些错误配置;
2. 允许同一个bitslot拥有两个甚至多个owner,多个owner之间的关系是“线或”(wire-ORed),意味着一个owner要输出逻辑1,对于其他逻辑0拥有更高的优先级。
三、帧结构与Control Word:
帧结构
SoundWire的帧可以看作成一个二维数组,由比特流(bitstream)的行和列组成。其中,行的值是48~256里面的几个值,同样,列是2~16。这些master设备可以通过配置寄存器来决定的,同时这些帧的属性变量是动态可配的。初始的帧大小就是96个bitslot(48行,2列)。
配置列数:
配置行数:
每一帧的第一个bitslot开始于时钟的下降沿(第一个output data生成),并且结束于时钟的上升沿(最后一个bitslot被采样)。因为列数永远是偶数,所以下一帧的第一个bitslot也总是在时钟下降沿开始。
但是SPEC说的一帧的最后一个bitslot结束和下一帧的开始bitlost是同一个moment,这个不太理解,我的理解是第N帧的结束和第N+1帧的开始,应该是相差一个周期的。
下图为帧结构的图:
Control Word
在帧结构中,第一列的前48个bitslot为control word({row[0],col[0]},{row[0],col[1]}......{row[0],col[48]}),由于bitstream传输是一行一行(row)传输的,因此control word在bitstream上是不连续的。前48行中,每行第一个为control word的一部分,该行剩下的bitslot都是data payload。下图为control word在帧结构中的位置。
在control word里面的bitslot被分配成以下两种功能:
• Control BitSlot(20):负责一些低层级的功能,例如帧同步等。
• Command BitSlot(28):负责帮助当前的command owner传输command给其他设备,也负责接收respond给command owner。
Control Word Fields
1. PREQ(Ping Request):
一个或者多个Slave用于通知Owner,其需要在Ping command 中上报一些状态。因为多个slave的data pin是"线与"关系,所以只要有一个slava拉起了PREQ,Owner收到的这一帧的PREQ都会被拉起来。当owner收到这个PREQ时,会在接下来的32帧内发送ping command去读取slave的状态。在第N帧内发生类似中断等信息需要发送PREQ时,已经晚于当前帧发送PREQ的时机了,因此会在N+1帧甚至N+2帧的时候才能发出PREQ,一旦拉起了PREQ,slave会一直拉起来直到其能成功收到来自Owner的ping command。
2. Opcode:
Opcode由3个bit组成,command field的组成由Opcode来决定。Opcode由Master或者Monitor接口(command owner), slave接口接收到不同的Opcode和对应的command field之后会做相应的动作。Opcode有3种:
• Ping:让总线上的所有slave返回状态。
• Write:Command Owner给一个或者多个设备中一个或者多个寄存器写一个8 bit 的值。
• Read:Command Owner从一个或者多个设备中一个或者多个寄存器读一个8 bit 的值。
当Opcode为Ping的时候,command field如下:
当Opcode为Write或者Read的时候,command field如下:
当Opcode为Reserved的时候,command field如下:
3. Static Synchronization
Static Synchronization是一个固定的8bit的值为 b'10110001,由master产生,slave接收,并以此来维持帧同步。
4. PHY Synchronization
PHY Synchronization为1bit,由master生成,通知slave当前的PHY属于什么状态:0代表普通的PHY,1代表High-PHY。当Slave收到这个值的时候,会把PHY_Sync值写到对应的寄存器中。
5. Dynamic Synchronization
Dynamic Synchronization为4个bit,为连续15个帧的一个动态码。由于只看Static Synchronization的话,比特流可能刚好与Static Synchronization一致,导致SoundWire总线进入假连接状态,加入Dynamic Synchronization后能更好的解决这个问题。Dynamic Synchronization的值来自于4-bit LFSR(linear feedback shift register)寄存器,其通过一个PRBS (pseudo-random binary sequence) 产生器生成出来。LFSR初始值为b’1111。
动态码的sequence如下:
6. 奇偶校验 PAR
Control Word中,存在一个奇偶校验位PAR,来检测data信号传输过程中是否出现错误。注意,奇偶校验的是data电平的高低次数,而不是逻辑的0和1。
PRA由Command Owneri经过计算后产生,并发送到别的设备进行匹配,如果设备计算出的PRA与Owner送出的PRA不一致,可能会引发中断(如果中断使能的话),并且会发送一个Command_Failed的response,让该总线上所有设备都丢弃这一帧,使得设备不会被这次错误传输所影响。
奇偶校验的窗口超过了一帧的边界,当Master修改帧结构,奇偶校验的窗口会包括上一个帧结构的部分Bitslot,和新的帧结构的部分Bitslot。下图为帧和校验窗口的关系图,注意,PAR并不是紧跟着校验窗口的,而是和奇偶校验窗口相差几个bit,多少个bit取决于你的列数,主要也是给Master计算PAR的时间。另外,校验窗口内所有的数据有需要拿来校验,包括上一帧的PAR。
下图为奇偶校验窗口的细节图。首先我们可以看到,校验窗口N只到了[44,0],此时窗口N的数据会被短暂存储起来用于计算PAR,校验窗口N+1由[44,1]开始。因此,44行的[44,1]~[44,15]都是窗口N+1的计算值,包括了窗口N的PAR本身,也是窗口N+1的计算值。
7. Response,NAK & ACK
Control Word中,存在两个bit,NAK和ACK来描述对Command的Response。
当一个设备被选中是command 的目标时,其response的NAK和ACK的组合可能如下:
• Command_Failed (NAK=1 & ACK=0):例如奇偶校验失败。
• Command_OK (NAK=0 & ACK=1):例如顺利完成读操作并返回读数据。
• Command_Ignored (NAK=0 & ACK=0):例如读了一个只写寄存器。
当一个设备没被选中是command 的目标时,其response的NAK和ACK的组合可能如下:
• Command_Failed (NAK=1 & ACK=0): 例如奇偶校验失败。
• Command_Ignored (NAK=0 & ACK=0):例如自身并不是读写操作的目标设备,或者奇偶校验没有失败。
Command Fields
1. Stream Synchronization Point (SSP)
SSP是Command Fields中的1个bit,用于设备间的传输同步。同时,当一个设备中,出现了不同的采样率,且采样率之间不是倍数关系,则需要用到SSP来使采样率和帧率同步。
2. Bus Request (BREQ)
BREQ 是Command Fields中的1个bit,Monitor通过拉起BREQ申请成为Command Owner。
3. Bus Release (BREL)
BREL 是Command Fields中的1个bit,Master通过拉起BREL允许Monitor成为Command Owner。
4. Slave Status (Slv_Stat_nn)
这个field一共是24个bit,一共包含了12个slave的状态(每个slave占用2个bit,slave0~11),这些状态包括:
• Slave 未成功连接。
• Slave 成功连接但是没有中断信息。
• Slave 成功连接并至少有1个中断需要上报。
5. Device Address (DevAddr)、Register Address (RegAddr)、Register Data (RegData)
Addr和Data,其中DevAddr 4个bit,RegAddr 16个bit,RegData 8个bit。
四、帧同步
Master 初始化
Master有时候会先发一段时间的时钟,再经过初始化,发出动态同步码和静态同步码等等,这并不妨碍slave识别和同步,因为slave总是匹配上了所有的同步码步骤之后,再进入同步状态。Master一开始发的帧是48行2列的结构,这样slave能过够更快同步上master。而且这种帧结构中,读写command占整个帧的比例最大,因此读写command的带宽会更大(同样的时间能送出更多的command),一旦枚举结束,所有slave同步了,master就可以改变帧结构来传输数据了。
Slave 同步步骤及SS_SM(Slave Synchronization State Machine)
Slave同步通过一个状态机SS_SM来实现,这个状态机体现了:
1. slave 如何与总线上的master进行同步;
2. slave 如何从总线上失去同步。
这个概念图为了简单阐述这个过程,因此同步过程只用了一种搜索算法和简单的参数去完成同步,实际上,真正的同步过程会用更高级的算法,并且使用多个参数(例如多种行和列的组合)去进行同步。同步时间的长短取决于slave自身的参数,master发送所用的参数,甚至是传送的data和command。另外,下图还包括对设备进入High-PHY mode的检测。实际上,系统会等所有的slave都具备High-PHY功能的时候,才会有可能进入High-PHY mode。
下图为SS_SM概念图:
状态描述:
State name | 描述 | 表现 |
Unattached | slave没接收到任何正确的静态同步码,所以不能正确的连接在总线上。 当前的搜索静态同步码的帧结构的列数可能是不正确的,并且行数也是未知的。 | slave不会own任何的bitslot。 slave会循环使用这些可能的列数去寻找静态同步码。保证先确定列数。 |
Column_OK | slave只接受过一次正确的静态同步码,并且不能正确的正确的连在总线上。 设定的列数可能是正确的。但是行数仍然是未知的。 | slave不会own任何的bitslot。 slave会假定这个列数是正确的,并去寻找第二次正确的静态同步码,以确定行数去初始化对应的寄存器。 |
Colume_Row_OK | slave还没接收足够的静态,动态以及PHY同步码,并且不能正确的连在总线上。 行数,列数以及High-PHY状态都可能是正确的。 | slave不会own任何的bitslot。 slave假定行数和列数都是正确的,并检查接下来15帧的静态,动态和PHY的同步码,以确定之前初始化的寄存器内容是否正确。 |
Attached | slave接受了足够多的静态,动态和PHY同步码,并且已经正确地连在了总线上。 | slave可以own bitslot来写control word或者data payload了。 |
Attached_Error_1 | slave已经attached了,但是收到当前一帧在同步码上出现错误的值 | slave可以own bitslot来写control word或者data payload了。 同时,slave会假定行数列数以及High-PHY域仍然是正确的,并检查当前一帧的剩余部分以及下一帧的静态,动态和PHY同步码,以此来确定行数列数以及High-PHY域是否正确。 |
Attached_Old_Error | slave是连在总线上的,但是上一帧的同步码有出现错误的值。 | 同上 |
转跳条件描述:
转跳条件名字 | 描述 |
Static_Sync_Missing | slave使用候选的列数进行搜索静态同步码 'b10110001,但是经过大于或者等于256个bitslot之后,仍然没找到。 |
Static_Sync_1_OK | slave使用候选的列数去搜索静态同步码 'b10110001,并且搜索成功。 |
Static_Sync_2_OK | slave在上一次成功搜索静态同步码之后,256个bigslot之内再次搜索成功。 |
Full_Sync_OK | slave用当前了的行数和列数以及寄存器值(PHY)正确的接受了所有的同步码。 |
Any_Sync_Error | slave用当前了的行数和列数以及寄存器值(PHY)接受的同步码中出现了错误。 |
PHY_OK_to_Attach | 满足下面其中一个条件: 1. SCP_SystemCtrl寄存器的High-PHY_Select域为0(Basic PHY) 2. 下列条件同时满足: a. High-PHY 的值是1 b. slave 在High-PHY模式下 c. SCP_Stat寄存器的High-PHY_NotOK域为0 |
End_of_Frame | slave继续用当前的行数和列数去检查当前一帧剩余部分的同步码,并且所有剩余的bitslot的值都是正确的,没有发生别的错误使状态机进入Unattached状态。 |
Self_Detach | slave因为某些原因自行选择下线。 |
五、系统控制(System Control)
主要介绍下SoundWire的底层功能,包括复位,时钟,data驱动冲突,PHY切换等等。
复位
SoundWire设备的复位分为3种,都会导致设备变成unattached,从而需要重新attached到总线上并且等待重新枚举,根据影响排列从小到大,3种复位分别是:
1. 软复位(Soft Reset)
软复位一般发生于设备出现同步错误的时候,当设备同步码出错误bit位出现太多了,就会出发软复位。此复位对设备影响最小,仅仅是防止设备在错误的时间往总线发送信息。当设备重新连上总线并枚举结束后,master可以读取设备的寄存器进行debug。
2. 硬复位(Hard Reset)
影响第二小的是硬复位,例如时钟停止,或者往SCP_Ctrl寄存器写ForceReset都能触发硬复位。硬复位对slave内部多个(或者全部)的状态都有影响,取决于designer如何设计。
3. Severe Reset
影响最大的是Severe Reset,例如Power_on Reset或者Bus Reset。其影响包括了硬复位所影响的部分,另外,一些自初始化之后就不会更改的部分,例如PHY output control,都会被Severe Reset所影响。
4. Bus Reset
如下图,如果设备连续接收了超过4096个逻辑1时(即2046个时钟周期),就会在第4096个逻辑1的时候触发Bus Reset。之后只要保持发送逻辑1,设备就会一直保持复位状态。
时钟
Master通过生成时钟来实现数据传输。
时钟切换
下图是SoundWire时钟切换的例子。Master可以动态在传输过程中切换时钟。在这个例子中,Master在配置Bank Switch Command之前已经配置了一系列寄存器了,当帧结束时,马上切换成需要的时钟等配置;
时钟暂停(Clock Pause)
时钟暂停指的是Master不通过任何的通知或者预警,可以在任何时候直接暂停时钟,使时钟停留在高或者低电平保持一段时间。时钟暂停是完全由Master操控的,并且会打乱slave接收帧的过程,因此时钟暂停一般发生在没有active channel的时候(例如只做ping,write和read的时候)。与下面说的时钟停止(Clock Stopping)不同在于,时钟停止可以无缝恢复传输。
时钟停止(Clock Stopping)
时钟停止在SoundWire中是一种节省功耗的行为。Master首先会发出时钟停止的命令,此时所有的slave应该支持该操作。Slave停止驱动data信号,并且忽略接下来的一帧Stopping Frame,此帧是Master用来驱动data信号来停在预设的电平。最后Master产生一个时钟下降沿表明Stopping Frame结束,然后时钟就停留在低电平处。
一个或者多个设备可以通过拉高data信号来唤醒master重新恢复clk(Wakeup request)。当Wakeup request发起时,master需要一段时间来重新启动clk。当master重新启动时钟时如果slave处于ClockStopMode0 状态,那么条件满足的时候可以无缝恢复数据传输。如果slave处于ClockStopMode1 状态,那么时钟恢复的时候slave需要重新连上总线并重新枚举。
下图是时钟停止及恢复过程时序图。Frame N包含了写命令去启动时钟停止(设置SCP_Ctrl寄存器的ClockStopNow为1),Frame N的最后一个bit是data的payload,当这个bitslot结束之后,正式进入stopping frame。在stopping frame中,master own了所有的bitslot,并且把control word的内容全部写0以保证所有slave在FrameN结束之后是一个新的attached状态。同时,master会产生payload data以确保data信号最终停留在低电平。当stopping frame结束的时候,master的data信号输出highz,让bus-keeper把data保持在低电平。
一个或者多个设备都可以通过拉高data信号来发起一个WakeUp请求。WakeUp请求需要不小于两个bitslo的长度。然后Master会拉起clk来表明这是Frame N+1的第一个bitslot结束。当时钟重新恢复时,data信号中看到Frame N+1行为是紧接着Frame N的,其data payload的操作与Frame N一致,时钟停止这段时间被看作成Frame N+1的第一个bitslot的拉长效果。
六、 命令(Command)
Command是control word的一部分,包含了以下三个操作:
• Ping:让总线上的所有slave返回状态。
• Write:Command Owner给一个或者多个设备中一个或者多个寄存器写一个8 bit 的值。
• Read:Command Owner从一个或者多个设备中一个或者多个寄存器读一个8 bit 的值。
Command Owner
任何发出帧的设备,其own opcode和其他command fields时,他就成为 command owner。在正常的操作中,command owner一般是master,例如master读或者写slave的寄存器。Monitor有时也会成为command owner,这取决于ping操作时的BREQ和BREL fields。每次command ownership的判别都发生在每一次的ping command。当发出其他command时,command owner会保持不变。如果Monitor想要变成command owner,就必须发出足够多的ping command去请求,如果想要持续成为command owner,还必须在每个ping command中都拉起BREQ。如果Master和Monitor都不是command owner,但是data收到opcode是‘b000,BREQ=0,即Master收到ping command但是Monitor不请求操作总线,那么command ownership会回到Master。
Ping Command
Ping Command是用来获取总线上slave的状态的,一般发生在枚举和配置完成的时候。PREQ域在control word中通知Command Owner slave 设备的Slave Stattus值已经更新了并等待着Ping Command来上报。
Rigister Bank Switching
寄存器分为两个Bank,都可以用来做控制payload的传输和用来做采样操作的。不同Bank之间的寄存器通过某个机制来进行无缝的修改。在任何时候,当一个bank的寄存器在控制操作时,另一个bank的寄存器可以被修改,而且不会马上影响当前帧的操作。当这个bank所有的寄存器被修改完毕时,可以通过操作去切换到这个已经修改好的bank的寄存器,在所有总线上进行传输(在帧结束时)。
一个常见的例子就是帧结构的修改。新的帧结构和老的帧结构可能大相径庭,每个data ports用的bitslot可能都不一样。如果使用单个修改寄存器的参数的方法,这样传输肯定会发生问题,bitslot会紊乱。当所有关于新帧结构的寄存器都写好之后,再通过切换的方法把新的一帧的寄存器切换上来做数据传输,这样就不会出现前面的问题。
Slave通过SCP_Stat寄存器的只读位CurrentBank来确认当前使用哪个bank。并且通过用Write Command写SCP_FrameCrtl寄存器来实现bank的切换。
CurrentBank_DPx and NextInvertBank
每一个data port都拥有自己的CurrentBank状态,称为CurrentBank_DPx。这个只影响这个data port自身的数据传输,并不会影响整个slave的传输过程,例如帧结构。
CurrentBank_DPx也是通过Wirte Command修改SCP_FrameCrtl的时候更新的。修改DPx_Port_Ctrl寄存器的NextInverBank域来修改CurrentBank_DPx的值。
Stream Synchronization Points(SSP)
Payload的传送和采样操作同时通过Data port内部的计数器通过测量bitslot的间隙来进行的。为了保证传输的正确性,Source和Destination(这里我的理解是master的DP和slave的DP,并不是指单纯的master与slave)的计数器必须时同步。SoundWire传输中有一个特别的时钟边沿,叫做SSP,在SSP中所有的计数器都应该force成0,强行同步。SSP的间隔是当前系统中所有采样间隔的整数倍,因此当SSP一旦把计数器force成0,那以后的SSP把寄存器force成0也不会影响计数器的计数结果。
Master有几个方法来声明某个特别的时钟沿是SSP,而这些特定的时钟沿也是SSP的间隔。如果master错过了某个时钟边沿来声明SSP,并不会造成多大的问题,因为所有的计数器都是同步的。SSP一般出现在帧的边界上,例如上一帧的下降沿BitSlot[MaxRow,Maxcol]和下一帧的开始BitSlot[0,0]。声明SSP的方法有:
1. 产生一个Ping Command,把SSP域置1。
2. 产生一个Write Command去更新SCP_FrameCrtl0 or 1 寄存器。
枚举过程中读取Device_Id寄存器
Master在进行正常的数据传输前,辨别和初始化总线上的Device的过程,叫做枚举过程。每个Slave存在6个具有特别功能的寄存器来支持Master的枚举过程。枚举过程中,假定这连续的6个寄存器(48bit)组成的值在系统中是唯一的,就算总线上存在同一个component例化了多个instance,他们SCP_DevId_0寄存器中的UniqueId域都应该是唯一的。
当Slave刚连上总线,都被当作第0号设备(Device Number 0),然后master会去读取其第一个Device_Id寄存器(SCP_DevId_0)。在整个读取过程中,参与这个过程的slave数量会越来越少直到剩下一个。然后Master会赋予slave一个新的并且唯一的device number,范围在1到11之间,最后再去读取最后一个还停留在0号设备的slave的寄存器,并赋值新的device number。当所有的slave都被赋予了一个新的device number之后,Master发送ping command发现slave 0的Slave Stat是Not_Present,或者发送read command给0号设备读取Dev_ID_0返回的respone是Command_Ignored,就结束枚举过程。每个slave都会参与枚举过程,解析data总线送来的数据。如果由于别的slave往data信号上输入逻辑1,覆盖了原来的逻辑0,此slave检测到了总线冲突,就会停止参与枚举过程,停止own bitslot,即使接收到了总线上的针对自身的Read Command,也会返回Command_Ignored。
七、寄存器
寄存器访问机制
设备寄存器的读写操作可以通过以下两种访问机制进行:
• Command Owner使用Read or Write Command
• 发起设备(一般是master)在BPT流(Bulk Payload Transport Stream)中把读写操作通过批量寄存器访问协议(Bulk Register Access Protocol)送到Slave的Data Port 0上。
普通的读写命令使用于所有的Slave,用这个方法每帧只能访问一个字节(byte)。由于普通读写command与帧同步,是control word的一部分,因此需要设备间通信正常才能进行读写操作。而使用批量寄存器访问协议(Bulk Register Access Protocol)的读写操作会更加高级,这个方法根据根据不同的payload配置,在一帧之内可以操作1到502个字节。同样因为这个方法比较复杂,所以其对slave所支持的功能来说,是个可选项,一些比较小的简单的slave并不支持这种读写方法。
Results and Responses
当设备收到了读或者写访问时,会产生3种Result,分别是Ignored,OK和Fail。当采用读写command去访问寄存器时,Result是control word中Response的一部分。当采用BRA访问寄存器时,Result将会保存在BRA_FooterResponse域中。
访问 Implementation-Defined 寄存器
比较典型的设计一般会把SounWire总线从部分或者全部的某种逻辑中分离开来,这些逻辑是来实现应用级的功能的。Implementation-Defined 寄存器就是来实现控制这些功能的,有些功能是针对data port的,有些是针对整个设备的。
Slave寄存器地址空间
寄存器的寻址空间是4GB,32bit地址。当采用BAR访问寄存器的时候,寄存器地址会存在于BRA Header(也是一个寄存器)。当采用command去读写寄存器的时候,地址由command中的16bit的RegAddr和可选的分页寄存器(optional paging register)的内容组合而成。
PS:command方式读写寄存器只能访问4GB中的前2GB,但是BAR可以访问全部4GB。(下图的地址只有31bit,所以是2GB)
每个设备都有自身的4GB寻址空间,前8k在spec中可以找到定义,前1GB剩下的部分是给Implementation-Defined 寄存器用的。第二个1GB中,前128MB规划给SDCA(SoundWire Device Clase of Audio Specification)第二个1GB剩下部分以及剩下的2BF部分都是保留的。
开头的8KB,前面的一半分为16个256byte(16*256=4096)的block,每一个block都与对应的Port关联。接下来2KB是用作MIPI的扩展方案,再接下来2KB是保留的。
Port 0 作为control port,用于设备总线的控制和状态操作,并且也用作BAR。Port 1~14对应的是各个Data Port,并且用于payload的控制和状态操作。Port15 用于对所有Data Port(1~14)的写操作。
Register Banks
一部分寄存器按照对应的Port分成一块一块,称为Bank。不同的Bank内的寄存器功能是相同的,只有选中的一个Bank可以控制总线操作。另外一部分寄存器并不像Bank寄存器一样有两套,但是其在两个Bank之间是通用的,并且一直控制总线操作,不受当前Bank的影响。Bank的功能是简化对多个control seting进行更改,并使这些更改同时发生。这种同时更改的操作称为Bank Switching,一般由Command Owner发起(一般是Master)。
Dual_Ranked 寄存器
要完成寄存器的bank的切换,即多个寄存器同时更新的操作,就需要用到Dual_Ranked寄存器。Dual_Ranked寄存器机制不是所有寄存器都需要,其一般用于SDCA,并且可以用户自己定义哪些寄存器用Dual_Ranked寄存器。(待续)
八、Payload
这个章节主要介绍SoundWire data ports传输的payload data,尤其是音频data。
概述
Soundwire总线的目的就是传送payload stream,在一般的系统中,多路的stream都是通路复用的。一般的payload stream是一个采样值的序列,例如音频payload。任何设备的任何一个data port都可以成为payload stream的source或者sink。一般一个data port发出一个stream,不过这个stream可以被多个data port接收。除了control word以外所有bitslot都算左payload data。即使用了特殊的方法把所有的stream混在一起再发送,但是从data port来看,就是点对点的链接,两个不同的sink data port在同一帧中能接收到各自的payload。
Bulk Payload Transport (BPT)是一种特殊的payload stream,可用于传输大量的寄存器配置,比以soundwire control word的方式配置slave更有效率。BPT一般是由Control Port 0来发送。
一般的设备中,data port编号从1到最大14。这些编号仅仅用于辨别寄存器对data port的控制。同样的,每个data port中channel的编号也是从1到最大8,每一个channel传输一个stream。把多个channel放到一个port里面的意义是,这些channel可以一系列相同的传输参数,包括采样率,采样位宽等等。
术语
payload采样
采样事件是由data port产生的,同步于SoundWire的帧中的bitslot,其频率是由payload传输的参数控制的。SoundWire spec并没有定义采样事件应该什么时候发发生,只要能够正常传输音频信号即可。
典型的设计中,采样时钟是有payload传输的参数(采样间隔)决定的,soundwire master生成的clk一般会被用作采样时钟的参考时钟。
两次采样事件发生的间隔时间叫做采样间隔(Sample Interval),其基于SoundWire clk包含了部分bitslot。一个data port的采样间隔与与之通信的data port一致,但是和其他data port不同。通常SoundWire的帧率是所有采样间隔的整数分之一,因此每一帧里面都包含整数个采样间隔。但是采样率也可以设置成和帧率没有整数倍关系。采样间隔之间包含的一系列bitslot,称为采样窗口(Sample Window)。
下图是采样间隔的例子,采样间隔仅仅是几个bitslot,可以越行,不一定需要和行对齐。
为了增加传输效率,几个采样事件的payload data会被组成一起。1到4个采样间隔合成一组,称为payload data interval,其包含的bitslots成为payload data window。
下图是payload data window的例子,此例子中,BlockGroupCount等于1,因此采样间隔和payload data interval相等,采样窗口和payload data window相等。在这个例子中,采样间隔是200 bitslots,而帧结构是50*16=800个bitslots,采样事件发生在[0,0],[12,8],[25,0]和[37,8]位的bitslot上。
Payload Data
Payload Channel Sample是channel的一个1到64的值,一般来说,其相当于一个channel中的音频数据。Payload Channel Sample可能会包含一些不代表真正音频信号的padding,这些padding可用于简化data port传输机制。Payload Channel Sample的值由SampleWordLength决定。
Payload Data Container是channel传输data的基本单位。在一个普通的payload传输中,一个Payload Data Container包含了Payload Channel Sample的bit。Payload Data Container的值由ContainerWordLength决定。
Payload Data Block是data port传输的基本单位,data port操作以下三种data packing的其中一种,因此Payload Data Block也是一样:
• 一组Payload Data Container,每个Payload Data Container都对应一个channel,有时候被称为音频的“采样帧”。
• 2、3或4组Payload Data Container,每一组包含一个Payload Data Container,对应一个channel。
• 一组Payload Data Sub-Block,每一个sub-block包含一个Payload Data Container,对应一个channel。
Payload Data Block的值由ContainerWordLength,BlockPackingMod, BlockGroupCount 和 NumChannels决定。下图展示了4种Payload Data Block的例子:
1. 第一个例子展示了一个Payload Data Container中,是先传MSB再传LSB
2. 这个例子中展示了,当多个channel使能的时候,编号小的channel先传输,编号大的后传输
3. 这个例子展示了Payload Data Block也可以很小
4. 这个例子展示了如果BlockGroupCount大于1,则Payload Data Block会在一个采样间隔内把所有bit发出去
下面这些例子说明了BlockPackingMode对Payload Data Block的影响:当BlockPackingMode是Block-per-Port的时候,每一个Payload Data Block囊括了一组Payload Channel Samples,每个都对应其channel;当BlockPackingMode是Block-per-Channel的时候,Payload Data Block分成了好几个Payload Data Sub-Block,每个sub-block都包含了一个Payload Channel Samples,每个Payload Channel Samples都对应其channel,因此每一个Payload Data Sub-Block包含了一段音频采样帧,而且Payload Data Sub-Block也是先传输编号小的。
Payload Transport
传输子帧(transport sub-frame)是一个抽象概念,data port用它来区分哪个bitslot属于哪个stream。一个传输子帧是SoundWire帧的一个列的子集,其是一个二维数组中包括了可能要传输的的bitslot的长方形边界。
下图是一个传输子帧的例子。从水平方向上看,传输子帧和行数从HStart开始,到HStop结束,他的长度等于HWidth。从垂直方向上看,传输子帧的跨度可以跨越整个SoundWire帧,从第0行到最后一行。一般来说,传输子帧包括的bitslot是stream用到的bitslot的超集,data port不会用所有子帧的bitslot来传输data。一般的data port配置会把几个data port配置到同一个子帧,然后使用的时候会微调一些offset参数使得这几个data block不会相互覆盖。
下图是简单的data port使用传输子帧的图,可以看出,只有一个data port的时候,传输子帧可以等于整个SoundWire帧。
Payload传输窗口(Payload Transport Window)也是一个data port用它来区分哪个bitslot属于哪个stream的抽象概念。Payload传输窗口是Payload Data Window的一个子集,是传输子帧与Payload Data Window的相交部分。当Payload Data Window比SoundWire帧的范围要大,Payload 传输窗口也可以超越帧的边界,包含了别的帧的bitslot。
下图是一个Payload传输窗口的示意图,可以看出,Payload传输窗口可以适配正方形和非正方形的Payload Data Window。Payload传输窗口可以不是长方形的。
下图展示了Payload传输窗口与在相同的采样间隔下,与不同的BlockGroupCount之间的关系。
Payload Positioning
Payload 传输窗口是通过Block Offset来控制的,其有助于在给定的列数内多个payload stream分享数据通道。
Payload Positioning in Block-per-Port Mode
Block Offset是用来辨别在Payload Transport Window里面多少bitslot是不用的,其控制的是Payload Transport Window中第一个bitslot到Payload Data Block中第一个bitslot的offset。然后Payload Data Block会填充Payload Transport Window中需要用到的bitslot,如果需要的话,Payload Data Block在Payload Transport Window中的Block offset还能超过两行(但是不会超过Payload Transport Window的范围)。下图是一个使用Block Offset的展示。
下图展示的是Payload Transport Window的大小是16个bitslot,每个Payload Transport Window刚好是帧的一行。这个例子展示了3个不同的Block Offset在Payload Data Block只有4个bit的情况。
Payload Positioning in Block-per-Channel Mode
Block Offset是用来辨别在Payload Transport Window里面多少bitslot是不用的,其控制的是Payload Transport Window中第一个bitslot到Payload Data Sub-Block中第一个bitslot的offset。然后Payload Data Sub-Block会填充Payload Transport Window中需要用到的bitslot,如果需要的话,Payload Data Sub-Block在Payload Transport Window中的Block offset还能超过两行(但是不会超过Payload Transport Window的范围)。下图是一个使用Block Offset和Sub-Block Offset的展示。
Payload Stream 的复用例子
如果两个payload stream的采样率是相同的,那么他们可以共享一个Payload Data Window。如果这些stream来自同一个data port,并且设置的相同的传输参数(传输子帧),则他们在Payload Transport Window中分享相同的bitslot(意思是接收端会把一个输入识别成多个stream?)。
两个不同的bitslot之间可以使用Block Offset来区分他们各自的Payload Data Block,使得他们在相同的Payload Transport Window中不会互相覆盖。
下面这个例子中,data portA和B拥有相同的采样率和Transport Sub-Block配置,所以他们共用一个Payload Transport Window,他们通过Block Offset来分开。
如果一个Payload Stream有好几个channel,并且是用Block-per-Channel的方式传输来分割几个Payload Data Sub-Block的话,其跟Block-per-Port生成的Data Block(单channel)很相似,但是其采样率高出NumChannels倍(或者说采样间隔缩小了NumChannels倍)。与Block Offset不同,Sub-Block Offset控制的是Sub-Block的offset,因此在多stream复用中可以提供更大的灵活性。入上图,Data PortC有2个channel并且采样率是单channel的Data PortB的一半,Data PortC采用的是Block-per-Channel模式。(如何理解说采样率高出了NumChannels倍,Data PortC不是Data PortB采样率的一半吗?)
当一个Stream的采样率是另一个Stream的整数分之一,则他们的采样窗口是相同的。后一个stream可通过配置合适的GroupCount来使得他们两个的Payload Data Window相同。因此,如果这些Stream的Data Port配置了相同的Transport Sub-Frame参数,那这两个Data Port的Payload Data Window将会完全一样。通过配置Block Offset来使得两个Data Port的数据完全不会被对方覆盖。
如下面例子,stream z和stream y的采样率分别是stream x的2倍和4倍,通过配置参数使得这几个这3个stream使用同一个Payload Data Window和Paylod Transport Window(帧的每一行)。他们就是通过Block Offset来分开的。
Port Flow Modes
Payload Stream的传输方式有4种,由DPN_PortCtrol 的PortFlowMode field决定。
Normal Payload 传输
其中一种就是Normal Payload 传输。与上文描述的传输方式一致,在每一个SoundWire帧中通过Payload Data Container来传输Payload Data Sample,Payload Data Sample生成的频率与SoundWire帧一致。
Flow-Controlled Payload 传输 (Asynchronous Payload Streams)
剩下3种传输方式都称为Flow-Controlled Payload 传输 (Tx-Controlled, Rx-Controlled 和 Full-Asynchronous modes)。Payload Data Sample生成的频率是不同的,可能比SoundWire帧频率要低一些。每个SoundWire帧可能包含多个Payload Data Container,第一个Payload Data Container包含一个flow-control bit来表明当前这个Payload Channel Samples是不是有效的。Payload Channel Samples的传输频率可以被Sink Data Port,Source Data Port给限制,只有当Sink Data Port和Source Data Port都ready时才能传输Payload Channel Samples。
在BlockPackingMode 是 Block-per-Channel,则Payload Data Container中,index最低的Container包含flow-control bit。
当使用Flow-Controlled Payload 传输时,不会使用Sample Grouping,会忽略BlockGroupControl这个域。
下图是4种传输方式的例子:
Port Flow 方向
Port 的方向有发送端和接收段(Source and Sink)。固定的Port只能操作一个方向。但是有些port的方向是可以配置的,但是其在active的时候不能改变方向。
Port Data Mode
Data Port 可以把Payload Stream 送到外部的数据口,但是也可以把data送到内部的检测电路,例如在BIST模式下。下面说的3种test mode中,他们在source和sink data port中都有相同的测试数据产生器,他们可以用这个来验证传输数据的正确性。
Normal Data Mode
在Normal Data Mode中,Source Data Port接收的信号是来自于外部数据连接的bitslot,这些bitslot是由寄存器控制的。而Sink Data Port接受的bitslot是来自外部数据连接的。SoundWire Payload 传输机制不会解码数据,也不会验证这些数据是否是从外部连接来的。在Source Data Port中,这个传输机制会通过特定寄存器在soundwire总线上生成数据。同样在Sink Data Port中,会通过特定寄存器在soundwire总线上接收数据。
Static_1 Test Mode
使用了Logic1的静态数据去验证数据连接的正确性,Sink Data Port使用Static_1 Test Mode来验证与Source Data Port的连接是否正确。
Static_0 Test Mode
使用了Logic0的静态数据去验证数据连接的正确性,Sink Data Port使用Static_1 Test Mode来验证与Source Data Port的连接是否正确。
PRBS Test Mode
第三种test mode是使用Source Data Port通过伪随机码发生器产生数据,然后把data传输到Sink Data Port,Sink Data Port再通过相同的数据产生器来检查接收数据的正确性。伪随机码生成器如下图,它可以循环产生255个data,其有两种方式来生成。
在此过程中,Sink Data Port不一定能够同步的开始从Source Data Port中接收随机码,有以下两种情况:
1. 随机码的初始值由寄存器来配置,所以如果Data Port同步的开始错误检查,则会在通道激活的时候,验证通道送来的每一个bit。在这种情况下,设备会第一时间清除Test Fail中断状态,并且在同步传输data之前enable中断。
2. 配置错误检查是自同步的,所以如果Data Port没有同步开始,这个错误检查会在接收最多8个正确的bit之后enable起来。在这种情况下,设备会先开始Source和Sink Data Port之间的数据传输,并在enable错误中断之前先把Test Fail中断清除掉。
Channel的准备与使能
激活channel
Data Port的每一个channel都有两个状态:Idle和Actived,由DPN_ChannelEn_Register控制。Channel只有在Active之前准备(prepared)好,才能传送有效的数据。
Channel的准备
Data Port需要在发送或者接收数据前做一些准备工作,例如在数据通道上输入足够的采样数据来稳定滤波器的输出。同样,在要结束发送和接收数据的时候也要做一下去准备工作,例如关闭功放的电源等。Spec里面定义了一些通=通用的机制来控制这个准备和去准备过程,来表明那些步骤是需要在数据传输之前做好。
这些操作被称为Channel Prepare State Machne(CP_SM,如下图),每一个channel都有自己的CP_SM,虽然所有channel的CP_SM的某些基础条件是共享的(例如PLL参数),但是后续的channel准备过程是瞬时完成的。
Data Port游泳一个Port Ready中断,用来通知软件准备和去准备工作是否已经完成,而不需要去配置DPN_PrepareStatus寄存器。单个中断会包含Data Port中所有channel的准备和去准备的状态。
Channel准备的操作如下: