文章来自一口linux博客(瑞芯微-I2S | 音频驱动调试基本命令和工具-基于rk3568_rk3568 i2s-CSDN博客) ,这里拿来做笔记使用
I2S-音频基础
1. 音频常用术语
名称 | 含义 |
---|---|
ADC(Analog to Digit Conversion) | 模拟信号转换为数字信号 |
AEC(Acoustic Echo Cancellor) | 回声消除 |
AGC(Automatic Gain Control) | 自动增益补偿,调整MIC收音量 |
ALSA(Advanced Linux Sound Architecture) | 高级Linux声音架构 |
ANS(Automatic Noise Suppression) | 背景噪音抑制,ANS可探测出背景固定频率的杂音并消除背景噪音 |
BCK(Bit Clock Line) | 位时钟,对应数字音频的每一位数据。标准称为SCK(Serial Clock),串行时钟。SCK=2x采样频率x采样位数 |
Codec | Coder/Decoder |
DAC(Digit to Analog Conversion) | 数字信号转换为模拟信号 |
DAI(Digital Audio Interface) | 数字音频接口 |
DAPM(Dynamic Audio Power Management) | 动态电源管理,DAPM可使基于linux的移动设备上的音频子系统,在任何时候都工作在最小功耗状态 |
DRC(Dynamic Range Control) | 动态压缩,将音频输出控制在一定范围内 |
DSP | Digital Signal Processor |
EQ(Equaliser) | 均衡器,通过对声音某一个或多个频段进行增益或衰减,达到调整音色的目的 |
I2S(Inter-IC Sound) | IC间传输数字音频资料的一种接口标准,采用序列的方式传输2组(左右声道),Codec与CPU间音频的通信协议/接口/总线 |
LRCK(Left-Right Clock) | 帧时钟,用于切换左右声道数据,0:左声道;1:右声道。标准称为WS(World Select),声道选择;或称为FS(Frame Sync),帧同步;LRCK的频率=采样频率 |
MCLK(Master Clock) | 主时钟,一般MCLK=256*LRCK。不是I2S标准中的一部分,主要用来同步模拟/数字转换器的内部操作 |
Mixer | 混音器,将来自不同通道的几种音频模拟信号混合成一种模拟信号 |
Mono | 单声道 |
Mute | 消音,屏蔽信号通道 |
OSS(Open Sound System) | 开放声音系统,老的Linux音频体系结构,被ASLA取代并兼容 |
PCM(Pulse Code Modulation) | 脉冲编码调制,一种从音频模拟信号转换成数字信号的技术,区别于PCM音频通信协议;I2S是PCM的子集 |
ramp | 逐步增加或减少音量等级,避免声音急速变化,用于暂停或恢复音乐 |
SSI(Serial Sound Interface) | |
Stereo | 双声道 |
TDM(Time Division Multiplexing) | 时分复用。I2S最多只能传2声道数据,TDM最多支持16通道 |
2. Pcm (playback 、capture)
PCM 是英文 Pulse-code modulation 的缩写,中文译名是脉冲编码调制。PCM就是要把声音从模拟转换成数字信号的一种技术,简单的来说就是利用一个固定的频率对模拟信号进行采样,采样后的信号的幅值按一定的采样精度进行量化,量化后的数值被连续地输出、传输、处理或记录到存储介质中。
PCM 信号的两个重要指标是采样频率
和量化精度
。
通常,播放音乐时,用程序从存储介质中读取音频数据(MP3、WMA、AAC…),经过解码后,最终送到音频驱动程序中的就是PCM数据,反过来,在录音时,音频驱动不停地把采样所得的PCM数据送回给应用程序,由应用程序完成压缩、存储等任务。所以,音频驱动的两大核心任务就是:
-
playback
如何把用户空间的应用程序发过来的PCM数据,转化为人耳可以辨别的模拟音频;
-
capture
把mic拾取到得模拟信号,经过采样、量化,转换为PCM信号送回给用户空间的应用程序。
3. 声音要素
声音三要素 - 音调、响度、音色
-
1、音调 “刺耳、低沉”,这其实是我们对声音高低的感觉描述,这一特征我们称之为音调。
在物理定义上,声音是物体振动(比如我们的声带)产生的波,而音调由发声体振动的频率决定,频率越高(振动越快)则音调越高,听起来就越“刺耳”,反之音调越低、听起来就越低沉。
我们声带的振动频率,约在100Hz~10KHz之间,基本对应于常说的男低音至女高音的频率。
而我们耳朵的听力范围仅限于频率20Hz ~ 20KHz,低于或者高于这个频率范围的声音,分别被称为次声波(<20Hz)和超声波(>20KHz),无法被人耳感知。不难发现,虽然人耳的感知范围有限,但人类的发声频率完全包含于人耳的感知范围之内,这意味着任何人说的话,总能被耳朵捕捉到,每个人都有发声的权力,也总有一双耳朵能倾听到你的声音。
-
2、响度 “响亮、微弱”,是我们对声音强弱的感觉描述,这种特征我们称之为响度。响度由发声体振动的幅度决定,当传播的距离相同时,振动幅度越大、则响度越大;相反,当振幅一定时,传播距离越远,响度越小,就是我们常说的“距离太远了,听不见”的原因。
-
3、音色 “风声、雨声、人声”,是我们对各种音调、各种响度声音的综合感受,这种特征我们称之为“音色”。音色是一种“感官属性”,我们利用这种“感官属性”,能区分发声的物体,发声的状态,还能评价听感上的优劣,比如“钢琴声、二胡声”,比如“只闻其声,如见其人”,比如“悦耳、动听”等等。那么音色是怎么“产生”的,又由什么“决定”呢?前面我们了解到,声音是由物体振动产生的波,而物体整体振动发出的只是基音,其各部分还有复合的振动,这些复合的振动也会发出声音并形成泛音,基音+泛音的不同组合就产生了多样化的音色,声音世界才变得丰富多彩起来。我们一般认为音色由发声体的材质决定。
4. 声音采样-ADC/DAC
处理器要想“听到”外界的声音必须要把外界的声音转化为自己能够理解的“语言”,处理器能理解的就是 0 和 1,也就是二进制数据。
所以我们需要先把外界的声音转换为处理器能理解的 0 和 1,在信号处理领域,外界的声音是模拟信号,处理器能理解的是数字信号,因 此这里就涉及到一个模拟信号转换为数字信号的过程,而完成这个功能的就是 ADC 芯片。
1)采样
以一定采样率,在时间轴上对模拟信号进行数字化。
首先,我们沿着时间轴,按照固定的时间间隔 T(假设 T=0.1s),依次取多个点(如图中 1~10 所对应波上的点)。
此时 T 称为取样周期,T 的倒数为本次取样的采样率(f=1/T=10Hz),f 即表示每秒钟进行采样的次数,单位为赫兹(Hz)。显然,采样率越高、单位时间的采样点越多,就能越好的表示原波形(如果高频率、密集地采集无数个点,就相当于完整地记录了原波形)。
2)量化
以一定精度,在幅度轴上对模拟信号进行数字化。
完成采样后,我们接下来进行音频数字化的第二步,量化。采样是在时间轴上对音频信号进行数字化,得到多个采样点;而量化,则是在幅度方向上进行数字化,得到每个采样点的幅度值。
如下图所示,我们设定纵轴的坐标取值范围为 0 ~8,得到每个采样点的纵坐标(向上取整),这里的坐标值即为量化后的幅度值。因为我们将幅度轴分为了 8 段,有 8 个值用于量化取整,即本次量化的精度为 8。
显然,如果分段越多,则幅度的量化取值将越准确(取整带来的误差就越小),也能越好的表示原波形。对于幅度的量化精度,有一个专有术语描述 – 位深,我们后面会详细说明。
3)编码
编码是整个声音数字化的最后一步,其实声音模拟信号经过采样,量化之后已经变为了数字形式,但是为了方便计算机的储存和处理,我们需要对它进行编码,以减少数据量。
常见的音频编码格式有PCM、PDM。
经过量化后,我们得到了每个采样点的幅度值。接下来,就是音频信号数字化的最后一步,编码。编码是将每个采样点的幅度量化值,转化为计算机可理解的二进制字节序列。
如下图所示,参照编码部分的表格,样本序号为样本采样顺序,样本值(十进制)为量化的幅度值。而样本值(二进制)即为幅度值转换后的编码数据。最终,我们就得到了“0”、“1”形式的二进制字节序列,也即离散的数字信号。
这里得到的,是未经压缩的音频采样数据裸流,也叫做PCM 音频数据(Pulse Code Modulation,脉冲编码调制)。实际应用中,往往还会使用其他编码算法做进一步压缩,以后的文章我们会再展开讨论。
同理,如果处理器要向外界传达自己的“心声”,也就是放音,那么就涉及到将处理器能理解的 0 和 1 转化为外界能理解的连续变化的声音,这个过程就是将数字信号转化为模拟信号,而完成这个功能的是 DAC 芯片。
5. 音频数字信号质量三要素
1)采样率
音频采样率,指的是单位时间内(1s)对声音信号的采样次数(参考数字化过程-采样)。常说的 44.1KHz 采样率,也即 1 秒采集了 44100 个样本。
我们前面了解到,采样率越高、采样点越多,就可以越好的表示原波形,这就是采样率的影响。
参考奈奎斯特采样定理:采样率 f,必须大于原始音频信号最大振动频率fmax 的 2 倍(也即 f > 2fmax,fmax 被称为奈奎斯特频率),采样结果才能用于完整重建原始音频信号;如果采样率低于 2fmax,那么音频采样就存在失真。
比如,要对最高频率fmax=8KHz 的原始音频进行采样,则采样率 f 至少为 16KHz。
对于最大频率为 f 的音频信号,当我们分别采用 f、2f、4f/3 的采样率进行采样时,所得到的采样结果参考下图。显然,只有当采样率为 2f 时,才能有效的保留原信号特征。采样率 f 和3f/4 下得到的结果,都和原波形差别很大。
那么,我们需要多大的采样率?
按前面的讨论,采样率似乎越大越好,是否如此呢?理论上来说,最低采样率需要满足奈奎斯特采样定理,在该前提下,采样率越高则保留的原始音频信息越多,声音自然就越真实。
但需要注意的是,采样率越高则采样得到的数据量越大,对存储和带宽的要求也就越高。在实际应用中,我们为了平衡带宽和音质,不同场景往往会有不同的选择。常见的选择如下:
采样率 | 描述 |
---|---|
8KHz | 在语聊、通话场景,满足基本的沟通目的,同时有效减少数据量、兼容各种传输/存储环境。人说话声音频率一般在300-700Hz之间,最大区间一般为60Hz-2000Hz, 参考奈奎斯特定理,8KHz采样率完全足够 |
16KHz、32KHz | 在保证基本沟通的基础上,进一步提升音质,同时平衡带宽、存储的压力。某些音频处理算法会要求使用32KHz的采样率 |
44.1KHz,48KHz | 在比如在线KTV、音乐教学等场景,对音质要求比较高,可考虑进一步提升采样率。人耳可识别的声音频率范围为 20Hz ~ 20KHz,根据奈奎斯特采样定理,理论上采样率大于40KHz则完全足够。实际应用中,44.1KHz 可满足绝大多数的音视频应用场景。我们一般将 44.1kHz作为CD音质的采样标准 |
96KHz、192KHz | 更特殊的应用,比如需要对采集的音频进行后期加工、二次处理等。96KHz、192KHz等采样率对于人耳听感来说已无明显的提升,反而会增大存储、带宽的压力,对采集/播放设备也有较高要求,RTC场景一般不考虑 |
当采样率从 8KHz 翻倍至 16KHz 时,听感明显变得更清晰、空灵和舒适。
此时,采样率的提升带来了明显的音质提升。而采样率从 16KHz 提升至 44.1KHz 时,实际听感却好像没有太大的变化,这是因为采样率到达一定程度后,音频质量已经比较高,再往上提升带来的优化已经很细微。
借助专业的频谱分析软件,或许可以观察到高频谱区域的能量差异,但对于人耳来说,已经很难进行区分。所以实际应用中,我们不需要一味追求高采样率,而是要综合带宽、性能、实际听感,选择合适的配置即可。
2)采样位深/量化精度
位深度,也叫位宽,量化精度。
指的是在音频采集量化过程中,每个采样点幅度值的取值精度,一般使用bit作为单位。
常见的位宽有:8bit或者16bit。
比如,当采样位深为 8bit,则每个采样点的幅度值可以用 2^8=256 个量化值表示;采样位深为 16bit 时,则每个采样点的幅度值可以用 2^16=65536 个量化值表示。
显然,16bit 比 8bit 可存储、表示的数据更多、更精细,量化时产生的误差损失就越小。位深影响声音的解析精度、细腻程度,我们可以将其理解为声音信号的“分辨率”,位深越大,音色也越真实、生动。
采样位深选择和采样率的选择类似,虽然理论上来说位深越大越好,但是综合带宽、存储、实际听感的考虑,我们应该为不同场景选用不同的位深。
采样率 | 描述 |
---|---|
8bit | 早期常用的位深精度,可满足基础的通话音质需求 |
16bit | 被认为是达到专业音频质量的位深标准,足够完整地收录绝大多数音频场景的动态变化,适用范围广。和44.1KHz采样率一起,被作为CD音质的标准 |
24bit、32bit、64bit | 对于使用常见播放设备(手机、普通音箱)的用户来说,32bit与16bit的感官差异很细微,音质上的提升不明显,反而带来了更大的带宽、存储压力,更不用说64bit。并不需要盲目追求 |
3)声道数
我们常说的单声道、双声道,其实就是在描述一个音频信号的声道数(分别对应于声道数 1 和 2)。
声波是可以叠加的,音频的采集和播放自然也如此,我们可以同时从多个音频源采集声音,也可以分别输出到多个扬声器,声道数一般指声音采集录制时的音源数量或播放时的扬声器数量。
除了常见的声道数1、2,PC上还有4,6,8等声道的扩展。一般来说声道数越多,声音的方向感、空间感越丰富,听感也就越好。
目前很多手机厂商已经将双声道扬声器作为旗舰标配。在RTC音乐场景,越来越多的应用也开始采用双声道配置,其目的也是进一步提高听感,给用户更好的体验。
声道数的选择实时音视频场景下,声道的选择受限于编解码器、前处理算法的能力,一般仅支持单、双声道。而双声道配置主要在语音电台、音乐直播、乐器教学、ASMR 直播等场景使用,其它场景单声道即可满足。
当然,最终能否使用哪一种声道配置,还是由实际采集、播放设备的能力决定。解码音频数据时,可以获取数据的声道数,在实际播放时,也要先获取设备属性。
如果设备支持双声道,但待播放数据是单声道的,就需要将单声道数据转成双声道数据再播放;同理,如果设备只支持单声道,但数据是双声道的,也需要将双声道数据转换成单声道数据再播放。
目前,CD音频的采样频率通常为 44100 Hz,量化精度是 16bit。
6. 音频码率
数字音频的三要素不仅影响音频质量,也会影响音频存储、传输所需的空间、带宽。而实际应用场景下,音质决定用户体验、带宽决定成本,都是我们必须考虑到。
音质可能更多是主观上的感受,但带宽、空间是比较容易量化的,我们需要了解音频码率的概念。
音频码率,又称为比特率,指的是单位时间内(一般为1s)所包含的音频数据量,可以通过公式计算。
数据传输率:数据传输率(bps) = 采样频率 × 量化位数 × 声道数。
声音信号的数据量:数据量(byte)= 数据传输率 * 持续时间 / 8。
比如采样率 44.1K Hz,位深16bit、双声道音频PCM数据,它的原始码率为:
原始码率 = 采样率/s x 位深/bit x 声道数 x 时长(1s)
44.1 * 1000 * 16 * 2 * 1 = 1411200 bps = 1411.2 kbps = 1.411 Mbps (需要注意单位之间的差异和转换,b=bit)
如果一个PCM文件时长为1分钟,则传输/存储这个文件需要的数据量为:
1.411 Mbps * 60s = 86.46Mb
上述计算结果是未经压缩的、原始音频PCM数据的码率。
RTC场景下,往往还需要再使用 AAC、OPUS 等编码算法做编码压缩,进一步减小带宽、存储的压力。码率的选择也是一个综合质量和成本的博弈。
7. 噪声抑制
有上图所示, 1、某一时刻,用户 A 开始说话,产生的语音 A 被麦克风 A 采集、并通过网络传输给用户 B,成为待播放的语音 A1
2、语音 A1 被扬声器 B 播放后,通过直射、周围环境反射等方式,最终又被麦克风 B 采集为语音 A2(图中的回声 A2)
3、被回采的语音 A2,会通过网络传再输给用户 A,并通过扬声器 A 播放出来
经过上述过程,用户 A 会发现:自己刚说完一句话,过一会儿居然又听到了自己的“复述”,这就是 RTC 场景下的“回声”现象。
噪声抑制技术用于消除背景噪声,改善语音信号的信噪比和可懂度,让人和机器听得更清楚。
8. I2S
I2S(Inter-IC Sound)总线有时候也写作 IIS, I2S 是飞利浦公司提出的一种用于数字音频设备之间进行音频数据传输的总线。
I2S 总线用于主控制器(譬如 ZYNQ 7010/7020)和音频 CODEC 芯片之间传输音频数据;主控制器和音频 CODEC 都得支持 I2S 协议 。
在I2S总线上,只能同时存在一个主设备和发送设备,主设备可以是发送设备或接收设备。
I2S是PCM的一个分支,接口定义相同。
I2S的采样率一般为44.1/48KHZ,PCM采样频率一般为8/16KHZ等。
I2S接口有4组信号:SCK(位时钟)、LRCK(帧时钟)、SDI/SDO(数据)。
LRCLK
采样时钟,也叫WS(Word Select):字段选择线,帧时钟 (LRC) 线,
用于切换左右声道数据,
-
1 :传输左声道的数据
-
0 :表示正在传输右声道的数据
WS的频率等于采样频率,比如采样率为44.1KHz的音频,WS=44.1KHz;
SCLK/BCLK
串行时钟信号,也叫位时钟(BCLK)、CK(Serial Clock)
数字音频的每一位数据都对应有一个 CK脉冲,它的频率为:2* 采样频率 * 量化位数, 2 代表左右两个通道数据
比如采样频率为44.1KHz、 16位的立体声音频,那么
SCK=2×44100×16=1411200Hz=1.4112MHz;
SD/DATA
SD(Serial Data):串行数据线
用于发送或接收两个时分复用的数据通道上的数据 (仅半双工模式),如果是全双工模式,该信号仅用于发送数据。
MCLK
MCLK (Master/System clock input)也叫做主时钟或系统时钟,音频 CODEC 芯片与主控制器之间同步用,一般是采样率的 256 倍或 384 倍。
之所以引入MCLK。这是由CODEC内部基于Delta-Sigma (ΔΣ)的架构设计要求使然,其主要原因是因为这类的CODEC没有所谓提供芯片的工作时钟晶振电路,需要使用控制器为编解码芯片提供的系统时钟。
如果使用MCLK时钟的话,MCLK时钟频率一般为采样频率的256倍或384倍,具体参考特定器件手册。
下图为一帧立体声音频时序图
逻辑分析仪抓到的数据帧:
通道 0 是 LRCK 时钟,通道 1 为 BCLK,通道 2 是 DACDATA,通道 3 是MCLK。
9. codec
处理器如果要想播放或者采集声音, 需要用到 DAC 和 ADC 这两款芯片。
那是不是买两颗 DAC 和 ADC 芯片就行了呢?
答案肯定是可以的,但是音频不单单是能出声、能听到就行。
我们往往需要听到的声音动听、录进去的语音贴近真实、可以调节音效、对声音能够进行一些处理(需要 DSP 单元)、拥有统一的标准接口,方便开发等等。
将这些针对声音的各种要求全部叠加到 DAC 和ADC 芯片上,那么就会得到一个专门用于音频的芯片,也就是音频编解码芯片,英文名字就是 Audio CODEC。
codec芯片举例:
wolfson(欧胜) 的WM8960;顺芯的es8388、es8396;瑞芯微的rk809
Codec里面包含了I2S接口、D/A、A/D、Mixer、PA(功放),通常包含多种输入Mic、Line-in、I2S、PCM和多个输出hp(headphone)耳机、spk(Speak)喇叭、听筒,Line-out
下图是codec es8396芯片的模块图。
10. dai
dai(digital audio interface)
数字音频接口全部是硬件接口,是实实在在的物理连线方式,即同一个PCB板上IC芯片和IC芯片之间的通讯协议。和音频编码格式完全是两回事。
数字音频接口有PCM、I2S、AC97、PDM;
-
I2S和PCM(TDM)接口传输的数据是PCM编码格式的音频数据;
-
PDM接口传输的数据是PDM编码格式的音频数据;
下图是数字音频接口硬件接线的一般场景:
音频驱动调试基本命令和工具
基于Linux嵌入式设备常用调试方法很多,本文一口君把调试语音用到的工具和方法给大家做一个简单的介绍。
1. procfs、sysfs
Linux系统上的/proc目录是一种文件系统,即proc文件系统。与其它常见的文件系统不同的是,/proc是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。
基于/proc文件系统如上所述的特殊性,其内的文件也常被称作虚拟文件,并具有一些独特的特点。例如,其中有些文件虽然使用查看命令查看时会返回大量信息,但文件本身的大小却会显示为0字节。此外,这些特殊文件中大多数文件的时间及日期属性通常为当前系统时间和日期,这跟它们随时会被刷新(存储于RAM中)有关。
ALSA有自己的proc tree,在/proc/asound这个目录下可以找到许多关于snd card 的详细信息。
/proc/asound
rk3568_r:/ # ls /proc/asound -l
total 0
dr-xr-xr-x 5 root root 0 2024-02-19 22:27 card0
dr-xr-xr-x 4 root root 0 2024-02-19 22:27 card1
-r--r--r-- 1 root root 0 2024-02-19 22:27 cards
-r--r--r-- 1 root root 0 2024-02-19 22:27 devices
-r--r--r-- 1 root root 0 2024-02-19 22:27 hwdep
-r--r--r-- 1 root root 0 2024-02-19 22:27 pcm
lrwxrwxrwx 1 root root 5 2024-02-19 22:27 rockchiphdmi -> card1
lrwxrwxrwx 1 root root 5 2024-02-19 22:27 rockchiprk809co -> card0
-r--r--r-- 1 root root 0 2024-02-19 22:27 timers
-r--r--r-- 1 root root 0 2024-02-19 22:27 version
其中主要的节点如下:
- cardx:表示注册的sound card;
- cards:显示当前配置的Alsa Drivers,index,the id string,short and long descriptions;
- version:显示版本字符串;
- devices:列举本机设备映射;
- pcm:列举当前可用的 pcm devides,格式如下:-: : : ;
/proc/asound/cards
通过 proc fs 确认声卡注册成功
# cat /proc/asound/cards
0 [rockchiprk809co]: rockchip_rk809- - rockchip,rk809-codec
rockchip,rk809-codec
7 [Loopback ]: Loopback - Loopback
Loopback 1
/proc/asound/devices
查看声卡下的功能设备
rk3568_r:/ # cat /proc/asound/devices
2: [ 0- 0]: digital audio playback
3: [ 0- 0]: digital audio capture
4: [ 0] : control
5: [ 1- 0]: digital audio playback
6: [ 1] : control
33: : timer
对于devices的print格式如下:
- Control设备: “minor: [card_id] : control”;
- PCM设备 : “minor: [card_id- device_id]: digital audio playback/capture”;
- timer设备 : “minor: : timer”;
/proc/asound/pcm
查看声卡采集、播放PCM信息
rk3568_r:/ # cat /proc/asound/pcm
cat /proc/asound/pcm
00-00: fe410000.i2s-rk817-hifi rk817-hifi-0 : fe410000.i2s-rk817-hifi rk817-hifi-0 : playback 1 : capture 1
01-00: rockchip,hdmi i2s-hifi-0 : rockchip,hdmi i2s-hifi-0 : playback 1
/proc/asound/version
查看ALSA驱动版本
rk3568_r:/ # cat /proc/asound/version
cat /proc/asound/version
Advanced Linux Sound Architecture Driver Version k4.19.232.
/proc/asound/card0/pcm0p/sub0/status
查看声卡0的信息
rk3568_r:/ # cat /proc/asound/card0/pcm0p/sub0/status
cat /proc/asound/card0/pcm0p/sub0/status
closed
rk3568_r:/sys/devices/platform/rk809-sound # ls
driver driver_override fe410000.i2s-rk817-hifi modalias of_node power sound subsystem uevent
kernel/Documentation/devicetree/bindings/sound/rockchip-i2s.txt rockchip,i2s-tdm.txt
创建 /proc/asound目录
alsa_sound_init函数中会调用snd_info_init函数创建 /proc/asound目录,并将该entry保存在全局变量 snd_proc_root(即作为 sound proc root entry),代码如下
int __init snd_info_init(void)
{
//1、创建 alsa proc root entry;
snd_proc_root = snd_info_create_entry("asound", NULL);
if (!snd_proc_root)
return -ENOMEM;
snd_proc_root->mode = S_IFDIR | 0555;
//2、创建 dir: /proc/asound
snd_proc_root->p = proc_mkdir("asound", NULL);
if (!snd_proc_root->p)
goto error;
#ifdef CONFIG_SND_OSSEMUL
snd_oss_root = create_subdir(THIS_MODULE, "oss");
if (!snd_oss_root)
goto error;
#endif
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
snd_seq_root = create_subdir(THIS_MODULE, "seq");
if (!snd_seq_root)
goto error;
#endif
if (snd_info_version_init() < 0 || //3、创建 file: /proc/asound/version
snd_minor_info_init() < 0 || //4、创建 file: /proc/asound/devices
snd_minor_info_oss_init() < 0 ||
snd_card_info_init() < 0 || //5、创建 file: /proc/asound/cards
snd_info_minor_register() < 0)
goto error;
return 0;
error:
snd_info_free_entry(snd_proc_root);
return -ENOMEM;
}
查看时钟clk summary
查询音频时钟,确认时钟设置正确
示例:查询 i2s0 mclk 频率,以及其所在的 pll,结果:mclk 为 12288000 Hz,pll 源为 cpll
cat /sys/kernel/debug/clk/clk_summary | egrep "i2s0|pll"
pll_cpll 1 1 0 500000000
cpll 5 10 0 500000000
mclk_i2s0_rx_div 0 0 0 500000000
mclk_i2s0_rx_fracdiv 0 0 0 12288000
mclk_i2s0_rx_mux 0 0 0 12288000
mclk_i2s0_rx 0 0 0 12288000
mclk_i2s0_tx_div 1 1 0 500000000
mclk_i2s0_tx_fracdiv 1 1 0 12288000
mclk_i2s0_tx_mux 1 1 0 12288000
mclk_i2s0_tx 1 1 0 12288000
mclk_i2s0_tx_out2io 2 2 0 12288000
2. 寄存器
io命令
通过 io 命令 查看修改寄存器(适合 SOC 寄存器查询),配合芯片手册确认配置以及工作状态。
# cat /proc/iomem | grep i2s
ff800000-ff800fff : i2s@ff800000
# #
io -4 -l 0x40 0xff800000
ff800000: 7200000f 004e000f 10003f3f 00000010
ff800010: 000f0110 01f00000 00000000 00000003
ff800020: 00000000 00000000 00000000 0000001f
ff800030: 00003eff 00003eff 00000303 20150001
regmap
通过 regmap 节点查看寄存器(只读)。
# ls /sys/kernel/debug/regmap/
0-0020-rk817-codec
ff800000.i2s
...
# cat /sys/kernel/debug/regmap/0-0020-rk817-codec/registers
12: 03
13: f4
14: 00
15: ff
16: 00
17: 40
18: 48
19: 00
1a: 00
1b: ff
1c: 00
1d: 00
1e: 02
1f: 00
...rk3568_r:/ # cat /sys/kernel/debug/regmap/0-0020-rk817-codec/name
cat /sys/kernel/debug/regmap/0-0020-rk817-codec/name
rk808## rk3568 i2s0控制器寄存器
rk3568_r: # cat /sys/kernel/debug/regmap/fe400000.i2s/registers
cat /sys/kernel/debug/regmap/fe400000.i2s/registers
00: 7200000f
04: 01c8000f
08: 00001f1f
0c: XXXXXXXX
10: 000f0010
14: 01f00000
18: XXXXXXXX
1c: 00000000
20: XXXXXXXX
24: XXXXXXXX
2c: XXXXXXXX
30: 00003eff
34: 00003eff
38: 00000707
## codec es809寄存器rk3568_r:/ # cat /sys/kernel/debug/regmap/0-0020-rk817-codec/registers
cat /sys/kernel/debug/regmap/0-0020-rk817-codec/registers
00: 00
01: 00
02: 00
03: 00
04: 00
05: 00
06: 00
07: 00
08: 00
09: 00
0a: 00
0b: 00
0c: 00
0d: 00
0e: 00
0f: 00
10: 00
11: 00
12: 03
13: f4
14: 00
注意: regmap 基于 cache 机制,如果通过 io 命令直接修改寄存器后, regmap 节点不会体现更新后的寄存器,除非驱动将寄存器类型设置为 volatile 或者将 regmap cache 关闭。
3. alsa-utils
瑞芯微的android版本的sdk中不支持aplay、arecord、amixer这组命令,下面是以复旦微厂家sdk举例。
官方sdk的buildroot目录下执行make menuconfig:
aplay
Usage: aplay [OPTION]... [FILE]...
-h, --help help
--version print current version
-l, --list-devices list all soundcards and digital audio devices
-L, --list-pcms list device names
-D, --device=NAME select PCM by name
-q, --quiet quiet mode
-t, --file-type TYPE file type (voc, wav, raw or au)
-c, --channels=# channels
-f, --format=FORMAT sample format (case insensitive)
-r, --rate=# sample rate
-d, --duration=# interrupt after # seconds
-M, --mmap mmap stream
-N, --nonblock nonblocking mode
-F, --period-time=# distance between interrupts is # microseconds
-B, --buffer-time=# buffer duration is # microseconds
--period-size=# distance between interrupts is # frames
--buffer-size=# buffer duration is # frames
-A, --avail-min=# min available space for wakeup is # microseconds
-R, --start-delay=# delay for automatic PCM start is # microseconds
(relative to buffer size if <= 0)
-T, --stop-delay=# delay for automatic PCM stop is # microseconds from xrun
-v, --verbose show PCM structure and setup (accumulative)
-V, --vumeter=TYPE enable VU meter (TYPE: mono or stereo)
-I, --separate-channels one file for each channel
-i, --interactive allow interactive operation from stdin
-m, --chmap=ch1,ch2,.. Give the channel map to override or follow
--disable-resample disable automatic rate resample
--disable-channels disable automatic channel conversions
--disable-format disable automatic format conversions
--disable-softvol disable software volume control (softvol)
--test-position test ring buffer position
--test-coef=# test coefficient for ring buffer position (default 8)
expression for validation is: coef * (buffer_size / 2)
--test-nowait do not wait for ring buffer - eats whole CPU
--max-file-time=# start another output file when the old file has recorded
for this many seconds
--process-id-file write the process ID here
--use-strftime apply the strftime facility to the output file name
--dump-hw-params dump hw_params of the device
--fatal-errors treat all errors as fatal
示例:通过声卡0 播放 48k 采样率 2声道 16 位的静音数据
aplay -D hw:0,0 --period-size=1024 --buffer-size=4096 -r 48000 -c 2 -f s16_le
/dev/zero
arecord
Usage: arecord [OPTION]... [FILE]...
-h, --help help
--version print current version
-l, --list-devices list all soundcards and digital audio devices
-L, --list-pcms list device names
-D, --device=NAME select PCM by name
-q, --quiet quiet mode
-t, --file-type TYPE file type (voc, wav, raw or au)
-c, --channels=# channels
-f, --format=FORMAT sample format (case insensitive)
-r, --rate=# sample rate
-d, --duration=# interrupt after # seconds
-M, --mmap mmap stream
-N, --nonblock nonblocking mode
-F, --period-time=# distance between interrupts is # microseconds
-B, --buffer-time=# buffer duration is # microseconds
--period-size=# distance between interrupts is # frames
--buffer-size=# buffer duration is # frames
-A, --avail-min=# min available space for wakeup is # microseconds
-R, --start-delay=# delay for automatic PCM start is # microseconds
(relative to buffer size if <= 0)
-T, --stop-delay=# delay for automatic PCM stop is # microseconds from xrun
-v, --verbose show PCM structure and setup (accumulative)
-V, --vumeter=TYPE enable VU meter (TYPE: mono or stereo)
-I, --separate-channels one file for each channel
-i, --interactive allow interactive operation from stdin
-m, --chmap=ch1,ch2,.. Give the channel map to override or follow
--disable-resample disable automatic rate resample
--disable-channels disable automatic channel conversions
--disable-format disable automatic format conversions
--disable-softvol disable software volume control (softvol)
--test-position test ring buffer position
--test-coef=# test coefficient for ring buffer position (default 8)
expression for validation is: coef * (buffer_size / 2)
--test-nowait do not wait for ring buffer - eats whole CPU
--max-file-time=# start another output file when the old file has recorded
for this many seconds
--process-id-file write the process ID here
--use-strftime apply the strftime facility to the output file name
--dump-hw-params dump hw_params of the device
--fatal-errors treat all errors as fatal
示例:通过声卡0 录制 16k 采样率 8声道 32 位 的音频数据
arecord -D hw:0,0 --period-size=1024 --buffer-size=4096 -r 16000 -c 8 -f s32_le
r.wav
aplay | arecord命令
两者通过管道可以方便的实现 loopback 功能,方便驱动调试和指标测试。
示例:声卡0 录制 -> 声卡1 播放
# arecord -D hw:0,0 --period-size=1024 --buffer-size=4096 -r 48000 -c 2 -f s16_le
-t raw | aplay -D hw:1,0 --period-size=1024 --buffer-size=4096 -r 48000 -c 2 -f
s16_le -t raw
amixer命令
控制 codec 内部的通路开关,结合 codec 手册的音频拓扑图(比如 图 3-2 RK3308 codec)实现音频流的路由,音量控制等
Usage: amixer <options> [command]
Available options:
-h,--help this help
-c,--card N select the card
-D,--device N select the device, default 'default'
-d,--debug debug mode
-n,--nocheck do not perform range checking
-v,--version print version of this program
-q,--quiet be quiet
-i,--inactive show also inactive controls
-a,--abstract L select abstraction level (none or basic)
-s,--stdin Read and execute commands from stdin sequentially
-R,--raw-volume Use the raw value (default)
-M,--mapped-volume Use the mapped volume
Available commands:
scontrols show all mixer simple controls
scontents show contents of all mixer simple controls (default command)
sset sID P set contents for one mixer simple control
sget sID get contents for one mixer simple control
controls show all controls for given card
contents show contents of all controls for given card
cset cID P set control contents for one control
cget cID get control contents for one control
示例:查询声卡 controls,将播放通路切换到 SPK
# amixer -c 0 contents
numid=1,iface=MIXER,name='Playback Path'
; type=ENUMERATED,access=rw------,values=1,items=11
; Item #0 'OFF'
; Item #1 'RCV'
; Item #2 'SPK'
; Item #3 'HP'
; Item #4 'HP_NO_MIC'
; Item #5 'BT'
; Item #6 'SPK_HP'
; Item #7 'RING_SPK'
; Item #8 'RING_HP'
; Item #9 'RING_HP_NO_MIC'
; Item #10 'RING_SPK_HP'
: values=0
...
# # amixer -c 0 cset numid=1 2
numid=1,iface=MIXER,name='Playback Path'
; type=ENUMERATED,access=rw------,values=1,items=11
; Item #0 'OFF'
; Item #1 'RCV'
; Item #2 'SPK'
; Item #3 'HP'
; Item #4 'HP_NO_MIC'
; Item #5 'BT'
; Item #6 'SPK_HP'
; Item #7 'RING_SPK'
; Item #8 'RING_HP'
; Item #9 'RING_HP_NO_MIC'
; Item #10 'RING_SPK_HP'
: values=2
alsaloop命令
支持 任意声卡间的路由
支持 自适应时钟同步
自持 自适应重采样
支持 mixer controls 重定向
Usage: alsaloop [OPTION]...
-h,--help help
-g,--config configuration file (one line = one job specified)
-d,--daemonize daemonize the main process and use syslog for errors
-P,--pdevice playback device
-C,--cdevice capture device
-X,--pctl playback ctl device
-Y,--cctl capture ctl device
-l,--latency requested latency in frames
-t,--tlatency requested latency in usec (1/1000000sec)
-f,--format sample format
-c,--channels channels
-r,--rate rate
-n,--resample resample in alsa-lib
-A,--samplerate use converter (0=sincbest,1=sincmedium,2=sincfastest,
3=zerohold,4=linear)
-B,--buffer buffer size in frames
-E,--period period size in frames
-s,--seconds duration of loop in seconds
-b,--nblock non-block mode (very early process wakeup)
-S,--sync sync mode(0=none,1=simple,2=captshift,3=playshift,4=samplerate,
5=auto)
-a,--slave stream parameters slave mode (0=auto, 1=on, 2=off)
-T,--thread thread number (-1 = create unique)
-m,--mixer redirect mixer, argument is:
SRC_SLAVE_ID(PLAYBACK)[@DST_SLAVE_ID(CAPTURE)]
-O,--ossmixer rescan and redirect oss mixer, argument is:
ALSA_ID@OSS_ID (for example: "Master@VOLUME")
-e,--effect apply an effect (bandpass filter sweep)
-v,--verbose verbose mode (more -v means more verbose)
-w,--workaround use workaround (serialopen)
-U,--xrun xrun profiling
-W,--wake process wake timeout in ms
-z,--syslog use syslog for errors
示例:声卡0录制的音频通过声卡1播放,同步模式采用 策略1(增加或减少采样点)
alsaloop -C hw:0,0 -P hw:1,0 -t 10000 -A 3 -S 1 -b -v
es8388播放和录音举例
/**************************************
* 波形测试, RAW数据
**************************************/aplay -D hw:0,0 -f S24_LE -r 44100 -c 2 -t raw /bin/busybox & arecord -D hw:0,1 -f S24_LE -r 44100 -c 2 -d 5 record.wav
抓包, 上传record.wav到电脑,可以听见杂波aplay -D hw:0,0 -f S24_LE -r 44100 -c 2 -t raw test.pcm & arecord -D hw:0,1 -f S24_LE -r 44100 -c 2 -d 5 record.wav
抓包, 上传record.wav到电脑,可以听见疯狂小鸟aplay -D hw:0,0 -fS24_LE -r 44100 -c 2 -t raw /all_0x00.bin &
arecord -r 44100 -f S24_LE -c 2 -d 30 -D hw:0,1 record.wav
aplay -D hw:0,0 -fS24_LE -r 44100 -c 2 -t raw /all_0xff.bin &
arecord -r 44100 -f S24_LE -c 2 -d 30 -D hw:0,1 record.wav
aplay /test.wav &
arecord -r 44100 -f S24_LE -c 2 -d 30 -D hw:0,1 record.wav
抓包, 上传record.wav, 听见疯狂小鸟
/**************************************
* 设置
**************************************/# 查看功能
amixer scontrols# 耳机测试
amixer sset 'Headphone Playback ZC' on # 打开耳机播放 ZC
amixer sset 'Right Output Mixer PCM' on # 打开右声道
amixer sset 'Left Output Mixer PCM' on # 打开左声道
amixer sset Headphone 105,105 # 设置耳机音量
amixer sset Playback 230,230 # 设置播放音量
# 播放
aplay /opt/hardwareTest/wav/test.wav # <---------------------------------------------------# MIC测试
#设置声卡输入捕获音量大小
amixer sset Capture 56,56
amixer sset 'ADC PCM' 200,200
#音频输入,关闭所有右声道
amixer sset 'Right Input Mixer Boost' off
amixer sset 'Right Boost Mixer RINPUT1' off
amixer sset 'Right Input Boost Mixer RINPUT1' 0
amixer sset 'Right Boost Mixer RINPUT2' off
amixer sset 'Right Input Boost Mixer RINPUT2' 0
amixer sset 'Right Boost Mixer RINPUT3' off
amixer sset 'Right Input Boost Mixer RINPUT3' 0
#音频输入,打开左声道 1 和 2,关闭 3
amixer sset 'Left Input Mixer Boost' on
amixer sset 'Left Boost Mixer LINPUT1' on
amixer sset 'Left Input Boost Mixer LINPUT1' 5
amixer sset 'Left Boost Mixer LINPUT2' on
amixer sset 'Left Input Boost Mixer LINPUT2' 3
amixer sset 'Left Boost Mixer LINPUT3' off
amixer sset 'Left Input Boost Mixer LINPUT3' 0
# 录音
arecord -r 44100 -f S24_LE -c 2 -d 10 -D hw:0,1 record.wav # <---------------------------------------------------# Line IN 测试
#设置声卡输入捕获音量大小
amixer sset Capture 56,56
amixer sset 'ADC PCM' 200,200
#音频输入,打开左声道 3,,关闭 1 和 2
amixer sset 'Left Input Mixer Boost' on
amixer sset 'Left Boost Mixer LINPUT1' off
amixer sset 'Left Input Boost Mixer LINPUT1' 0
amixer sset 'Left Boost Mixer LINPUT2' off
amixer sset 'Left Input Boost Mixer LINPUT2' 0
amixer sset 'Left Boost Mixer LINPUT3' on
amixer sset 'Left Input Boost Mixer LINPUT3' 5
#音频输入,打开右声道 2,关闭 1 和 3
amixer sset 'Right Input Mixer Boost' on
amixer sset 'Right Boost Mixer RINPUT1' off
amixer sset 'Right Input Boost Mixer RINPUT1' 0
amixer sset 'Right Boost Mixer RINPUT2' on
amixer sset 'Right Input Boost Mixer RINPUT2' 5
amixer sset 'Right Boost Mixer RINPUT3' off
amixer sset 'Right Input Boost Mixer RINPUT3' 0
4. tiny-alsa
RK Android SDK 标配 tiny-alsa 工具。
Linux ALSA 在内核层提供了 alsa-driver,在应用层提供了 alsa-lib,应用程序只需要调用 alsa-lib 提供的 API 即可完成对底层硬件的操作。
但由于 ALSA 架构太过于庞大,对于嵌入式设备而言很多功能用不到,且会增加功耗,所以 Android 采用了精简后的 tinyalsa。
Android 中使用 tinyalsa 控制管理所有模式的音频通路,也可以使用 tinyalsa 提供的工具进行查看、调试。
Tinyalsa 源码位于 android 源码目录下 external/tinyalsa,可以使用 mmm 命令编译,
mmm external/tinyalsa
编译 tinyalsa 后会生成四个小工具:
- tinymix
- tinyplay
- inycap
- inypcminfo
1) tinypcminfo
tinypcminfo 用于查看 pcm 通道的相关信息,如 PCM 采样率,Channels,采样点数等信息。
Usage: tinypcminfo [-D card] [-d device]
示例:
rk3568_r:/ # tinypcminfo -D 0
Info for card 0, device 0:PCM out:
Access: 0x000009
Format[0]: 0x000444
Format[1]: 00000000
Format Name: S16_LE, S24_LE, S32_LE
Subformat: 0x000001
Rate: min=8000Hz max=96000Hz
Channels: min=2 max=8
Sample bits: min=16 max=32
Period size: min=8 max=65536
Period count: min=2 max=16384PCM in:
Access: 0x000009
Format[0]: 0x000444
Format[1]: 00000000
Format Name: S16_LE, S24_LE, S32_LE
Subformat: 0x000001
Rate: min=8000Hz max=96000Hz
Channels: min=2 max=8
Sample bits: min=16 max=32
Period size: min=8 max=65536
Period count: min=2 max=16384
2) tinyplay
tinyplay 是一个简易的音乐播放器,一般用于播放测试。
可以直接进行播放 wav 格式文件,在播放前需要先使用 tinymix 进行相关控件的设置。
Usage: tinyplay file.wav [-D card] [-d device] [-p period_size] [-n n_periods]
示例:播放src_test_xiaoniao.wav、1khz_44100_16bit.wav 音频文件
rk3568_r:/sdcard # tinyplay src_test_xiaoniao.wav
Playing sample: 2 ch, 44100 hz, 16 bit 1764000 bytesrk3568_r:/sdcard # tinyplay 1khz_44100_16bit.wav
Playing sample: 2 ch, 44100 hz, 16 bit 15876000 bytes
3) tinycap
tinycap 是一个简易的录音软件,一般用于录音测试。
使用之前也需要先设置录音相关的控件,设置好控件后,执行 tinycap xxx.wav 即可将音频录制到 xxx.wav 中。
Usage: tinycap file.wav [-D card] [-d device] [-c channels] [-r rate] [-b bits]
[-p period_size] [-n n_periods]
示例:44.1k 采样率录制音频
# tinycap /sdcard/rec.wav -D 0 -d 0 –c 2 –r 44100 –b 16 –p 1024 –n 3
rk3568_r:/sdcard # tinycap /sdcard/rec.wav -D 0
Capturing sample: 2 ch, 44100 hz, 16 bit
4) tinymix
控制 codec 内部的通路开关, 音量控制等。效果等同于 amixer
1)tinymix 可以查看系统的音频控件,可直接执行 tinymix 进行查看;
2)tinymix 可以手动设置控件的值,控件可通过 tinymix 查看,或者通过 mixer_paths.xml 查看。
usage: tinymix [-D card]
rk3568_r:/sdcard # tinymix --help
tinymix [options] [control name/#] [value to set]
options:
--device|-D <card#> - use the given card # instead of 0.
--all-values|-a - show all possible values/ranges for control.
--tabs-only|-t - separate all output columns/values with tabs.
--value-only|-v - show only the value for the selected control.
示例:
rk3568_r:/sdcard # tinymix
Mixer name: 'rockchip,rk809-codec'
Number of controls: 2
ctl type num name value0 ENUM 1 Playback Path OFF
1 ENUM 1 Capture MIC Path MIC OFF
rk3568_r:/sdcard # tinymix -a
Mixer name: 'rockchip,rk809-codec'
Number of controls: 2
ctl type num name value
range/values
0 ENUM 1 Playback Path >OFF RCV SPK HP HP_NO_MIC BT SPK_HP RING_SPK RING_HP RING_HP_NO_MIC RING_SPK_HP
1 ENUM 1 Capture MIC Path >MIC OFF Main Mic Hands Free Mic BT Sco Mic
5. i2c工具链
i2c工具主要用于配置codec,本文使用的是es8388,配置该芯片可以通过i2c接口。
通过 i2ctool 查看修改 codec 寄存器(适合 i2c 类型的 codec 设备),配合 codec 手册确认配置以及工作状态。
rk3568sdk集成i2c工具链,做了精简,与其他版本工具链使用略有差别。
安装命令
apt-get update
apt-get install i2c-tools
linux版本代码下载路径:
https://mirrors.edge.kernel.org/pub/software/utils/i2c-tools/
i2cdetect
rk3568_r:/ # i2cdetect --help
usage: i2cdetect [-ary] BUS [FIRST LAST]
usage: i2cdetect -F BUS
usage: i2cdetect -l
Detect i2c devices.
-a All addresses (0x00-0x7f rather than 0x03-0x77)
-F Show functionality
-l List all buses
-r Probe with SMBus Read Byte
-y Answer "yes" to confirmation prompts (for script use)
查询 i2c0 总线上的设备
rk3568_r:/ # i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- --
20: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
i2cdump命令
dump 设备的所有寄存器
rk3568_r:/ # i2cdump --help
usage: i2cdump [-fy] BUS CHIP
Dump i2c registers.
-f Force access to busy devices
-y Answer "yes" to confirmation prompts (for script use)
示例:查询 i2c0 总线下 rk817(设备地址:0x20)的寄存器,其中 0x12 ~ 0x4f 为 codec 寄存器。
rk3568_r:/ # i2cdump -f -y 0 0x20
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 02 00 09 04 08 17 05 00 00 00 01 01 00 01 80 00 ?.?????...??.??.
10: 00 00 03 f4 00 00 00 06 c8 00 00 00 00 00 00 00 ..??...??.......
20: 00 00 00 ff ff 00 00 70 00 66 00 00 00 00 00 0f ...??..p.f.....?
30: 06 03 03 00 a5 02 00 00 01 ff ff 00 00 e0 0f 09 ???.??..???..???
40: 69 7f 0c 58 2d 0c 95 01 00 00 00 0f 20 00 0f 00 i??X-???...? .?.
50: 8c 00 01 00 01 b0 44 10 00 60 00 00 00 00 00 00 ?.?.??D?.`......
60: 00 00 00 00 00 00 00 00 00 00 00 00 01 00 eb 00 ............?.?.
70: 00 00 00 00 ff ff ff ff 00 01 ff ff 00 00 00 00 ....????.???....
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90: 60 80 e9 7f cb df a6 80 e9 00 00 00 00 00 00 00 `????????.......
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
b0: 00 0f 0f 0f 0f 04 a4 ff ff 00 64 1c 20 64 1a 20 .????????.d? d?
c0: 64 00 00 64 1a 20 6b ff ff ff ff ff 0c 0c 0c 0c d..d? k?????????
d0: 0c 0c 6c 6c 6c 6c 6c 6c 30 30 30 30 30 30 09 31 ??llllll000000?1
e0: 00 00 00 55 a2 c8 c5 40 00 ff 22 03 0a 80 94 0e ...U???@.?"?????
f0: c2 ac a0 40 18 40 00 86 00 fc 00 ff 00 ff 60 00 ???@?@.?.?.?.?`.
i2cget
查询单个寄存器值
Usage: i2cget [-f] [-y] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]
I2CBUS is an integer or an I2C bus name
ADDRESS is an integer (0x03 - 0x77)
MODE is one of:
b (read byte data, default)
w (read word data)
c (write byte/read byte)
Append p for SMBus PEC
rk3568_r:/ # i2cget --help
usage: i2cget [-fy] BUS CHIP ADDR
Read an i2c register.
-f Force access to busy devices
-y Answer "yes" to confirmation prompts (for script use)
示例:查询 rk817 的 0x12 寄存器
rk3568_r:/ # i2cget -f -y 0 0x20 0x12
0x03
i2cset
修改单个寄存器值
Usage: i2cset [-f] [-y] [-m MASK] [-r] I2CBUS CHIP-ADDRESS DATA-ADDRESS [VALUE]
... [MODE]
I2CBUS is an integer or an I2C bus name
ADDRESS is an integer (0x03 - 0x77)
MODE is one of:
c (byte, no value)
b (byte data, default)
w (word data)
i (I2C block data)
s (SMBus block data)
Append p for SMBus PEC
rk3568_r:/ # i2cset --help
usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE
Write an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.
-f Force access to busy devices
-y Answer "yes" to confirmation prompts (for script use)
示例:修改 rk817(0x20) 的 0x12 寄存器,将值改为0
rk3568_r:/ # i2cset -fy 0 0x20 0x12 0 b
rk3568_r:/ # i2cget -f -y 0 0x20 0x12
0x00
i2ctransfer
i2c-tools-4.0及以后版本添加了i2ctransfer命令。
i2cget和i2cset可以读写的i2c设备的寄存器地址小于0xff,即寄存器是8位地址。
如果i2c设备寄存器是16位地址,可使用i2ctransfer命令,该命令同样可用在寄存器地址是8位的设备。
1、命令
"Usage: i2ctransfer [-f] [-y] [-v] [-V] [-a] I2CBUS DESC [DATA] [DESC [DATA]]...\n"
" I2CBUS is an integer or an I2C bus name\n"
" DESC describes the transfer in the form: {r|w}LENGTH[@address]\n"
" 1) read/write-flag 2) LENGTH (range 0-65535, or '?')\n"
" 3) I2C address (use last one if omitted)\n"
" DATA are LENGTH bytes for a write message. They can be shortened by a suffix:\n"
" = (keep value constant until LENGTH)\n"
" + (increase value by 1 until LENGTH)\n"
" - (decrease value by 1 until LENGTH)\n"
" p (use pseudo random generator until LENGTH with value as seed)\n\n"
"Example (bus 0, read 8 byte at offset 0x64 from EEPROM at 0x50):\n"
" # i2ctransfer 0 w1@0x50 0x64 r8\n"
"Example (same EEPROM, at offset 0x42 write 0xff 0xfe ... 0xf0):\n"
" # i2ctransfer 0 w17@0x50 0x42 0xff-\n");
2、用法
## 从i2c 4号总线0x38设备的0x3a01寄存器开始读16个字节的数据,w2:表示寄存器0x3a01的长度为2个字节
i2ctransfer -y -f 4 w2@0x38 0x3a 0x01 r16
## 向i2c 4号总线0x38设备的0x3a01寄存器写0x10,w3:表示寄存器0x3a01和写入值0x10的长度为3字节
i2ctransfer -y -f 4 w3@0x38 0x3a 0x01 0x10
逻辑分析仪
调试过程中,有时候我们需要抓取控制器和codec之间语音信号,并转换成语音数据,
一口君使用的是Kingst的 LA系列逻辑分析仪。
这是一款非常简单容易上手的设备,
即使新手也很容易就能上手,
比示波器好用很多。
后面会单独开一篇讲解该设备如何抓取波形并转换成语音数据。
抓取波形页面