ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

韦东山嵌入式Linux视频教程_3期项目实战之ALSA声卡_从零编写之添加录音功能(基于优龙FS2410开发板,UDA1341声卡)

2020-02-19 23:53:39  阅读:587  来源: 互联网

标签:dma snd struct 优龙 substream 开发板 声卡 s3c2440 s3c


一、实验环境

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

二、修改代码

2.1 修改s3c2440_dma.c

1) static volatile struct s3c_dma_regs *dma_regs;

    改为:

    static volatile struct s3c_dma_regs *dma_regs_ch1; //for playback
     static volatile struct s3c_dma_regs *dma_regs_ch2; //for capture

    相应的,修改所有涉及到DMA寄存器操作的函数,根据substream->stream的类型,来选择对应的dma_regs_chx,

2) 添加preallocate_dma_buffer(),修改s3c2440_dma_new(),为playback substream和capture substream分别分配DMA缓冲区

3) 把原先定义的全局变量struct s3c2440_dma_info playback_dma_info改为在s3c2440_dma_open()里

static int s3c2440_dma_open(struct snd_pcm_substream *substream)
{

    struct s3c2440_dma_info *prtd;
    ...
    prtd = kzalloc(sizeof(struct s3c2440_dma_info), GFP_KERNEL);
    runtime->private_data = prtd;
    ...
}

    相应的,修改所有访问playback_dma_info的函数,改为访问substream->runtime->private_data

2.2(这是后来调试时才发现要加的)

   参考内核的s3c24xx-i2s.c,修改s3c2440-i2s.c:

   添加s3c2440_snd_txctrl()、s3c2440_snd_rxctrl(),然后修改s3c2440_i2s_trigger()

static int s3c2440_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{
    int ret = 0;
    switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
	    //s3c2440_iis_start();
	    if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		s3c2440_snd_rxctrl(1);
	    else
		s3c2440_snd_txctrl(1);
	    break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	default:
            //s3c2440_iis_stop();
	    if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		s3c2440_snd_rxctrl(0);
	    else
		s3c2440_snd_txctrl(0);
	    ret = -EINVAL;
	    break;
    }

exit_err:
    return ret;
}

三、调试

1. 编译、安装驱动,过程略,详见:韦东山嵌入式Linux视频教程_3期项目实战之ALSA声卡_从零编写之调试(基于优龙FS2410开发板,UDA1341声卡)

2. 执行aplay windows.wav 后,耳机里是高频杂音!

    / # cat /proc/interrupts 可见确实发生了DMA中断

    CPU0

    25: 0 s3c s3c2410-wdt

    30: 26510 s3c S3C2410 Timer Tick

    35: 2 s3c  myalsa for playback

    …

    经查,需要在s3c2440_dma_hw_params()中加上:

    prtd->phy_addr = substream->dma_buffer.addr;

    原先是 playback_dma_info.phy_addr,在s3c2440_dma_new()中直接作为dma_alloc_writecombine的输出参数被初始化的:

    playback_dma_info.virt_addr = (unsigned int)dma_alloc_writecombine(pcm->card->dev, s3c2440_dma_hardware.buffer_bytes_max,
                                                                                                                     &playback_dma_info.phy_addr, GFP_KERNEL);

    重新编译加载驱动,然后再次执行aplay windows.wav 后,耳机里终于能听到声音了!

3. 执行arecord -d 5 my1.wav,但过了5秒钟没有任何反应!强制ctrl-c后,报:

    Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono

    ^CAborted by signal Interrupt...

    arecord: pcm_read:2031: read error: Interrupted system call

    / # cat /proc/interrupts 没有发生任何DMA中断

4. 用devmem2 查看寄存器DISRC1(0x4B000040), DIDST1(0x4B000048), IISCON(0x55000000)的值:

  (注:双箭头的左边是执行arecord之前的值,右边是执行arecord后的值)

    / # devmem2 0x4B000040

      Value at address 0x4B000040 (0xb6fba040): 0x0 <==> 0x55000010

    / # devmem2 0x4B000048

    Value at address 0x4B000048 (0xb6f46048): 0x0 <==> 0x33B80000

    / # devmem2 0x55000000

    Value at address 0x55000000 (0xb6fc6000): 0x100<==> 0x122 Bit[0]=0 即IIS interface disable,说明这位的1没写进去!

    查内核自带的sound\soc\samsung\ s3c24xx-i2s.c,发现除了要操作IISCON之外,还要操作IISMOD、IISFCO。

    遂参考内核的s3c24xx-i2s.c,修改s3c2440-i2s.c:

    添加s3c2440_snd_txctrl()、s3c2440_snd_rxctrl(),然后修改s3c2440_i2s_trigger()。

5. 重新编译加载驱动,然后再次执行arecord -d 5 my1.wav,这次5秒后正常退出,没有报错。

    查看IISCON的值:

    / # devmem2 0x55000000

    Value at address 0x55000000 (0xb6fbd000): 0x10B ,说明bit[0]的1写进去了!

    / # cat /proc/interrupts

    CPU0

    25: 0 s3c s3c2410-wdt

    30: 139493 s3c S3C2410 Timer Tick

    34: 1 s3c  my alsa for capture  说明DMA中断发生了

    执行aplay my1.wav,能够播放声音!说明录音成功!

6. 在JZ2440,wm8976声卡上测试,也是成功的。而程序的修改,只需要把s3c2440_dma.c和s3c2440_iis.c拷贝覆盖过去即可。

附:源代码

myalsa_FS2410_can_record

myalsa_JZ2440_can_record

四、参考资料

1. 韦东山 嵌入式Linux视频教程_3期项目实战之ALSA声卡

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

3. linux 3.4.2 内核源代码

4. s3c2440数据手册

标签:dma,snd,struct,优龙,substream,开发板,声卡,s3c2440,s3c
来源: https://www.cnblogs.com/normalmanzhao2003/p/12333864.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有