ALSA声卡_从零编写之调试(基于优龙FS2410开发板,UDA1341声卡)

发布者:心有所属最新更新时间:2024-07-11 来源: elecfans关键字:调试 手机看文章 扫描二维码
随时随地手机看文章

一、实验环境

1.1 虚拟机环境

    a) Vmware版本:Vmware Workstation 12.5.7

    b) Ubuntu版本:9.10

    c) 内核版本:2.6.31.14

    d) toolchain版本:arm-linux-gcc 4.3.2

1.2 开发板

    优龙FS2410开发板,UDA1341声卡

    内核版本:3.4.2

二、调试过程记录

1. 编译声卡驱动,修改语法错误

2. 配置内核去掉原来的声卡驱动

    -> Device Drivers

    -> Sound card support

    -> Advanced Linux Sound Architecture

    -> ALSA for SoC audio support

        < > ASoC support for Samsung // CONFIG_SND_SOC_SAMSUNG 这项去掉勾选后,下面这项会连带自动消失

        < > SoC I2S Audio support UDA134X wired to a S3C24XX // CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X // s3c24xx_uda134x.c

3. 编译内核,然后通过nfs把新的内核下载到开发板,并启动

4. 把新的声卡驱动通过nfs拷贝到根文件系统里,然后安装

    insmod /alsa/driver/myalsa/platform/s3c2440_iis.ko

    insmod /alsa/driver/myalsa/platform/s3c2440_dma.ko

    insmod /alsa/driver/myalsa/codec/uda1341.ko

    insmod /alsa/driver/myalsa/machine/s3c2440_uda1341.ko

    mkdir /dev/snd

    cd /dev/snd/

    ln -s /dev/controlC0

    ln -s /dev/pcmC0D0p

    ln -s /dev/pcmC0D0c

    cd /

    为了方便,把以上这些语句放到prepare.sh里:


#!/bin/sh

#insmod alsa/driver/myalsa/platform/s3c2440_iis.ko

#insmod alsa/driver/myalsa/platform/s3c2440_dma.ko #这样写的话,执行时会报错:can’t insert s3c2440_iis.ko,invalid parameter c2440_iis.ko,原因待查

#insmod alsa/driver/myalsa/codec/uda1341.ko        #同上

#insmod alsa/driver/myalsa/machine/s3c2440_uda1341.ko #同上

mkdir -p /dev/snd && cd /dev/snd

cd /alsa/driver/myalsa/platform/  #得按照这种套路写才行?

insmod s3c2440_iis.ko

insmod s3c2440_dma.ko

cd /alsa/driver/myalsa/codec/

insmod uda1341.ko

#insmod wm8976.ko  #在JZ2440开发板上,codec驱动用wm8976.ko

cd /alsa/driver/myalsa/machine/

insmod s3c2440_uda1341.ko

cd /dev/snd && ln -s /dev/controlC0 && ln -s /dev/pcmC0D0p && ln -s /dev/pcmC0D0c

cd /


    执行prepare.sh,报错:

        soc-audio: coherent DMA mask is unset

        asoc: platform pcm constructor failed

        asoc: can’t create pcm 100ask_UDA1341:-12

    解决办法:

        参考内核自带的soundsocsamsungdma.c 的dma_new,在我们的s3c2440_dma.c的s3c2440_dma_new()中添加:

        if (!card->dev->dma_mask)

            card->dev->dma_mask = &dma_mask;

        if (!card->dev->coherent_dma_mask)

            card->dev->coherent_dma_mask = DMA_BIT_MASK(32);

5. aplay windows.wav后kernel oops了:

        LR指向snd_pcm_info,PC指向0

    猜测是在snd_pcm_info里调用了某个不存在的子函数,推测是在这里出错:substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);

    在《第2课第1.1_17节_ALSA声卡05_ASoC驱动框架》里,曾分析过这个ioctl的赋值是在soc_new_pcm里:

        soc_pcm_ops->ioctl = platform->driver->ops->ioctl;

    遂查看s3c2440_dma_ops,发现确实没有ioctl,遂参考内核的soundsocsamsungdma.c,加上 .ioctl = snd_pcm_lib_ioctl,

6. 再次aplay windows.wav,又kernel oops:

        pc is at copy_from_user

        backtrace:

        snd_pcm_lib_write_transfer

        copy_from_user

   查snd_pcm_lib_write_transfer:


...

else {

char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);

if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))

    return -EFAULT;

}

    而runtime->dma_area的赋值是在:


(sound/soc/samsung/dma.c)


dma_hw_params


    snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); //substream->dma_buffer是在dma_new里分配的


        struct snd_pcm_runtime *runtime = substream->runtime;


        runtime->dma_area = bufp->area; 


    查我们的s3c2440_dma_new,发现确实没有提供这个信息给内核,遂加上:


        buf->area = playback_dma_info.virt_addr;


        buf->bytes = playback_dma_info.buf_max_size;


7. 重新编译安装驱动,再次aplay windows.wav,这次没有oops,但报:aplay: pcm_write:1939:write error: Input/output error


    aplay windows.wav &  让它后台运行


    cat /proc/interrupts


    发现中断一次都没有发生,难办了☹!


8. 用devmem2来查看相关寄存器有没有被正确的设置:


   注:我在实验中没有用二期课程中的寄存器编辑器ker_wr和regeditor,因为在编译ker_rw的时候,报了一些错误,比如:


     error: asm/arch/regs-gpio.h: No such file or directory


     error: implicit declaration of function 'class_device_create'


     原因应该是原代码是针对2.6的内核编译的,和3.4.2内核不兼容。修改了代码之后,虽然编译通过,而且也能运行,但读不出寄存器的值,原因待查。


    / # devmem2 0x4B000080

     /dev/mem opened.

     Memory mapped at address 0xb6f9a000.

     Value at address 0x4B000080 (0xb6f9a080): 0x33B00000 //读DMA2_BASE_ADDR寄存器, 结果是有值的

     / # devmem2 0x55000000

     /dev/mem opened.

     Memory mapped at address 0xb6f50000.

     Value at address 0x55000000 (0xb6f50000): 0x100  //读IISCON寄存器,结果都是0 (bit8的1是默认值,代表Left/Right channel index (Read only))


    原因是:s3c2440的IIS的时钟没有使能?(排查思路是怎样的?是凭经验么?)


    解决办法:在s3c2440_iis_init()里加入:


    clk = clk_get(NULL, 'iis');


    clk_enable(clk);


    clk_put(clk);


    疑问:为什么裸板程序没有问题?


    答案:因为裸板程序开始运行时,板子的时钟都是默认使能的,而linux启动后,为了省电,默认都是关闭的!


9. 重新编译安装驱动,再次aplay windows.wav,仍然没有声音,


    cat /proc/interrupts


    中断还是没有发生


    / # devmem2 0x55000000

     /dev/mem opened.

     Memory mapped at address 0xb6fd8000.

     Value at address 0x55000000 (0xb6fd8000): 0x1A2 //读IISCON寄存器,bit0(iis_start)=0,表明iis传输没有启动

    解决办法:


    s3c2440_iis.c加入s3c2440_i2s_trigger、s3c2440_iis_start、s3c2440_iis_stop


10. 重新编译安装驱动,再次aplay windows.wav,这次终于有声音了!


image

   最后一个改进:


    虽然能播放声音,但会有周期性杂音。视频略去排查过程,直接上结论:load_dma_period()里,要把dma_regs->dcon的bit22设为1:noreload


    不知道排查思路是怎样的?


    推测是由于period_size比较小,导致音频数据被分割成了多块来传输,并且由于dcon的bit[22] =0即autoreload模式,所以每次传完一个period的数据后,dma会自动将src、dst、TC的值加载到CURR_SRC、CURR_DST、CURR_TC,并开始一次新的DMA传输(所以如果新的数据还来不及加载到CURR_SRC,则导致相当于重复播放上个period的数据)。而这之后才调用了DMA中断服务(硬件总是比软件快),进而load_dma_period()加载下一个period的数据到DMA的CURR_SRC。因此出现了播放时有周期性的杂音。


    如果把s3c2440_dma_hardware修改一下(仅用于实验),使其能在一个period里播完windows.wav,则也能消除周期性的杂音:


// .buffer_bytes_max = 128*1024,

// .period_bytes_min = PAGE_SIZE,

// .period_bytes_max = PAGE_SIZE*2,

.buffer_bytes_max = 1024*1024,

.period_bytes_min = 512*1024,

.period_bytes_max = 512*1024,

    另外,如果用内核自带的驱动,则不会出现上述问题。经初步分析,因为它利用了dcon的autoload功能,并且设计了一个比较复杂的框架,使得当一个period正在传输时,下一个period准备就绪。这样就能平滑的播放出声音。


三、参考资料


1. 韦东山 嵌入式Linux视频教程_3期项目实战之ALSA声卡:第2课第1.1_17节_ALSA声卡11_从零编写之调试


2. 李兰溪  S3C24XX DMA框架源码分析


3. rushzengjianmei  Alsa period_size/periods/buffer_size计算逻辑


关键字:调试 引用地址:ALSA声卡_从零编写之调试(基于优龙FS2410开发板,UDA1341声卡)

上一篇:ALSA声卡_从零编写之数据传输(基于优龙FS2410开发板,UDA1341声卡)
下一篇:ALSA声卡_从零编写之添加录音功能(基于优龙FS2410开发板,UDA1341声卡)

推荐阅读最新更新时间:2024-11-05 14:14

foc电机控制算法的调试经验总结
本文分享foc电机控制算法的调试经验,针对的场景是往一套新的控制板卡上移植一套电机控制软件。 具体调试过程是 发波= 电流反馈= 环路= 角度 将调试过程分解为以下步骤。 确认pwm模块正常 确认svpwm发波正常 确认电流反馈正常 引入电机角度 评估角度精度 下文中对移植调试的步骤分解,并给出每一个调试步骤的软件框图。 1、确认pwm模块正常 1.1、确认母线电压和实际测试值一致。 1.2、三相输出悬空,三相输出寄存器分别给固定占空比,测量各相对的波形,看是否和给定占空比一致。 2、确认svpwm发波正常 2.1、连接电机或其他三相对称负载。 2.2、参考以下框图,选取较低频率,生成固定转速强制角。给电压
[嵌入式]
foc电机控制算法的<font color='red'>调试</font>经验总结
ARM学习进阶(2)-SMARTARM2200调试初体验
去年8月购买了ZLG的SmartARM2000,因为工作的原因,一直没能抽空学习,到了春节前后终于可以抽空学习ARM了。我在 互动出版社 购买了一批书籍,希望能ARM快速入门并尽快提高。 开始进行ARM理论学习,我是参考ZLG的《ARM嵌入式系统基础教程》,同时我又温习了下C51的知识,希望在ARM中学习中能把C51也灵活掌握。 接着就是用SmartARM2000开发板做实验,需要安装ARM开发环境,具体步骤可参见本人的 《ARM学习进阶(1)-ARM开发环境的配置》 。按配套实验教程《ARM嵌入式系统实验教程(二)》的要求完成了第二章的基础实验,由于是直接运行配套光盘的DEMO源程序,每个实验都是针对某个
[单片机]
在MSP430的RAM中调试程序的研究
先说下我所使用的IDE及硬件,IDE为IAR集成开发环境,本人从学习单片机时就使用的IAR,CCS也用过,但觉得没IAR使用的顺手,如果是CCS爱好者请自己去研究下CCS中应该怎么设置才能在RAM中调试MSP430的程序,理论上也是很简单的。硬件为MSP-EXP430F5529LP,也就那块红色的MSP430F5529 LaunchPad 。至于为什么要在RAM中调试程序,自己去百度这样做的好处吧,我也懒得说了。 首先简单分析下MSP430F5529的启动过程,根据其官方数据手册所述,中断向量表如下: 可以看到中断向量表在0xFF80-0xFFFF,其中复位向量在0xFFFE-0xFFFF,一共两个字节,16位,系统上电
[单片机]
如何操做示波器触收遏制调试时分
  硬件触收   示波器中最多睹的触收是硬件触收。正在那类环境下,因为对触收遏制实时措置,所以即即是最罕见的触收事件也能够或许被捕捉。但是,一些事件很是复杂,以致于硬件触收回法捕捉。为了触收那些事件,需供将硬件触收(比方 Agilent Infiniuum 示波器上的 InfiniiScan)与硬件触收一起彩琴做。当遏制硬件触收时,硬件触收将搜刮捕捉到的事件迹线。假定找到此迹线,那么示波器便会遏制触收。但是,虽然此类触收伏从很强除夜,但出法遏制实时触收。对频仍产撕媚事件去讲,那出有甚么标题成绩,但对罕见事件而止,那倒是一个宏除夜的缺点。正在那类环境下,硬件触收将可以或许错掉踪除夜多数罕见事件真例,而示波器可以或许需供很少时分才气触
[测试测量]
泰克推出HDMI 2.0一致性测试及调试解决方案
新测试解决方案支持新“4K”视频监视器技术,帮助获得快速、一致和准确的结果。 中国 北京,2014年6月18日 —全球示波器市场的领导厂商---泰克公司日前宣布,其提出的新的实现方法 (MOI)被HDMI论坛批准为针对最近发布的HDMI 2.0标准的官方一致性测试解决方案,该方法采用全自动一致性测试和调制解决方案来支持该标准。该解决方案支持全面的HDMI 2.0发射机和接收机电气物理层 (PHY) 测试,可帮助确保来自该快速成长行业的不同供应商的产品间的互操作性。 作为得到广泛采用的HDMI 1.4a/b标准的后继者,HDMI 2.0旨在满足未来超高清(或4K)电视的带宽要求,同时支持使用现有电缆,以保证向后兼容性。它
[测试测量]
基于逻辑分析内核的FPGA电路内调试技术
  随着FPGA融入越来越多的能力,对有效调试工具的需求将变得至关重要。对内部可视能力的事前周密计划将能使研制组采用正确的调试战略,以更快完成他们的设计任务。   “我知道我的设计中存在一个问题,但我没有很快找到问题所需要的内部可视能力。”由于缺乏足够的内部可视能力,调试FPGA基系统可能会受挫。使用通常包含整个系统的较大FPGA时,调试的可视能力成为很大的问题。为获得内部可视能力,设计工程师必须把一些引脚专门用作调试引脚,而不是实际用于设计。哪些工具可用于进行内部FPGA迹线测量?又有哪些技术可用固定的引脚数最大化内部可视能力?   FPGA设计工程师有两种进行内部迹线测量的方法:   1. 把结点路由至引脚,使用传统的外部
[医疗电子]
基于逻辑分析内核的FPGA电路内<font color='red'>调试</font>技术
基于AT89C51的数据采集系统设计新方法
0 引言 近年来,随着制造技术的发展,单片机的价格越来越低,性能却不断提升,因而其应用范围也越来越广。然而在开发基于单片机的应用系统时,传统方法一般都需要大量的硬件设备,这些设备极易损坏而且携带不方便。为此,本文基于AT89C51数据采集系统详细说明了如何利用Pro-teus和两款串口仿真软件来进行单片机程序及外围电路的仿真设计。采用该方法可以大大简化硬件电路测试和系统调试过程,对单片机系统开发具有指导意义。本文介绍的基于AT89C5l单片机的数据采集系统能实现16路信号输入,每一路都是0~10 mV的信号,每秒钟采集一遍,从而将数据传给上位PC计算机。 1 硬件设计 1.1 主控芯片 AT89C51是一种带有4 KB闪烁
[应用]
基于U盘和单片机的FPGA配置
引 言 FPGA广泛应用在电子通信领域,其安全性引起了注意,本文针对安全配置提出了解决方案。 现场可编程门阵列FPGA(Field Programmablc Gate Array)是基于门阵列方式为用户提供可编程资源的,其内部逻辑结构的形成是由配置数据决定的。采用在线可重配置方式ICR(In-Circuit Reconfigurability)将这些配置数据配置到FPGA内部SRAM中,但由于SRAM的易失性,每次上电时,都必须对FPGA重新进行配置,从而实现用户编程所要实现的功能。 以前的设计大多是将配置数据存放在FPGA组成的系统上,本文提出将配置数据存放在使用者自己携带的外部存储器(如可加密的U盘)中。使用前将U盘接入
[应用]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved