这段时间一直在做USB Audio Device(UAC)
设备的开发工作。由于UAC采用的是isochronous endpoint
来传输数据,对时钟的要求较高。但无奈我们的嵌入式平台的时钟并不准,数据同步就成了问题。经过研究,发现只能使用异步模式来解决这个问题。
所谓异步模式,就是建立一个feedback endpoint在一个固定的时间间隔反馈本地时钟给host, 从而使得host端能够实时的了解client端的时钟变化,调节数据包的长度,从而避免接收或者发送缓冲溢出。
USB 2.0 spec在5.12.4.2中明确的定义了如何提供feedback给host, 个人觉得写得有点复杂,特总结如下:
1. Feedback endpoint
数据长度为3字节,发送间隔由bRefresh
决定。
2. Fm = Fs * 2^P
, Fm
是本地的时钟频率,Fs
是采样频率。
3. Tmeas=2^K/2^P=2^(K-P)
, Tmeas
是测量时间, 对于full speed, K= 10, 对于high speed, K=13
4. 在每Tmeas
frame/subframe时间间隔,把本地的clock数写入feedback endpoint。
上面的一大段看起来很复杂,其实基本的思想很简单。不就是时钟不同步嘛,要想让大家同步,怎么办呢?比如说采样率是48000,如果时钟同步,那么1s的时间内,就应该有48000个sample。如果不同步,那么就测量1s, 把1s内的实际sample数返回给host端就可以了。上面的公式实际要表达的就是这个意思。至于要注意的是返回的格式,spec上面说是对于full speed, 数据格式是10.14,对于high speed, 数据格式是16.16。如果你的UAC设备是1.0 version,那么就算是你把它定义成一个high speed的设备,返回数据格式还是10.14的。
例如:
48000 采样率 –> feedback (48 * 2^14) = 0xc0000
47000 采样率 –> feedback (47 * 2^14) = 0xbc000