图4 编解码的软件流程
(1) 编码
首先对系统初始化,包括对AC97、CODEC、DMAC等模块配置,以及有关状态变量的初始化。然后,采样第1帧语音数据,采样结束进入DMA中断,在中断处理中再次配置DMAC,触发新的采样传输,并对刚采样的数据编码。由于编码由内核执行,采样由CODEC和DMA完成,故对第K帧编码和对第K+1帧采样是并发进行的。
(2) 解码
同编码过程类似,首先对系统进行初始化,然后解码第1帧音频数据。解码完配置DMAC,触发数据传送至AC97输出FIFO,通过放音设备播放录音。同样,解码第K+1帧数据与播放第K帧数据并发进行。
本设计采用“双Buffer”机制缓冲数据。“双Buffer”是指:开辟两个帧缓冲区为Buf0、Buf1,缓冲标志Flg初始为0。编码时,采样第1帧数据,DMA从AC97输入FIFO向Buf0传输数据,传输完后,设置Flg=1,编码器从Buf0中取数据编码;同时,DMA向Buf1中传送新数据。周而复始,每帧数据采样完,设置Flg=!Flg,编码器从Buf!Flg缓冲区取数据编码,DMA传送采样数据的目的地址为Buf Flg,从而实现了第K+1帧数据采样和第K帧数据编码并发。只要编码速度高于采样速度,就不会出现数据的覆盖。处理过程如下(解码时的情况类似):
Flg=0;?
Psmp=Buf Flg;?
Run_Sample(Psmp);//采样第1帧数据?
While(1) { ?
Flg=! Flg;?
Penc=Buf !Flg;//编码指针指向缓冲区Buf !Flg??
Psmp=Buf Flg;//采样指针指向缓冲区Buf Flg??
Run_Sampler(Psmp); Run_Encoder(Penc); ?
//启动采样器和编码器,两者并发?
}
4、性能优化
语音处理的实时性要求很高,否则,若数据处理速度跟不上语音变化速度,就会在录音时出现刚采样的数据覆盖了先采入但未处理的数据;在放音时,出现播放的速度比实际语音慢。当然,如果用足够大的缓冲,可以避免录音出现的问题,但放音出现的问题是无法避免的。同时,鉴于存储资源对于嵌入式系统是很宝贵的,故此方案没有实际价值。上文介绍的“双Buffer”机制,能够使采样和编码之间、解码和播放之间分别互不影响、并发执行,易于控制;但要满足实时性要求,还要使编解码速度符合采样和播放的要求。语音速率是8 KB/s,而系统中一个采样点用16位表示,故编解码速度不能低于16 KB/s(即每秒至少编码16 KB的PCM码,每秒至少解出16 KB的PCM码)。表1是未对系统优化前,测试裸机无操作系统情况下,处理512 KB的PCM码(对应128 KB的ADPCM码)所用时间。该测试是使用SoC内部定时器TIMER进行的,见参考文献[1]。测试结果显示,系统优化前没有满足语音实时性要求。
表1 优化前编解码速度
到此,系统目标代码都是在SDRAM中运行的。SEP3203提供了一个很有用的模块——片内高速存储器eSRAM。eSRAM存取速度非常快,可达到0.89 MIPS/MHz,所以对系统性能有很大的优化作用,而SDRAM却只能有其性能的1/3左右。表2是在50 MHz时钟、32位ARM指令情况下,SDRAM和eSRAM的性能比较。各项指标的意义见参考文献[1]。
表2 eSRAM和SDRAM性能比较
但是,SEP3203的20K的eSRAM资源是有限的,不可能也不必要将所有代码都放在其中执行。ARM集成开发工具提供了Profile功能,可以对整个程序进行统计分析,得到各部分代码(主要以标准C函数为单位)所耗时间占系统总时间的百分比。通过对软件系统做Profile分析,得到各编解码库函数在总编解码时间内所占的百分比,其中主要部分如表3所列。
表3 最耗费时间的库函数
以上三个函数在总编解码时间内占用了近80 %的时间(Quan()、Fmult()、Update()的功能分别为量化表查找、定点化的浮点数乘法、状态变量更新),对这些代码优化就会明显提高编解码速度。把这些函数代码整合到文件rec_esram.c中,然后加载remap.scf文件进行内存映像(*.scf文件是ARM ADS集成开发工具提供的链接脚本文件)。下面是remap.scf文件的内容:
FLASH 0x30002000 0x1000000
{?
FLASH 0x30002000?
//系统初始化入口及其他代码存放地址
{?
init_ice.o (INIT, +First)?
* (+RO,+RW,+ZI)?
}?
32bitRAM 0x00000000 //中断向量表入口地址?
{?
boot_gfd.o (BOOT, +First)?
} ?
ESRAM 0x1fff0000 0x600 //核心库代码存放地址,在eSRAM中?
{?
rec_esram.o (+RO,+RW,+ZI)?
}?
/*堆栈设置部分*/
}
进行内存映像后,rec_esram.c的目标代码rec_esram.o(约为1.5KB)就加载到eSRAM(起始地址为0x1fff0000)中执行了。表4是经过eSRAM优化后编解码速度测试结果。
表4 eSRAM优化后的编解码速度
在有操作系统的情况下,也对语音系统性能进行了测试,如表5所列。该操作系统为东南大学专用集成电路系统工程技术与研究中心自主研发的面向嵌入式应用的ASIXOS,提供图形用户界面、网络、时钟、实时中断管理等支持和清晰的应用程序开发接口。语音系统为该OS环境中的一个应用,有独立的用户界面和底层服务。限于篇幅,本文不再详述。
从以上测试可以看出,在经过eSRAM优化后,无论是在裸机上还是在有操作系统的情况下,编解码速度都能满足语音实时性的需要,达到了设计要求。
表5 eSRAM优化后的编解码速度
结语
在设计一款面向多媒体应用的嵌入式系统时,实时性能非常重要。本文提出了一种基于ARM7TDMI内核的SoC中语音处理系统的设计方案,并根据该款SoC具有eSRAM的特点,进行了系统性能的优化。对样机的测试表明系统在主频70 MHz、有操作系统的情况下编码速率为19.88 KB/s,解码速率为22.68 KB/s,达到了语音系统的实时性要求。而且,如果语音处理作为样机的子系统应用,其硬件设计也支持MP3播放和LCD触摸屏
的功能,实现了系统板面积减小、整机成本降低的目的,不失为一种高效价廉的设计方案。
参考文献
1 凌明.基于ARM7TDMI的低成本手持多媒体设备处理器.南京:东南大学国家ASIC工程中心,2004
2 苟大举,杨启刚.基于ADPCM 编码的语音录放系统开发平台.四川大学学报(自然科学版), 1998.4, Vol.35 No.2:178~182
3 傅秋良,袁宗宝.纯软件实现ADPCM语音压缩算法.电信科学, 1994.10, Vol.10 No.10:21~24
4 Gibson Jerry D. 多媒体数字压缩原理与标准.李煜晖译.北京:电子工业 出版社,2002
5 CCITT. Recommendation G.721: A 32kbit/s Adaptive Differential Pulse?Code?Modulation, Red Book,1984
6 CCITT. Recommendation G.711: General Aspects of Digital Transmission Systems and Terminal Equipments, Blue Book, 1988
① 开发工具用的是Tornado2.2 for arm;
② 参考资料有BSP Kit、S3C4510B DataSheet;
③ 参考Tornado2.2 for ARM下自带的wrSBCarm7 BSP;
④ 烧写程序采用编程器。
通常在开发BSP的时候,我们需要在Tornado原带BSP目录下找一个与我们所用的处理器相同或相近。与BSP相关的文件有:romInit.s、sysAlib.s、bootInit.c、bootConfig.c、sysLib.c、config.h、configNet.h、makefile以及与我们硬件相关的,如串口sysSerial.c等。由于篇幅所限,具体的文件作用在此就不说了。下面主要根据S3C4510B来阐述一下BSP开发步骤。
(1)拷贝BSP
将wrSBCarm7 BSP拷贝一份并命名为4510BSP,接下来的工作就是修改该目录下的文件,从而得到自己的BSP。
(2)修改MakeFile文件
修改4510BSP目录下的makefile文件,修改如下几行:
TARGET_DIR = 4510BSP # changed by caiyang
VENDOR = CAI # changed by caiyang
BOARD = MyarmBoard # changed by caiyang
ROM_TEXT_ADRS = 01000000 # ROM entry address
ROM_WARM_ADRS = 01000004 # ROM warm entry address
ROM_SIZE = 00080000 # number of bytes of ROM space
RAM_LOW_ADRS = 00006000 # RAM text/data address (bootrom)
RAM_HIGH_ADRS = 00486000 # RAM text/data address (bootrom)
MACH_EXTRA =
注解:ROM_TEXT_ADRS:BOOT ROM的入口地址。对大多数板来说,这就是ROM地址区的首地址,然而也有的硬件配置使用ROM起始的一部分地址区作为复位向量,因此需要根据此设置偏移量作为它的地址。这个偏移量因CPU结构而定。
ROM_WARM_ADRS:BOOT ROM热启动入口地址。它通常位于固定的ROM_TEXT_ADRS+4的地方。当需要热启动时,sysLib.c文件中sysToMonitor( )函数代码明确的跳转到ROM_Warm_ADRS地址处开始执行。
ROM_SIZE:ROM实际大小。
RAM_LOW_ADRS:装载Vxworks的地址。
RAM_HIGH_ADRS:将Boot Rom Image拷贝到RAM的目的地址。
注意:RAM_LOW_ADRS 和 RAM_HIGH_ADRS 都是绝对地址,通常位于DRAM起始地址的偏移量处,该偏移量取决于CPU结构,这需要参考VxWorks内存分布。对于arm的内存分布请看图3,从图3可以看出RAM_LOW_ADRS在DRAM+0x1000处。这些地址对于S3C4510B来说都应该是重映射后的地址。
(3)修改config.h文件
主要是修改ROM_BASE_ADRS、ROM_TEXT_ADRS、ROM_SIZE、RAM_LOW_ADRS、RAM_HIGH_ADRS和undef掉不需要的部分。注意这些应该和makefile文件中设置的一致。
(4)修改romInit.s文件
CPU一上电就开始执行romInit( )函数,因此在romInit.s代码段中它必须是第一个函数。对于热启动,处理器将会执行romInit( )加上4后的代码(具体参考sysLib.c中的sysToMonitor( )函数)。更多的硬件初始化在sysLib.c中sysHwInit( )函数中,romInit( )的工作就是做较少的初始化并把控制权交给romStart( )(在bootInit.c文件)。
在S3C4510B处理器中,romInit.s文件主要做了以下几个工作:
① 禁止CPU中断并切换到SVC32模式;
② 禁止中断控制器;
③ 初始化SYSCFG、EXTDBWTH、ROMCON0、ROMCON1、DRAMCON0等寄存器,同时初始化了FLASH、SDRAM、DM9008等外围设备;
④ 将FLASH的内容拷贝到SDRAM中;
⑤ 改变FLASH和SDRAM的基地址,将SDRAM基地址改为0;
⑥ 初始化堆栈指针;
⑦ 跳转到C程序romStart( )函数中。
本文转自电子工程世界