第31卷 第2期2008年4月电子器件Ch in es e Jo u rnal Of Electro n Devi cesVol.31 No.2Apr.2008Design and Implementation of Audio Driver for Embedded Linux SystemYU Yue,YA O G uo -liang*(N ational A S I C S ystem Eng ine ering Center ,S outhe ast Unive rsity ,N anj ing 210096,China)Abstract:This paper intro duces the fundam ental principle and architecture of the audio system w hich con -sists of the CODEC UCB1400and the 805puls,and describes the design of audio dev ice dr iv er based on Audio Codec .97for Embedded Linux System.The paper focuses o n the implementatio n of the DM A trans -port and ioctl interface.T he audio dr iv e is running w ell in actual Embedded Linux system equipments.Key words:805plus;embedded Linux;Audio A C .97driver;DM A;ioctl interfaceEEACC :1130B嵌入式Linux 系统中音频驱动的设计与实现虞 跃,姚国良*(东南大学国家专用集成电路系统工程中心,南京210096)收稿日期:2007-07-09作者简介:虞 跃(1982-),男,东南大学电子工程系国家专用集成电路工程技术研究中心硕士研究生,研究方向为嵌入式系统设计;姚国良(1979-),男,东南大学电子工程系博士研究生,yuyueo@.摘 要:介绍了由805puls 处理器和U CB1400编解码芯片构成的音频系统体系结构及工作原理,接着阐述了嵌入式Linux操作系统下基于A C .97协议标准的音频设备驱动程序的设计与实现。
其中着重讲述了采用循环缓冲区进行音频数据的DM A 传输流程以及ioctl 接口的实现。
此设计方案已在嵌入式L inux 系统中得到使用,运行效果良好。
关键词:805plus;嵌入式L inux ;AC .97音频驱动;DM A;ioctl 接口中图分类号:TP391文献标识码:A 文章编号:1005-9490(2008)02-0709-03嵌入式音频系统广泛应用于GPS 自动导航、PDA,3G 手机等移动信息终端,具备播放、录音功能的音频系统的应用使得移动信息终端上视听娱乐IP 电话、音频录制等成为可能,并推动了移动信息终端设备的发展。
在软件上,嵌入式操作系统的新兴力量Linux 的开源性,内核可定制等优点吸引了许多的开发者与开发商。
它是个和U nix 相似、以核心为基础的、完全内存保护、多任务多进程的操作系统。
支持广泛的计算机硬件,包括X86,A lpha,Sparc,M IPS,PPC,ARM ,NEC,MOT OROLA 等现有的大部分芯片[1]。
本文针对805puls 微处理器选用Philips 公司的编解码芯片(CODEC)U CB1400,构建了基于Au -dio Codec .97(AC .97)标准的音频系统。
并介绍了该音频系统在Linux 操作系统2.4.19内核下驱动程序的实现技术。
1 音频系统构架1.1 微处理器805plus805plus 是东南大学ASIC 系统工程技术研究中心和北京大学微处理器研究开发中心共同设计和开发的32bit 嵌入式微处理器,是采用H ar vard 结构的RISC 处理器。
内部采用五级流水线结构,兼容16bit 和32bit 的指令系统805plus 嵌入式微处理器集成了存储接口EMI,时钟和功耗管理PM C,中断控制器INTC,通用定时器T IM ER,脉宽调制器PWM,实时时钟RT C,通用串口UA RT,LCD 控制器LCDC,AC .97控制器,同步外设接口SPI 。
1.2 AC .97协议标准[2]AC'97协议标准是一套关于A C'97数字音频处理(AC'97Digital Controller)、AC '97数字串口(AC-Link)、A C'97编、解码以及输入,输出支持(A C'97CODEC)的协议组。
AC '97规范中并没有定义AC -Link 的主控端,因此符合AC'97规范的UCB1400也只是作为一个编解码芯片接到了805puls 的AC .97控制器(AC'97Co ntro ller Unit)上面,该控制单元也符合AC'97规范,并且还支持AC -Link 。
它们的连接方式如图1所示。
图1 U CB1400通过A C -L ink 连接到805puls 的AC .97控制器上[3]需要注意的是对UCB1400芯片所有的操作都必须通过AC -Link 来进行,AC -Link 接口由5针数字串口组成:同步信号SYNC,位时钟信号BIT _CLK,数据输出SDAT A -OU T,数据输入SDATA _IN,RESET 信号。
一个音频帧包含帧头和数据两部分。
SYNC 信号的上升沿标识音频帧的开始,下降沿标识数据帧的开始。
在音频帧期间,当BIT _CLK 信号上升沿时发送数据,下降沿时接收数据,从而实现全双工的数据传输。
AC .97控制器提供基于A C -Link 协议通信的同步机制AC .97控制器与U CB1400之间的PCM 音频数据传输,以及对UCB1400片上寄存器的读,写都遵循了AC -Link 数据串口协议标准。
1.3 音频系统的构架如图2所示,整个音频系统可以简略地分为三个部分:CPU (805Plus)和主存(SDRAM ),CODEC 芯片(UCB1400),外设(麦克风和扬声器)。
图2 音频系统的构架图U CB 1400芯片中的DA (Digital to Analo g)和AD (Analo g to Digital)分别完成数字信号到模拟信号以及模拟信号到数字信号的转换,因此对于放音来说,用户进程中CPU 将音频文件解码成PCM 编码,音频管理模块主要就是将用户进程中的PCM 编码的数据通过DM A 通道写入AC .97控制器,然后AC .97控制器通过AC -Link 传到U CB 1400,由U CB1400来对其进行DA 转换,最后送到线性输出信号线上到扬声器,最终完成声音播放,录音部分原理一样,是上述过程的逆过程[4]。
2 音频驱动的设计与实现设备驱动程序中需要完成的任务包括:对设备以及对应资源初始化和卸载;控制音频数据在硬件中流动,并为音频应用提供标准接口。
读取应用程序传送给设备文件的数据并回送应用程序请求的数据。
这需要在用户空间、内核空间、总线及外设之间传输数据[5]。
2.1 初始化和卸载设备初始化是为了确保整个硬件能够正确的运转。
驱动程序首先在init_soundco re 中向内核注册了名为/mixer 0和/dsp 0的2个设备,主设备号为14,次设备号分别为0和3。
然后将A C .97控制器寄存器和GPIO 等相关寄存器到虚拟地址空间并配置AC .97控制器以及AC -Link 相关接口。
最后调用初始化音频设备:包括初始化UCB1400芯片并配置其基本寄存器。
上述工作完成后向内核注册DM A 中断。
初始化出错或设备卸载时调用卸载功能函数。
卸载时要停止DMA 通道,清除中断允许,up 信号量,关闭音频设备。
还必须释放驱动程序使用的各种系统资源包括DMA 缓冲区,AC .97,DMA 中断等。
2.2 CODEC 芯片操作接口和竞争操作系统中对于同步的控制一般采用锁和信号灯。
在Linux 中通用的防止并发数据访问的方式一般有:循环缓冲区、进行互斥的自旋锁以及使用p/v 操作的信号量[6]。
AC .97规范中AC -Link 属于连接AC .97控制器和CODEC 芯片的唯一通道,各模块均要通过它与U CB1400进行通讯,因此它属于一种临界资源。
音频驱动中要负责接收上层各模块的读写请求,然后对AC c 97控制器进行控制,其中还包含了对AC c 97控制器以及AC -link 的初始化、处理控制器自身的中断以及负责AC -link 这一临界资源的互斥使用。
其中实现的核心函数是读写函数ac97_read()710电 子 器 件第31卷和ac97_w rite(),所有对于CODEC 芯片的操作最终都由这两个函数完成。
为了保证读写函数的原始性,接口中加入了信号量机制,以写寄存器为例,当把一个值写入U CB 1400寄存器的地址空间,操作前先dow n(&CAR_mutex )这个信号量,然后再写寄存器,如果成功,在AC .97控制器中会产生一个标记,该操作正确得以执行,再up(&CAR_mutex ),完成写操作。
这部分仅以dow n()和UP()进行分析,给出整个实现的伪码:dow n(){保存程序状态字;关中断;semapho re--;恢复状态寄存器(开中断);if(sem aphore<0)挂入等待队列,转进程调度;}up(){保存程序状态字;关中断;sem aphore++;恢复状态寄存器(开中断);if(sem aphore<=0)唤醒等待队列;}2.3 DMA 传输由于音频应用对实时性有很高的要求,且需要处理的数据量较大,所以必须合理分配资源,使用合适的算法。
本方案中DM A 的数据缓冲区是用co nsistent_alloc()函数申请的一块16@12kbit 的连续的内存区域,然后用描述符的方式将这16个块形成一个循环链表。
每个缓冲块都有一个805_dm a _desc *dma_desc;的数据结构:ty pedef str uct {volatile u32ddadr;/*指向下一个描述符*/volatile u32dsadr;/*DMA 传输的原地址,是物理地址*/volatile u32dtadr;/*DM A 传输的目的地址,是物理地址*/}805_dma_desc;因为CPU 解码和DMA 传输是不相互影响的,所以有一个16@12kbit 的循环数据缓冲区会加快软件运行的效率,这样从用户空间将音频解码的数据拷贝到DM A 缓冲区时,不致使音频驱动在数据缓冲区上出现瓶颈[7]。