前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[ 物联网篇 ] 28 - Linux ES7210 Driver 调试

[ 物联网篇 ] 28 - Linux ES7210 Driver 调试

作者头像
程序手艺人
发布2020-09-15 10:18:39
3.2K2
发布2020-09-15 10:18:39
举报
文章被收录于专栏:程序手艺人程序手艺人

前言

项目开发过程中,由于Broadcom平台音频数字接口比较少,所以采用模拟麦克风作为输入端,经顺芯ES7210 ADC 转换送至Broadcom PCM 数字音频接口。

提示:本文记录了调试ES7210 Driver 过程中的问题与收获。

一、ES7210 简介

在这里插入图片描述
在这里插入图片描述

ES7210 是一款高性能四通道音频ADC,支持I2S / PCM / TDM 模式,可支持多个ES7210级连模式。常用于智能音箱领域。

二、ES7210 Driver Porting

1. Broadcom 平台 集成 ES7210

ES7210 Driver 需要顺芯原厂提供,虽然Linux 先的音频框架是一样的,但是芯片内部会有一系列寄存器需要设置。

  • 将ES7210.c和ES7210.h复制到src/kernel/linux/v4.4/sound/soc/codecs/路径下
  • 修改src/kernel/linux/v4.4/sound/soc/codecs/Makefile,
代码语言:javascript
复制
#obj-$(CONFIG_SND_SOC_ES7243)   += es7243.o
obj-$(CONFIG_SND_SOC_ES7210)    += es7210.o

默认驱动ees7210.c中采用过的是I2C_detect方式注册,

如有需要用dts方式注册,请将ES7210_MATCH_DTS_EN赋值为1.

代码语言:javascript
复制
#define ES7210_MATCH_DTS_EN		1	
//ES7210 match method select: 0: i2c_detect, 1:of_device_id

2. Broadcom 平台定制化参数

代码语言:javascript
复制
/*  to set internal mclk and adclrclk ratio   */

#define RATIO_768  0xC3
#define RATIO_256  0xC1
#define RATIO_128  0x01
#define RATIO_64   0x41 /* mclk from bclk pin */

#define ES7210_MCLK_LRCK_RATIO   RATIO_128

Broadcom 平台 LRCK 默认是16KHz , 通过逻辑仪看到LRCK的频率为2.04MHz。故ES7210_MCLK_LRCK_RATIO 需要设置为RATIO_128

3. 排查 ES7210 无法正常工作

通过逻辑分析仪观察到波形,PCM In 一直没有数据,相当于ES7210 没有正常工作。

在这里插入图片描述
在这里插入图片描述

根据 调试笔记 — 使用ADC芯片ES7243遇到的问题 的分析,快速验证了I2C , 可以正常工作。

参考数字音频接口

在这里插入图片描述
在这里插入图片描述

找到ES7210 Datasheet ,TDM参考设计。MCLK 需要连接

在这里插入图片描述
在这里插入图片描述

而Broadcom 中的ES7210 中的MCLK 是悬空的, 这个时候找顺芯FAE 咨询了下,MCLK 不能悬空,一般是LRCLK的256倍。如果没有MCLK,需要将BCLK短接到MCLK。

在这里插入图片描述
在这里插入图片描述

通过飞线将MCLK与BCLK连接在一起, 通过逻辑分析仪抓取波形,发现PCM Data 一直都是某个bit持续为高电平,其它为低电平。感觉ES7210 还是没有工作起来。跟顺芯FAE沟通了解. 驱动中不需要更改。

在这里插入图片描述
在这里插入图片描述

想起来之前,驱动代码中一旦使能 clk_prepare_enable(es7210->mclk),kernel 会立即发生崩溃。顺芯FAE 解释说 本身提供的是的RK 平台的驱动代码,针对博通平台,需要去掉该操作,只要主控能送出BCLK 就可以,其他不会有影响,代码只是使能MCLK

代码语言:javascript
复制
ssoc-audio soc-audio: ASoC: machine MapleTree should use snd_soc_register_card()
########### debug 1es7210_probe!
Unable to handle kernel paging request at virtual address fffffffe
pgd = c0014000
[fffffffe] *pgd=1fffd821, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1] PREEMPT SMP ARM
Modules linked in:
CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.1.52 #8
Hardware name: Generic DT based system
task: df422c00 ti: df43a000 task.ti: df43a000
PC is at clk_prepare+0x14/0x2c
LR is at clk_prepare_lock+0x10/0xf8
pc : [<c02721b8>]    lr : [<c02710f8>]    psr: 60000113
sp : df43bdb0  ip : 00000000  fp : 00000000
r10: df4c4e20  r9 : df4c4c58  r8 : fffffffe
r7 : df4c4c00  r6 : df4c3d90  r5 : c07b6ca0  r4 : fffffffe
r3 : df422c00  r2 : 00000001  r1 : 00000000  r0 : 00000001
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c5387d  Table: 0001404a  DAC: 00000015
Process swapper/0 (pid: 1, stack limit = 0xdf43a210)
Stack: (0xdf43bdb0 to 0xdf43c000)
bda0:                                     df4c4c10 c02bb894 df4c4c10 df4c4c28
.....
[<c02721b8>] (clk_prepare) from [<c02bb894>] (es7210_probe+0x58/0x110)
[<c02bb894>] (es7210_probe) from [<c028d3bc>] (soc_probe_component+0x1f0/0x320)
[<c028d3bc>] (soc_probe_component) from [<c028ff7c>] (snd_soc_register_card+0x8b0/0xfc0)
[<c028ff7c>] (snd_soc_register_card) from [<c02186fc>] (platform_drv_probe+0x2c/0x60)
[<c02186fc>] (platform_drv_probe) from [<c02172a0>] (really_probe+0x190/0x290)
[<c02172a0>] (really_probe) from [<c0215a0c>] (bus_for_each_drv+0x60/0x94)
[<c0215a0c>] (bus_for_each_drv) from [<c0217108>] (device_attach+0x84/0x8c)
[<c0217108>] (device_attach) from [<c02167f8>] (bus_probe_device+0x84/0xa8)
[<c02167f8>] (bus_probe_device) from [<c0214b30>] (device_add+0x358/0x544)
[<c0214b30>] (device_add) from [<c02184c8>] (platform_device_add+0x110/0x220)
[<c02184c8>] (platform_device_add) from [<c05c3a6c>] (bcm63xx_audio_init+0x38/0x60)
[<c05c3a6c>] (bcm63xx_audio_init) from [<c001973c>] (do_one_initcall+0x8c/0x1d4)
[<c001973c>] (do_one_initcall) from [<c05a9dcc>] (kernel_init_freeable+0x148/0x1e8)
[<c05a9dcc>] (kernel_init_freeable) from [<c0446484>] (kernel_init+0x8/0xe8)
[<c0446484>] (kernel_init) from [<c001f4e8>] (ret_from_fork+0x14/0x2c)
Code: 012fff1e e92d4010 e1a04000 ebfffbcb (e5940000) 
---[ end trace 0daed059f560601b ]---
Kernel panic - not syncing: Fatal exception
CPU3: stopping
CPU: 3 PID: 0 Comm: swapper/3 Tainted: G      D         4.1.52 #8
Hardware name: Generic DT based system
[<c0026be0>] (unwind_backtrace) from [<c00229c8>] (show_stack+0x10/0x14)
[<c00229c8>] (show_stack) from [<c044a57c>] (dump_stack+0x8c/0xa0)
[<c044a57c>] (dump_stack) from [<c00253a4>] (handle_IPI+0x148/0x158)
[<c00253a4>] (handle_IPI) from [<c001941c>] (gic_handle_irq+0x5c/0x60)
[<c001941c>] (gic_handle_irq) from [<c00234c0>] (__irq_svc+0x40/0x74)
Exception stack(0xdf45ff88 to 0xdf45ffd0)
ff80:                   00000001 00000000 00000000 c002bd00 df45e000 c05dc4b0
ffa0: c0450704 00000000 df45ffd8 c05d7200 00000000 00000001 01000000 df45ffd0
ffc0: c00205f0 c00205f4 60000113 ffffffff
[<c00234c0>] (__irq_svc) from [<c00205f4>] (arch_cpu_idle+0x38/0x3c)
[<c00205f4>] (arch_cpu_idle) from [<c005ce60>] (cpu_startup_entry+0x15c/0x264)
[<c005ce60>] (cpu_startup_entry) from [<000194ac>] (0x194ac)                                         
CPU0: stopping                                                                                       
CPU: 0 PID: 0 Comm: swapper/0 Tainted: G      D         4.1.52 #8                                    
Hardware name: Generic DT based system                                                               
[<c0026be0>] (unwind_backtrace) from [<c00229c8>] (show_stack+0x10/0x14)
[<c00229c8>] (show_stack) from [<c044a57c>] (dump_stack+0x8c/0xa0)
[<c044a57c>] (dump_stack) from [<c00253a4>] (handle_IPI+0x148/0x158)
[<c00253a4>] (handle_IPI) from [<c001941c>] (gic_handle_irq+0x5c/0x60)
[<c001941c>] (gic_handle_irq) from [<c00234c0>] (__irq_svc+0x40/0x74)
Exception stack(0xc05dbf28 to 0xc05dbf70)
bf20:                   c05dbf70 00000018 312acb4c 00000000 dfbc9910 00000001
bf40: 3124e81c 00000000 312acb4c 00000000 c0602f54 c05d9200 14000000 c05dbf70
bf60: fffffff8 c0267dac 00000113 ffffffff
[<c00234c0>] (__irq_svc) from [<c0267dac>] (cpuidle_enter_state+0xd8/0x20c)
[<c0267dac>] (cpuidle_enter_state) from [<c005cf08>] (cpu_startup_entry+0x204/0x264)
[<c005cf08>] (cpu_startup_entry) from [<c05a9c78>] (start_kernel+0x3a8/0x3b4)
[<c05a9c78>] (start_kernel) from [<0001807c>] (0x1807c)
CPU2: stopping
CPU: 2 PID: 371 Comm: ubi_bgt0d Tainted: G      D         4.1.52 #8
Hardware name: Generic DT based system
[<c0026be0>] (unwind_backtrace) from [<c00229c8>] (show_stack+0x10/0x14)
[<c00229c8>] (show_stack) from [<c044a57c>] (dump_stack+0x8c/0xa0)
[<c044a57c>] (dump_stack) from [<c00253a4>] (handle_IPI+0x148/0x158)
[<c00253a4>] (handle_IPI) from [<c001941c>] (gic_handle_irq+0x5c/0x60)
[<c001941c>] (gic_handle_irq) from [<c00234c0>] (__irq_svc+0x40/0x74)
Exception stack(0xd965fe20 to 0xd965fe68)
fe20: c07aeafc 80000193 00000001 20000113 dfbc3f08 00000005 00000035 c07906b8
fe40: 00000000 00000006 00000000 00000100 00000002 d965fe68 c0061710 c0062310
fe60: 60000113 ffffffff
[<c00234c0>] (__irq_svc) from [<c0062310>] (console_unlock+0x33c/0x4f8)
[<c0062310>] (console_unlock) from [<c0062814>] (vprintk_emit+0x348/0x5a0)
[<c0062814>] (vprintk_emit) from [<c0062b8c>] (vprintk_default+0x20/0x28)
[<c0062b8c>] (vprintk_default) from [<c0448810>] (printk+0x6c/0x7c)
[<c0448810>] (printk) from [<c02495c4>] (ubi_thread+0x40/0x174)
[<c02495c4>] (ubi_thread) from [<c0046da8>] (kthread+0xdc/0xf4)
[<c0046da8>] (kthread) from [<c001f4e8>] (ret_from_fork+0x14/0x2c)
Rebooting in 5 seconds..

然后查看原理图,发现有MIC_EN引脚,连接的是ES7210中断引脚,咨询TP_Link硬件之后,发现这个脚目前是悬空状态,因此排除中断引脚的问题。

在这里插入图片描述
在这里插入图片描述

发现该排查的问题已经排查完成,先和FAE沟通,看还有哪些忽略的点,FAE说打开调试信息,查看Reg的值,沟通之后,了解方法之后,查看代码。通过应用层操作可以看出全部寄存器的数值。

代码语言:javascript
复制
1721 static struct attribute_group es7210_debug_attr_group = {
1722         .name   = "es7210_debug",
1723         .attrs  = es7210_debug_attrs,
1724 };
static DEVICE_ATTR(es7210, 0644, es7210_show, es7210_store);

06 static ssize_t es7210_show(struct device *dev, struct device_attribute *attr, char *buf)
1707 {
1708         printk("echo flag|reg|val > es7210\n");
1709         printk("eg read star address=0x06,count 0x10:echo 0610 >es7210\n");
1710         printk("eg write star address=0x90,value=0x3c,count=4:echo 4903c >es7210\n");
1711         return 0;
1712 }

/由于echo flag打印的寄存器不全,需要用 echo 0x47可以打印出全部寄存器

代码语言:javascript
复制
echo 0x4f > /sys/devices/platform/ubus@ff800000/ff802100.i2c/i2c-0/0-0040/es7210_debug/es7210

Read: start REG:0x00,count:0x4f
REG[0x00]: 0x41;  REG[0x01]: 0x20;  REG[0x02]: 0xc3;  REG[0x03]: 0x04;  
REG[0x04]: 0x01;  REG[0x05]: 0x00;  REG[0x06]: 0x00;  REG[0x07]: 0x20;  
REG[0x08]: 0x20;  REG[0x09]: 0x30;  REG[0x0a]: 0x30;  REG[0x0b]: 0x02;  
REG[0x0c]: 0x00;  REG[0x0d]: 0x09;  REG[0x0e]: 0xff;  REG[0x0f]: 0xff;  
REG[0x10]: 0x00;  REG[0x11]: 0x63;  REG[0x12]: 0x07;  REG[0x13]: 0x00;  
REG[0x14]: 0x03;  REG[0x15]: 0x03;  REG[0x16]: 0x00;  REG[0x17]: 0x00;  
REG[0x18]: 0xf7;  REG[0x19]: 0xf7;  REG[0x1a]: 0x00;  REG[0x1b]: 0xbf;  
REG[0x1c]: 0xbf;  REG[0x1d]: 0xbf;  REG[0x1e]: 0xbf;  REG[0x1f]: 0xff;  
REG[0x20]: 0x0a;  REG[0x21]: 0x2a;  REG[0x22]: 0x0a;  REG[0x23]: 0x2a;  
REG[0x24]: 0x11;  REG[0x25]: 0xff;  REG[0x26]: 0xff;  REG[0x27]: 0x0a;  
REG[0x28]: 0xff;  REG[0x29]: 0xff;  REG[0x2a]: 0xff;  REG[0x2b]: 0x2a;  
REG[0x2c]: 0xff;  REG[0x2d]: 0xff;  REG[0x2e]: 0xff;  REG[0x2f]: 0x2a;  
REG[0x30]: 0xff;  REG[0x31]: 0xff;  REG[0x32]: 0xff;  REG[0x33]: 0x2a;  
REG[0x34]: 0xff;  REG[0x35]: 0xff;  REG[0x36]: 0xff;  REG[0x37]: 0x2a;  
REG[0x38]: 0xff;  REG[0x39]: 0xff;  REG[0x3a]: 0xff;  REG[0x3b]: 0xff;  
REG[0x3c]: 0xff;  REG[0x3d]: 0x72;  REG[0x3e]: 0x10;  REG[0x3f]: 0x01;  
REG[0x40]: 0x42;  REG[0x41]: 0x70;  REG[0x42]: 0x70;  REG[0x43]: 0x1c;  
REG[0x44]: 0x1c;  REG[0x45]: 0x1c;  REG[0x46]: 0x1c;  REG[0x47]: 0x08;  
REG[0x48]: 0x08;  REG[0x49]: 0x08;  REG[0x4a]: 0x08;  REG[0x4b]: 0x00;  
REG[0x4c]: 0x00;  REG[0x4d]: 0xff;  REG[0x4e]: 0xff; 

根据寄存器的值判断ES7210的工作状态,这个时候想到确实应该这样操作,FAE确实从其中发现了问题:

通过寄存器0x14和0x15发现处于Mute状态。

同时0x02寄存器值不对,没匹配到没有mclk的值。这才真正的问题所在,这个时候思考为什么会导致这样的情况发生?

FAE推测到 说明没执行到es7210_pcm_startup()或者录音没有跑这个7210的声卡。这个时候最终明白问题所在了。

目前ES7210只走初始化流程,并不走es7210_pcm_startup() 这个时候明白了问题所在。

在这里插入图片描述
在这里插入图片描述

当初最初设计的方案 :

● ES7210 只需要走初始化流程,不需要完全对接Alsa的应用层,因为ES7210 SOC 是被动的,最终是Broadcom SOC PCM 接口去ES7210 获取数据的。 ● Broadcom SOC 不需要通过Alsa 应用层,可以先通过bhDsphal.c应用程序调试看PCM是否又音频数据。

而ES7210中是对接的Alsa Lib接口,当通过arecord 录音的时候,Alsa Driver 是需要调用 es7210_pcm_startup(),而该函数的功能是启动延迟队列,执行 umute 操作。

通过这样的分析,解释了为什么ES7210 没数据的问题,主要是驱动初始化执行了mute操作,当arecoed的时候执行umut操作。而BCM6755 PCM 并没有走Alsa流程,导致一直处于mute状态。

代码语言:javascript
复制
 831 static struct snd_soc_dai_ops es7210_ops = {
 832         .startup = es7210_pcm_startup,
 833         .hw_params = es7210_pcm_hw_params,
 834         .set_fmt = es7210_set_dai_fmt,
 835         .set_sysclk = es7210_set_dai_sysclk,
 836         .digital_mute = es7210_mute,
 837 };
 
 
static int es7210_pcm_startup(struct snd_pcm_substream *substream,struct snd_soc_dai *dai)
{
    struct snd_soc_codec *codec = dai->codec;
    struct es7210_priv *es7210 =                        snd_soc_codec_get_drvdata(codec);
    if (es7210_init_reg == 0) {
        schedule_delayed_work(&es7210->pcm_pop_work, msecs_to_jiffies(100));
    }
        return 0;
}
// 延迟队列执行函数
 747 static void pcm_pop_work_events(struct work_struct *work)
 748 {
 749         printk("enter into %s\n", __func__);
 750         es7210_unmute();
 751         es7210_init_reg = 1;
 752 }

4. ES7210 Gain Channels Adjust

代码语言:javascript
复制
// 由于echo flag打印的寄存器不全,需要用 echo 0x47可以打印出全部寄存器
echo 0x4f > /sys/devices/platform/ubus@ff800000/ff802100.i2c/i2c-0/
0-0040/es7210_debug/es7210
//寄存器列表如下图 
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
//需要调整ES7210 通道的GAIN数值

#define ES7210_MIC1_GAIN_REG43		0x43
#define ES7210_MIC2_GAIN_REG44		0x44
#define ES7210_MIC3_GAIN_REG45		0x45
#define ES7210_MIC4_GAIN_REG46		0x46

#define ES7210_MIC_GAIN 0x1c  // need check hw design and channel
#define ES7210_AEC_GAIN 0x13  // need check hw design and channel

es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN, i2c_clt1[i]);
es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN, i2c_clt1[i]);
es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN, i2c_clt1[i]);
es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN, i2c_clt1[i]);

// 根据寄存器可以分析出,增益值现在为34.5dB, 根据算法的要求,麦克风的录音数据应该是不需要添加任何增益的,需要改为0
i2cset -f -y 0 0x40 0x43 0x10
i2cset -f -y 0 0x40 0x44 0x10
i2cset -f -y 0 0x40 0x45 0x10
i2cset -f -y 0 0x40 0x46 0x10
在这里插入图片描述
在这里插入图片描述

总结

调试ES7210 Driver 前后花费了一周的时间,过程中遇到的很多问题,所以每次交付的时间都Delay。主要这个Broadcom平台对接的是TDM接口以及走的ALSA 接口有区别,很多东西不是很熟悉,解决问题过程中需要去弄明白才能快速的解决问题。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、ES7210 简介
  • 二、ES7210 Driver Porting
    • 1. Broadcom 平台 集成 ES7210
      • 2. Broadcom 平台定制化参数
        • 3. 排查 ES7210 无法正常工作
          • 4. ES7210 Gain Channels Adjust
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档