最近想玩玩LINUX,于是双系统装了一个Ubuntu13.04。
在新系统下用着都还好,不过我自己DIY的USB DAC出了问题。在WIN7下能正常工作,但是在Ubuntu下就爆音不断,很明显是音频数据流断流引起的。
这说明stm32上的固件与Ubuntu的USB AUdio驱动程序不太兼容,于是开始检查。在这个过程中,学到不少调试方法,下面详细描述下调试的过程:
1. 第一步需要确定USB DAC已经成功连接到PC,这里使用dmesg命令查看内核的信息。
USB DAC连接PC,输入命令:
>> dmesg | tail
[ 2148.890771] usb 1-1.2: Product: Ilmen Audio [ 2148.890774] usb 1.2: Manufacturer: IlmenTech [ 2148.890778] usb 1.2: SerialNumber: 5CDC856933 [ 2150.327668] usb 1.2: USB disconnect,device number 83 [ 2151.785785] usb 1.2: new full-speed USB device number 84 using ehci-pci [ 2151.880680] usb 1.2: New USB device found,idVendor=0483,idProduct=5730 [ 2151.880687] usb 1.2: New USB device strings: Mfr=1,Product=2,SerialNumber=3 [ 2151.880692] usb 2151.880696] usb 2151.880699] usb 1.2: SerialNumber: 5CDC856933
可以看到设备的一些信息,USB设备已经成功的连接到PC。(由于最初我的USB配置描述符有BUG,所以可以从内核的输出信息里看到USB没有枚举成功,以及出错的原因)
2.第二步是查看这个USB设备的具体信息,这里用到命令lsusb。
>> lsusb
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 003: ID 1366:0101 SEGGER J-Link ARM Bus 004: ID 0483:5730 SGS Thomson Microelectronics Bus 003: ID 046d:c52f Logitech,Inc. Wireless Mouse M305 Bus 004: ID 064e:f207 Suyin Corp.
可以看到这个设备在Bus 001下,Device为004;在知道这两个地址后,可以用lsusb命令查看更多该设备的信息。
于是输入>> lsusb -D /dev/bus/usb/001/004
Device: ID 5730 SGS Thomson Microelectronics Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x0483 SGS Thomson Microelectronics idProduct 0x5730 bcdDevice 2.00 iManufacturer 1 iProduct 2 iSerial 3 bNumConfigurations 1
......
命令行则会列出设备的描述符,由于很长,所以之列出前面几行信息。
http://www.linuxnix.com/2013/05/find-usb-device-details-in-linuxunix-using-lsusb-command.html这个帖子介绍了lsusb的基本用法,可以参考。
3. USB设备信息有了,接下来看看系统音频设备列表里的情况。
查看当前可用的音频设备可以通过命令>> aplay -l
**** PLAYBACK 硬體裝置清單 **** card 0: MID [HDA Intel MID],device 0: ALC272 Analog [ALC272 Analog] 子设备: 1/1 子设备 #0: subdevice #0 card 1: ALC272 Digital [ALC272 Digital] 子设备: 1: Audio [Ilmen Audio],128)">0: USB Audio [USB Audio] 子设备: 0/2: Generic [HD-Audio Generic],128)">3: HDMI 0 [HDMI 0] 子设备: 0
目录/proc/asound/下有各种音频设备,例如我的USB DAC就在/proc/asound/card1/文件夹下,这里可以看到很多音频设备的信息。
音频设备的参数 >> cat /proc/asound/card1/pcm0p/sub0/hw_params
access: MMAP_INTERLEAVED format: S16_LE subformat: STD channels: 2 rate: 44100 (44100/1) period_size: 1024 buffer_size: 16384
如果没有播放声音(无音频流)
IlmenTech Ilmen Audio at usb-0000:00:1a.0-1.2,full speed : USB Audio Playback: Status: Stop Interface 1 Altset 1 Format: S16_LE Channels: 2 Endpoint: 1 OUT (ASYNC) Rates: 44100
再往上看,反馈(feedback)的格式是10.14,这在USB 2.0协议里有详细说明。当前反馈的采样率是43640 Hz(会变化),下面那个44100是此设备支持的采样率。
上面这是我成功解决问题后打印出的信息,在USB DAC工作不正常时(断流),可以看到第一个Moment freq这一项的参数十分接近48000 Hz且不会变动,这是不正常的。
在google了一天也没找到原因,最后无意间将feedback的范围从 44.1Khz +- 5Khz 减小到44.1Khz +- 1Khz才工作正常。
可见Ubuntu与WIN7的底层音频驱动有不同,由于没看过具体代码,所也目前也只能猜测:当我反馈的采样率值超过当前设备的“额定采样率”44.1Khz过多后,就导致了当前采样率“卡”在了某一固定值,不知道这算不算一个BUG。
有关ALSA的东西可以在这里查:http://www.alsa-project.org/main/index.php/Asoundrc
4.最后再提一个linux下调试USB十分方便的工具:usbmon
这个USB的抓包工具linux自带,已经编译进内核。
具体使用方法可以参考http://www.jb51.cc/article/p-owjrwpja-vw.html
不过抓到的数据看起来很不直观, 例如下面我是一小段用usbmon抓到信息:
ead46c00 3346920735 C Zi:1:003:2 0:16:954:0 1 3 4 = f0e80b00 ead46c00 3346920736 S Zi:2 -115:954 1 -18:4 < eddf8600 3346928822 C Zo:955:8 188 188:192 380:568:760:1524 > eddf8600 3346928836 S Zo:955 8 -188 -192 -572:1524 = a503c8fd 7703c6fd 3f03c3fd 0803c3fd d102c6fd 9102ccfd 5702d4fd 1602dafd ea4cbc00 3346936710 C Zo:963:1524 > ea4cbc00 3346936723 S Zo:963 1524 = 08fbf9fa 22fbe5fa 40fbd2fa 5efbc1fa 83fbb9fa abfbb5fa d4fbaffa 03fcb1fa ead46e40 3346936729 C Zi:970:4 = f0e80b00
109 Here is the list of words,from left to right: 110 111 - URB Tag. This is used to identify URBs,and is normally an in-kernel address 112 of the URB structure in hexadecimal,but can be a sequence number or any 113 other unique string,within reason. 114 115 - Timestamp in microseconds,a decimal number. The timestamp's resolution 116 depends on available clock,and so it can be much worse than a microsecond 117 (if the implementation uses jiffies,255)">forexample). 118 119 - Event Type. This type refers to the format of the event,not URB type. 120 Available types are: S - submission,C - callback,E - submission error. 121 122 - "Address" word (formerly a pipe"). It consists of four fields,separated by 123 colons: URB type and direction,Bus number,Device address,Endpoint number. 124 Type and direction are encoded with two bytes in the following manner: 125 Ci Co Control input and output 126 Zi Zo Isochronous input and output 127 Ii Io Interrupt input and output 128 Bi Bo Bulk input and output 129 Bus number,and Endpoint are decimal numbers,but they may 130 have leading zeros,255)">for the sake of human readers. 131 132 - URB Status word. This is either a letter,or several numbers separated 133 by colons: URB status,interval,start frame,and error count. Unlike the 134 address" word,all fields save the status are optional. Interval is printed 135 only for interrupt and isochronous URBs. Start frame is printed only for 136 isochronous URBs. Error count for isochronous callback 137 events. 138 139 The status field is a decimal number,sometimes negative,which represents 140 a status" field of the URB. This field makes no sense for submissions,but 141 is present anyway to help scripts with parsing. When an error occurs,the 142 field contains the error code. 143 144 In case of a submission of a Control packet,255)">this field contains a Setup Tag 145 instead of an group of numbers. It is easy to tell whether the Setup Tag is 146 present because it is never a number. Thus if scripts find a set of numbers 147 in this word,they proceed to read Data Length (except for isochronous URBs). 148 If they find something else,like a letter,they read the setup packet before 149 reading the Data Length or isochronous descriptors. 150 151 - Setup packet,255)">if present,consists of 5 words: one of each for bmRequestType,152 bRequest,wValue,wIndex,wLength,255)">as specified by the USB Specification 2.0. 153 These words are safe to decode if Setup Tag was s'. Otherwise,the setup 154 packet was present,but not captured,and the fields contain filler. 155 156 - Number of isochronous frame descriptors and descriptors themselves. 157 If an Isochronous transfer event has a set of descriptors,a total number 158 of them in an URB is printed first,then a word per descriptor,up to a 159 total of 5. The word consists of 3 colon-separated decimal numbers 160 status,offset,and length respectively. For submissions,initial length 161 is reported. For callbacks,actual length is reported. 162 163 - Data Length. For submissions,255)">this is the requested length. For callbacks,128)">164 is the actual length. 165 166 - Data tag. The usbmon may not always capture data,even if length is nonzero. 167 The data words are present only if this tag is ='. 168 169 - Data words follow,255)">in big endian hexadecimal format. Notice that they are 170 not machine words,but really just a byte stream split into words to make 171 it easier to read. Thus,the last word may contain from one to four bytes. 172 The length of collected data is limited and can be less than the data length 173 reported in the Data Length word. In the case of an Isochronous input (Zi) 174 completion where the received data is sparse in the buffer,the length of 175 the collected data can be greater than the Data Length value (because Data 176 Length counts only the bytes that were received whereas the Data words 177 contain the entire transfer buffer).
ead46c00 1524 = a503c8fd 7703c6fd 3f03c3fd 0803c3fd d102c6fd 9102ccfd 5702d4fd 1602dafd
第一行的 “ead46c00” 就是上面说明里提到的URB Tag; "3346920735" 是时间戳,以微秒为单位,这个可以从连续的两个feedback验证,
...... ead46c00 4 = f0e80b00 ...... ead46e40 4 = f0e80b00
......
两个包的时间戳之差约为16000,而我的feedback端点的refresh间隔的确是16ms为周期。
时间戳之后的 C 代表[feedback]事件类型;在这之后是 address项,它由4个部分组成,以符号:隔开,Zi表示同步In端点,1:003代表bus1下的003号设备,2表示该端点号。
接下来是“URB Status word”, 包括"URB status,and error count"。
之后是“Number of isochronous frame descriptors and descriptors themselves“,这部分首先是一个数代表frame descriptor的个数,接下来以空格为间隔,列出每个frame descriptor的信息,此信息有3个部分“status,and length”,以 : 符号隔开。可以看到,第一行只有一个frame descriptor,数据长度为3。
最后是数据长度, 紧跟着是 > < 或 =, 然后就是部分的传输数据了。
from:http://www.cnblogs.com/Ilmen/archive/2013/11/30/3451628.html