VOIP的基本原理:通过声音的压缩算法对声音数据编码进行压缩处理,然后把这些声音数据进行打包,经过IP网络把数据包送至接收地,再把这些声音数据包重组,经过解压处理后,还原成原来的声音信号,从而达到由互联网传送声音的目的。VxWorks是常用的嵌入式操作系统,基于VxWorks的嵌入式开发应用非常广泛。本文试图在小范围的以太网环境实现VxWorks操作系统下基于声卡的VOIP的尝试,为某些需要声卡的嵌入式开发提供支持。
1 VxWorks及声卡简介
VxWorks是由风河(Wind River System Inc.)公司专门为实时嵌入式系统设计开发的一套具有微内核、高性能、可伸缩的实时操作系统,为程序员提供了高效的实时任务高度、中断管理,实时的系统资源以及实时的任务间通信,并能够根据用户的需求进行组合。应用程序员可以将尽可能多的精力放在应用程序本身,而不必再去关心系统资源的管理。VxWorks是一种功能强大而且比较复杂的操作系统,VxWorks只占用了很小的存储空间,并可高度裁减,保证了系统能以较高的效率运行。VxWorks的优秀特性为编写应用程序和设备驱动程序提供了极大的便利。在VxWorks下,设备驱动程序既可以嵌入到内核中随系统一起启动,也可以作为可加载模块在系统启动之后运行。本文的声卡驱动程序采用后一种方式。
本文选用的声卡是Cirrus Logic公司的CS4281/AC′97。这是一款功能强大的声卡,他主要由CS4281和C2S4297A芯片组成。CS4297A是符合AC′97(Audio Codec′97)规范的一个混合***。他负责对原始声音信号的采样混音处理,把接收的模拟声音信号转换成数字信号;也将接收的数字音频信号通过一种特殊的音频算法转换成模拟信号。CS4281是一个PCI-Ac′97数字控制器,他提供串行AC′97编解码器(如CS4297A)与并行PCI总线之间的接口。
2 总体设计
程序划分为两个模块:(1) CS4281声卡的VxWorksPCI驱动,实现声音的录音和播放;(2) 通信模块,该模块负责接收驱动模块的声音数据,并打包通过以太网发送;接收以太网的数据,解包成声音数据传给驱动模块。
低层是声卡驱动:从麦克风进来的声音在这里记录,并发送PCM抽样声音数据到上层;同时,声音数据从上层传来并发送到声卡播放,通过耳机输出。主要有以下几个函数:PCI配置空间的分配,完成声卡的查找及内存映射;CS428l及CS4297的初始化,进行一系列的硬件初始化;DMA缓冲区的分配,用来缓存声卡驱动和通信模块之间的声音数据;取样率和格式的设置,选择合适的取样率及格式;声音系统的打开及关闭,控制录音及播放功能的开关;中断处理函数,声卡驱动和通信模块之间通过中断来进行数据的存取。
上层是通信部分:声音数据在这里打包成分组通过网卡发送出去,从网卡接收来的数据在此解包并交给声卡驱动,数据经过以太网的发送和接收通过调用Socket来实现。
2.1 确定取样率
结合实际的实验环境,从诸多的取样率和格式中,选择11025 Hz取样频率、8 b单声道。计算最低的数据传输率:
2.2 设置缓冲区
如果网络中通信量变化较大,将产生时延抖动。需要设置两个缓冲区用来在发送数据和接收数据时进行缓存,以减轻时延抖动的影响,保证通信质量。缓冲区大小应适当,如果太小,将会造成数据丢失;如果太大,抖动时延将增长。
在x86结构中,页面大小是4 kB。这对DMA缓冲大小是个限制,因为DMA需要位于一个内存页面中来保持缓冲区的连续性,且要适应基于UDP的Socket通信,我们确定播放DMA缓冲和录音DMA缓冲大小都为2 kB,并且用“乒乓”技术在这两个缓冲区间传输,那么每1 kB,将有一个播放中断和录音中断。1 s中的中断次数为:1×11k/1k△11。
3 声卡驱动程序
3.1 PCI局部总线
本文所选用的声卡是Cirrus Logic公司的CS4281/AC′97 PCI声卡,作为一个PCI设备,在设备的初始化阶段,他和一般的PCI设备的步骤相同。
每一个PCI总线设备都有一个配置寄存器空间,他使目标设备的配置简单易行。配置空间是一个容量为256 B并具有特定结构的地址空间。配置寄存器是PCI设备的硬件与PCI设备的初始化软件及错误处理软件之间的信息交换区,以便软件对PCI设备进行识别和控制以及PCI设备向软件反映设备状态和要求。该空间分为头标区和设备关联区两部分。一个设备的配置空间不仅在系统自举时可以访问,而且在其他时间内也可以访问。
3.2 声卡的驱动结构及流程
(1) 声卡的探测以及入口
VxWorks BSP在syslib.c中探测并初始化系统中的PCI设备,检测设备的I/O映射地址,内存映射地址以及中断向量和级别,这些硬件参数对于主芯片的读写和挂接中断起到至关重要的作用。因此,在这里加入声卡的探测模块。然后将探测到的参数传递给驱动程序入口函数。
在声卡的探测模块中,利用的是CS4281/AC′97的厂商标识和设备标识,得到他的功能号、总线号和设备号.然后配置他的PCI配置空间,将声卡的寄存器映射。最后得到声卡内存映射基地址以及中断向量和级别。
(2) 入口函数
入口函数主要完成CS4281控制芯片和CS4297编解码芯片的初始化,DMA缓冲区内存分配,设置采样率和格式及挂接中断等任务。
CS4281芯片的初始化要严格按照文献的说明顺序进行。CS4297编解码芯片的初始化主要完成耳机和麦克风的选择、打开,音量设置等任务,涉及到的寄存器有PCM_OUT_VOLUME,MASTER_VOLUME,HEAD-PHONE_VOLUME,GENERAL_PURPOSF,MICRO-PHONE_VOLUME,INPUT_MUX_SELECT,RE-CORD_GAIN,GENERAL_PURPOSE。为DMA播放和录音缓冲区分配连续的2 kB内存空间,把分配的内存空间基地址写入DMA基地址寄存器。在本文中,我们选择的是8 b单声道格式和11 025 Hz取样频率,经过计算,把相应的值写入DMA引擎模式寄存器,把采样率写人DACSR和ADCSR。最后利用探测模块中取得的中断向量和中断级把中断号和中断处理函数挂接在一起。
(3) 声音系统的启动和关闭
该模块主要完成录音的开启和关闭、播放的开启和关闭。录音的开启即把0写入DMA引擎控制寄存器1中的MSK位,且使能中断;录音的关闭即把1写入DMA引擎控制寄存器1中的。MSK位。播放的开启即把0写人DMA引擎控制寄存器0中的MSK位,且使能中断;播放的关闭即把1写入DMA引擎控制寄存器0中的MSK位。
(4) 中断处理程序
CS4281有一个中断状态寄存器和一个中断屏蔽寄存器,他们对应位意义相同。中断状态寄存器反映了声卡能产生的几种中断。一旦有中断发生,分析中断状态寄存器,判断中断类型,再做相应的处理。根据我们的设计,如果是播放中断则释放播放信号量,促使上层软件拷贝声音数据至下层软件;如果是录音中断则释放录音信号量,促使上层软件从下层软件取走已到达的声音数据。最后设置中断结束标志。
(5) 播放和发送时的数据流
播放时的数据流。声卡中的播放缓冲(上文中所设的DMA缓冲)和FIFO0(从格式化器formatter接收声音数据,按先入先出方式存储,供CS4297芯片播放)之间数据传输由DMA0控制。DMA0引擎尽量保持FIFO0满。播放缓冲是个2 kB的内存,他的起始地址被写进DMA0基地址寄存器(DBA0)。2 047 B(计数应比所分配的字节数小1,因为中断发生于roll-unders模式下)写入DMA0基本计数寄存器(DBC0),DMA0引擎控制从播放缓冲中读入的字节数。当播放缓冲半空或空,将产生一个中断,促使从上层软件取数据。
录音时的数据流。声卡中的录音缓冲和FIFO1(从CS4297芯片接收声音数据,按先入先出方式存储,传给格式化器formatter)之间数据传送受控于DMA1。DMA1引擎尽量保持FIFO1为空,他同样也计算写进录音缓冲的字节数。当录音缓冲半满或满,将产生一个中断,促使上层软件把数据取走。
4 UDP通信
4.1 UDP协议
在以太网设施基础上,VxWorks使用因特网组件TCP/IP提供的端到端的传输能力在位于不同的主机上的任务间传输用户数据。在VxWorks中,使用Socket作为应用程序和TCP/IP协议的接口。Socket有2种基本类型:可靠的数据流SOCK_STREAM,使用TCP协议;数据报SOCK_DGRAM,使用UDP协议。
UDP相对于TCP有以下一些优点:
(1) UDP的报文短,利于减小传输时延;
(2) UDP是无连接协议,发送数据前不需要建立连接,适合于声音数据这种实时性要求高的应用;
(3) UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。
UDP的这些优点对于声音数据的实时传输非常重要,这些优点将保证传输尽可能有一个短时延、恒定的速度,因此选择UDP。
在无连接的Socket中,在通信的两端分别创建客户机端和服务器端,通信双方在整个过程中是平等的,双方直接通过Socket调用来发送或接收数据报。
UdpClient模块:创建客户端Socket;初始化服务器端地址;FOREVER{调用UDP发送模块;发送数据到服务器}。
UdpServer模块:创建本地地址;创建服务器端Sock-et;把Socket和本地地址绑定起来;FOREVER{接收数据;调用UDP接收模块)。
4.2 UDP发送
发送模块等待录音信号量。如果获得,表示一些新的数据在录音缓冲中已有效。将把新数据从录音缓冲拷入上层软件存储区,然后通过Socket把他发送到另一端主机。如果上层软件中的存储区满,丢弃旧分组存入新分组。
4.3 UDP接收
接收模块等待从Socket来的数据。如果获得播放信号量,表示播放缓冲区中的数据已被播放,将把上层软件存储区中的数据拷入播放缓冲;否则,任务将被挂起。如果上层软件中的存储区满,丢弃旧分组存入新分组。
5 遇到的主要问题
在本文所搭建的环境中,能较好地实现两块声卡之间的通话。开发过程中,主要遇到两个问题:
(1) 声卡中没有声音数据。声卡的FIFO缓冲区及DMA缓冲区中均没有数据。经分析查出:CS4297芯片中关于耳机和麦克风的寄存器没有打开和选中,耳机和麦克风一直处于“mute”状态。关掉“mute‘’后,问题解决。
(2) 不能产生中断。DMA缓冲区中已有数据,根据程序设计,此时应产生中断,由上层通信模块取走声音数据,但中断一直不能产生。经分析原因为:在声卡探测程序段获得的中断级直接用作中继号来挂接中断。解决方法:通过中断级来获取中断向量,再获取中断号,用来挂接中断处理程序。
VOIP的基本原理:通过声音的压缩算法对声音数据编码进行压缩处理,然后把这些声音数据进行打包,经过IP网络把数据包送至接收地,再把这些声音数据包重组,经过解压处理后,还原成原来的声音信号,从而达到由互联网传送声音的目的。VxWorks是常用的嵌入式操作系统,基于VxWorks的嵌入式开发应用非常广泛。本文试图在小范围的以太网环境实现VxWorks操作系统下基于声卡的VOIP的尝试,为某些需要声卡的嵌入式开发提供支持。
1 VxWorks及声卡简介
VxWorks是由风河(Wind River System Inc.)公司专门为实时嵌入式系统设计开发的一套具有微内核、高性能、可伸缩的实时操作系统,为程序员提供了高效的实时任务高度、中断管理,实时的系统资源以及实时的任务间通信,并能够根据用户的需求进行组合。应用程序员可以将尽可能多的精力放在应用程序本身,而不必再去关心系统资源的管理。VxWorks是一种功能强大而且比较复杂的操作系统,VxWorks只占用了很小的存储空间,并可高度裁减,保证了系统能以较高的效率运行。VxWorks的优秀特性为编写应用程序和设备驱动程序提供了极大的便利。在VxWorks下,设备驱动程序既可以嵌入到内核中随系统一起启动,也可以作为可加载模块在系统启动之后运行。本文的声卡驱动程序采用后一种方式。
本文选用的声卡是Cirrus Logic公司的CS4281/AC′97。这是一款功能强大的声卡,他主要由CS4281和C2S4297A芯片组成。CS4297A是符合AC′97(Audio Codec′97)规范的一个混合***。他负责对原始声音信号的采样混音处理,把接收的模拟声音信号转换成数字信号;也将接收的数字音频信号通过一种特殊的音频算法转换成模拟信号。CS4281是一个PCI-Ac′97数字控制器,他提供串行AC′97编解码器(如CS4297A)与并行PCI总线之间的接口。
2 总体设计
程序划分为两个模块:(1) CS4281声卡的VxWorksPCI驱动,实现声音的录音和播放;(2) 通信模块,该模块负责接收驱动模块的声音数据,并打包通过以太网发送;接收以太网的数据,解包成声音数据传给驱动模块。
低层是声卡驱动:从麦克风进来的声音在这里记录,并发送PCM抽样声音数据到上层;同时,声音数据从上层传来并发送到声卡播放,通过耳机输出。主要有以下几个函数:PCI配置空间的分配,完成声卡的查找及内存映射;CS428l及CS4297的初始化,进行一系列的硬件初始化;DMA缓冲区的分配,用来缓存声卡驱动和通信模块之间的声音数据;取样率和格式的设置,选择合适的取样率及格式;声音系统的打开及关闭,控制录音及播放功能的开关;中断处理函数,声卡驱动和通信模块之间通过中断来进行数据的存取。
上层是通信部分:声音数据在这里打包成分组通过网卡发送出去,从网卡接收来的数据在此解包并交给声卡驱动,数据经过以太网的发送和接收通过调用Socket来实现。
2.1 确定取样率
结合实际的实验环境,从诸多的取样率和格式中,选择11025 Hz取样频率、8 b单声道。计算最低的数据传输率:
2.2 设置缓冲区
如果网络中通信量变化较大,将产生时延抖动。需要设置两个缓冲区用来在发送数据和接收数据时进行缓存,以减轻时延抖动的影响,保证通信质量。缓冲区大小应适当,如果太小,将会造成数据丢失;如果太大,抖动时延将增长。
在x86结构中,页面大小是4 kB。这对DMA缓冲大小是个限制,因为DMA需要位于一个内存页面中来保持缓冲区的连续性,且要适应基于UDP的Socket通信,我们确定播放DMA缓冲和录音DMA缓冲大小都为2 kB,并且用“乒乓”技术在这两个缓冲区间传输,那么每1 kB,将有一个播放中断和录音中断。1 s中的中断次数为:1×11k/1k△11。
3 声卡驱动程序
3.1 PCI局部总线
本文所选用的声卡是Cirrus Logic公司的CS4281/AC′97 PCI声卡,作为一个PCI设备,在设备的初始化阶段,他和一般的PCI设备的步骤相同。
每一个PCI总线设备都有一个配置寄存器空间,他使目标设备的配置简单易行。配置空间是一个容量为256 B并具有特定结构的地址空间。配置寄存器是PCI设备的硬件与PCI设备的初始化软件及错误处理软件之间的信息交换区,以便软件对PCI设备进行识别和控制以及PCI设备向软件反映设备状态和要求。该空间分为头标区和设备关联区两部分。一个设备的配置空间不仅在系统自举时可以访问,而且在其他时间内也可以访问。
3.2 声卡的驱动结构及流程
(1) 声卡的探测以及入口
VxWorks BSP在syslib.c中探测并初始化系统中的PCI设备,检测设备的I/O映射地址,内存映射地址以及中断向量和级别,这些硬件参数对于主芯片的读写和挂接中断起到至关重要的作用。因此,在这里加入声卡的探测模块。然后将探测到的参数传递给驱动程序入口函数。
在声卡的探测模块中,利用的是CS4281/AC′97的厂商标识和设备标识,得到他的功能号、总线号和设备号.然后配置他的PCI配置空间,将声卡的寄存器映射。最后得到声卡内存映射基地址以及中断向量和级别。
(2) 入口函数
入口函数主要完成CS4281控制芯片和CS4297编解码芯片的初始化,DMA缓冲区内存分配,设置采样率和格式及挂接中断等任务。
CS4281芯片的初始化要严格按照文献的说明顺序进行。CS4297编解码芯片的初始化主要完成耳机和麦克风的选择、打开,音量设置等任务,涉及到的寄存器有PCM_OUT_VOLUME,MASTER_VOLUME,HEAD-PHONE_VOLUME,GENERAL_PURPOSF,MICRO-PHONE_VOLUME,INPUT_MUX_SELECT,RE-CORD_GAIN,GENERAL_PURPOSE。为DMA播放和录音缓冲区分配连续的2 kB内存空间,把分配的内存空间基地址写入DMA基地址寄存器。在本文中,我们选择的是8 b单声道格式和11 025 Hz取样频率,经过计算,把相应的值写入DMA引擎模式寄存器,把采样率写人DACSR和ADCSR。最后利用探测模块中取得的中断向量和中断级把中断号和中断处理函数挂接在一起。
(3) 声音系统的启动和关闭
该模块主要完成录音的开启和关闭、播放的开启和关闭。录音的开启即把0写入DMA引擎控制寄存器1中的MSK位,且使能中断;录音的关闭即把1写入DMA引擎控制寄存器1中的。MSK位。播放的开启即把0写人DMA引擎控制寄存器0中的MSK位,且使能中断;播放的关闭即把1写入DMA引擎控制寄存器0中的MSK位。
(4) 中断处理程序
CS4281有一个中断状态寄存器和一个中断屏蔽寄存器,他们对应位意义相同。中断状态寄存器反映了声卡能产生的几种中断。一旦有中断发生,分析中断状态寄存器,判断中断类型,再做相应的处理。根据我们的设计,如果是播放中断则释放播放信号量,促使上层软件拷贝声音数据至下层软件;如果是录音中断则释放录音信号量,促使上层软件从下层软件取走已到达的声音数据。最后设置中断结束标志。
(5) 播放和发送时的数据流
播放时的数据流。声卡中的播放缓冲(上文中所设的DMA缓冲)和FIFO0(从格式化器formatter接收声音数据,按先入先出方式存储,供CS4297芯片播放)之间数据传输由DMA0控制。DMA0引擎尽量保持FIFO0满。播放缓冲是个2 kB的内存,他的起始地址被写进DMA0基地址寄存器(DBA0)。2 047 B(计数应比所分配的字节数小1,因为中断发生于roll-unders模式下)写入DMA0基本计数寄存器(DBC0),DMA0引擎控制从播放缓冲中读入的字节数。当播放缓冲半空或空,将产生一个中断,促使从上层软件取数据。
录音时的数据流。声卡中的录音缓冲和FIFO1(从CS4297芯片接收声音数据,按先入先出方式存储,传给格式化器formatter)之间数据传送受控于DMA1。DMA1引擎尽量保持FIFO1为空,他同样也计算写进录音缓冲的字节数。当录音缓冲半满或满,将产生一个中断,促使上层软件把数据取走。
4 UDP通信
4.1 UDP协议
在以太网设施基础上,VxWorks使用因特网组件TCP/IP提供的端到端的传输能力在位于不同的主机上的任务间传输用户数据。在VxWorks中,使用Socket作为应用程序和TCP/IP协议的接口。Socket有2种基本类型:可靠的数据流SOCK_STREAM,使用TCP协议;数据报SOCK_DGRAM,使用UDP协议。
UDP相对于TCP有以下一些优点:
(1) UDP的报文短,利于减小传输时延;
(2) UDP是无连接协议,发送数据前不需要建立连接,适合于声音数据这种实时性要求高的应用;
(3) UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。
UDP的这些优点对于声音数据的实时传输非常重要,这些优点将保证传输尽可能有一个短时延、恒定的速度,因此选择UDP。
在无连接的Socket中,在通信的两端分别创建客户机端和服务器端,通信双方在整个过程中是平等的,双方直接通过Socket调用来发送或接收数据报。
UdpClient模块:创建客户端Socket;初始化服务器端地址;FOREVER{调用UDP发送模块;发送数据到服务器}。
UdpServer模块:创建本地地址;创建服务器端Sock-et;把Socket和本地地址绑定起来;FOREVER{接收数据;调用UDP接收模块)。
4.2 UDP发送
发送模块等待录音信号量。如果获得,表示一些新的数据在录音缓冲中已有效。将把新数据从录音缓冲拷入上层软件存储区,然后通过Socket把他发送到另一端主机。如果上层软件中的存储区满,丢弃旧分组存入新分组。
4.3 UDP接收
接收模块等待从Socket来的数据。如果获得播放信号量,表示播放缓冲区中的数据已被播放,将把上层软件存储区中的数据拷入播放缓冲;否则,任务将被挂起。如果上层软件中的存储区满,丢弃旧分组存入新分组。
5 遇到的主要问题
在本文所搭建的环境中,能较好地实现两块声卡之间的通话。开发过程中,主要遇到两个问题:
(1) 声卡中没有声音数据。声卡的FIFO缓冲区及DMA缓冲区中均没有数据。经分析查出:CS4297芯片中关于耳机和麦克风的寄存器没有打开和选中,耳机和麦克风一直处于“mute”状态。关掉“mute‘’后,问题解决。
(2) 不能产生中断。DMA缓冲区中已有数据,根据程序设计,此时应产生中断,由上层通信模块取走声音数据,但中断一直不能产生。经分析原因为:在声卡探测程序段获得的中断级直接用作中继号来挂接中断。解决方法:通过中断级来获取中断向量,再获取中断号,用来挂接中断处理程序。
举报