固件程序由以下文件组成[5]:
FX2.h 共同的FX2常数、宏、数据类型以及函 数库内库函数的原型框架。
FX2regs.h FX2寄存器的声明及位屏蔽常数
Fw.c 框架源代码
Ti6713HPI2cy13.c 用户函数挂钩的相关定义
Gpif.c 由GPIF_Designer生成,用以匹配HPIC、HPIA、HPID时序
Dscr.a51 USB 描述符表的范例
Ezusb.lib EZ-USB 函数库目标代码
USBJmpTb.OBJ USB中断向量表和GPIF中断源
其中Fw.c、Ti6713HPI2cy13.c和Gpif.c是固件程序的核心内容。
在Fw.c中主要包括任务分配器(TD)函数和设备请求(DR)函数。Ti6713HPI2cy13.c中定义这些关键函数。Gpif.c由GPIF_Designer生成,本设计将GPIF_Designer的4组波形分别定义为:第一半字写、第二半字写、FIFO写和FIFO读。其中前两组波形配合任务分配器函数TD_Poll()完成DSP中寄存器HPIC和HPIA的写,后两组波形配合TD_Poll()完成自增模式下HPID的读写。波形的设计要严格遵守HPI总线访问时序。
在TD_Init()中设置整体状态变量的初始值并规定各种端点资源的使用(包含中断)以及配置外围接口的输入输出。为匹配HPI通信所需数据总线宽度,寄存器EPxFIFOCFG中 WORDWIDE位置1。PORTB配置为FD[7:0],PORTD配置为FD[15:8]。为了达到最大的USB2.0带宽,设计中将AUTOOUT/AUTOIN位置1。主机与主控制器被直接连接,CPU被旁路,OUT FIFO自动从主机提交到FIFO。
TD_Init()定义中的程序片段:
……
EP2CFG=0xA0; //端点2可用、输出、
数据流、512 B、
//4倍缓冲模式
SYNCDELAY;
EP4CFG=0x00; //端点4不可用
SYNCDELAY;
EP6CFG=0xE0; //端点2可用、输入、
数据流、512 B、4倍缓冲模式
SYNCDELAY;
EP8CFG=0x00; //端点8不可用
SYNCDELAY;
FIFORESET=0x80; //暂不接受主机请求
SYNCDELAY;
FIFORESET=0x02; //将EP2 FIFO恢复为缺省状态
SYNCDELAY;
FIFORESET=0x06; //将EP6 FIFO恢复为缺省状态
SYNCDELAY;
FIFORESET=0x00; //重新开放主机请求
SYNCDELAY;
EP2FIFOCFG=0x01; //
SYNCDELAY;
EP2FIFOCFG=0x11; //数据宽度16 bit、AUTOOUT模式
SYNCDELAY;
EP6FIFOCFG=0x09; //数据宽度16 bit、AUTOIN模式
SYNCDELAY;
……
TD_Poll()中最核心部分在于完成写HPIC寄存器、写HPIA寄存器、以自增模式读写HPID。
(1)写HPIC寄存器。
EP0BCL=0; //激活EP0缓冲器以接收主机的下一个请求
while(EP01STAT & bmEP0BSY);//等待EP0空闲可用
while(!HPI_RDY); //等待HPI准备好接收数据
IOA=bmHPIC; //PA2、PA3选通HPIC
GPIFWFSELECT=0xB9; //选择写入第一个半字的GPIF波形
GPIF_SingleByteWrite(EP0BUF[0],EP0BUF[1]);
//写入一个16 bit半字
其中GPIF_SingleByteWrite()定义为:
void GPIF_SingleByteWrite(BYTE gdatah,BYTE gdatal)
{
while( !(GPIFTRIG & 0x80) ) {;} //轮询GPIFTRIG.7
//Done位查看上一次事务是否完成
XGPIFSGLDATLX=gdatal; //高8位写入XGPIFSGLDATLX
XGPIFSGLDATH=gdatah; //低8位写入XGPIFSGLDATH
}
对于16位模式,把高8位写入XGPIFSGLDATLX,低8位写入XGPIFSGLDATH就可以自动启动一个单向写事务。当这个事务完成时,GPIFTRIG.7 Done置1,触发GPIFdone中断,68013使XGPIFSGLDATLX和XGPIFSGLDATH中的数据出现在16位数据总线FD[15:0]上。
(2)写HPIA寄存器。
与写HPIC基本相同,只是将IOA=bmHPIA,使PA2、PA3选通HPIA。
(3)自增模式下写HPID。
if(GPIFTRIG & 0x80) //检查当前GIPF是否空闲
{
if (!(EP24FIFOFLGS & 0x02 ) ) //检查外围是否有
//数据等待传入EP2,EP2非空
{
IOA=bmHPID_AUTO; //PA2、PA3选通自增模式HPID
while(!HPI_RDY); //等待HPI准备好传输数据
SYNCDELAY;
GPIFTCB1=EP2FIFOBCH;
SYNCDELAY;
GPIFTCB0=EP2FIFOBCL; //将EP2FIFO中字节数设置为TC的值
SYNCDELAY;
GPIFTRIG=GPIF_EP2; //写寄存器GPIFTRIG触发 EP2 OUT事务
SYNCDELAY;
while( !( GPIFTRIG & 0x80 ) ); //等待本次事务处理完毕
SYNCDELAY;
}
}
(4)自增模式下读HPID。
与自增模式下写HPID写过程基本相同。不同点在于:事务计数器的值不是端点6中字节的个数,而是应当由主机方通过控制端点EP0告知FX2;读EP6前要检查EP6 FIFO非满,触发时将GPIFTRIG设置成EP6IN。
3.1.2 固件代码的存储位置
本设计将固件代码存在主机中,设备上电以后由下面要介绍的驱动程序将固件下载到FX2片内RAM后执行,这一过程也就是重枚举。这种方法便于系统的调试和升级,用户可以根据自己的需要将相应驱动下载到PC上,从而使设备呈现出不同的属性功能,并可以进行适当的软升级。这种方法对片外EEPROM或ROM的存储空间要求很低,便于实现,使用灵活。
另外还可以把固件代码固化到一片EEPROM中,上电后FX2通过I2C总线下载到片内RAM后执行;或者把程序固化到一片ROM中充当外部程序存储器,连接到FX2总线上。
3.2 设备驱动程序
设备驱动程序提供用户访问设备的接口。EZ-USB系列芯片都具有通过下载固件和重枚举的方式来动态改变设备特性的能力,这就需要一个特殊的具有下载固件并完成设备重枚举功能的设备驱动程序,也可以叫做固件下载驱动程序。Cypress公司发布的EZ-USB软件开发包中提供了一个固件下载驱动程序的模版,即EZ-LoaderDriver。通过它可以方便地将自己的固件程序嵌入固件下载驱动程序。主要步骤包括:(1)设定固件下载前后两次枚举的不同VID和PID;(2)修改ezloader中source文件的目标名称;(3)修改Dscr.a51中的VID、PID;(4)利用ezloader提供的工具将用Keil编写固件所生成的.hex文件转换成.sys文件;(5)编写与.sys文件相对应的安装信息文件(.inf);(6)修改EEPROM,将VID、PID写入,并设置成C0引导加载模式。
3.3 主机应用程序
为提高开发速度,本设计的主机应用程序在Cypress公司提供的USB Control Pane的基础上加以修改,增添了读取存储和分析音频文件(主要是.wav文件)的功能。
3.4 DSP数据处理程序
将G.723.1公布的低码率语音压缩算法以C与汇编混合编程的方法[4]移植到TMS320C6713,并加以调整优化。
本系统开发旨在为G.723.1以及G.729等常用的低码率语音压缩标准提供运行及测试的硬件平台。DSP系统中的程序采用C与汇编混合编程的方法。实验表明,USB的数据带宽完全可以满足多路音频数据实时处理的要求,并具有良好的稳定性和适应性,能够达到所要求的通信质量,实现较为完善的语音编解码系统。