用RTDX实现数据的实时双向传输

来源:百度文库 编辑:神马文学网 时间:2024/04/28 11:35:38
摘   要:讲述实时数据传输(RTDX)的使用,描述一个用RTDX双向传递大量多媒体数据的实现方法。该方法可以方便的应用于其他TI DSP的系统设计中。
关键词:TI DSP;RTDX
引言
TI DSP在数字电路中作为信号处理、电路控制的核心设备,广泛应用于各个行业。在TI DSP系统设计阶段,实时数据交换(RTDX)提供了一种目标板和主机之间的双向实时数据传输的方法。它可以应用于大量数据的双向传输,例如应用在多媒体数据进行仿真处理中。但是由于它的实现难度较大以及不处于系统设计的核心位置,所以没有得到广泛使用。本文的目的是向读者描述一种RTDX的具体实现。
RTDX的使用方法
RTDX提供了目标板与主机之间的实时数据通信。当系统使用该功能时,DSP上驻留一个小的RTDX片上软件库,片上程序通过调用这个软件库的API实现JTAG与主机之间的数据传输。与DSP目标板相连的主机上也存在一个相应的RTDX主机端软件库,客户编写的主机端程序通过对象嵌入,实现DSP目标板的实时数据分析,以及向目标板提供新的数据。
在编写DSP的软件上,RTDX的使用方式和C语言文件的IO操作非常相似,如图1、2所示,在实现数据由DSP到主机的过程中,首先声明一个RTDX输出通道,然后对该通道进行操作,最后查询状态,看数据是否被发送出去;而从主机端到DSP端的数据传输过程中,则声明一个RTDX输入通道,然后读取该通道上的数据。
在主机端,TI 提供的RTDX库使用了微软公司的COM技术,数据的传输过程分别如图3、图4所示。
用RTDX实现多媒体数据的
双向传输
多媒体数据原始信息往往拥有极大的数据量,DSP在多媒体数据处理中的应用主要是压缩和解压缩,但由于DSP自身的限制,它没有大量的空间存储多媒体数据,即便这些数据是已经被压缩过的。在系统的调试阶段,如何单独测试DSP的编码效率呢?一种可行的解决办法就是借用DSP目标板相连的主机空间,用RTDX把原始数据传递给DSP,DSP对数据处理后再通过RTDX传回主机。
系统的整体构架
由于DSP片上存储空间有限, TI对RTDX一次在主机和目标DSP之间传输的数据长度做了限制,此值不应该超过253个字长为16bit的数据,如果一次传输的数据量超过253,则要对数据分片传递。本应用中每次传递的数据远远大于253,所以主机端和目标板都定义了分片长度RTDXBLOCK,RTDXBLOCK=200。传输时两边同时进行相反的工作,目标板写数据的时候主机等着读数据,主机写数据的时候目标板进行相反的操作。每传输RTDXBLOCK大小的数据,两者的工作进行交换。分段传递数据还带来了很多好处,它可以方便主机与目标板之间的同步,每次数据的发出也是对上一次收到数据的应答;RTDX的特性是读一个字节,写一个字节,读写采用相同大小段节省了将近一半的时间;inbuffer与outbuffer可以指向相同的地址,又节省了一些内存。
采用相同大小的段传输数据还有一些细节问题要考虑,目标板的第一次操作是否应该先是写出?以便空出地方来接收下一次被处理的数据。由于每次传输数据总量的不对称性,大部分情况下是输入的数据比输出的数据多,目标板先写出数据会多占用一次传输的时间。另一个问题就是数据总量的不对称性,总是主机或目标板先写完数据,只剩下某一种操作,这部分时间没有办法节省。
对于数据传递过程中可能传送的一些命令字如,跳过当前帧、程序终止等。做了这样的考虑,由主机和目标板主程序来填写和解释这些命令字,命令字不单独传输,本应用中放在inbuffer\outbuffer的第0个位置,与下一块数据同时传送。另外,本应用中inbuffer与outbuffer的第1个位置存放的是数据段的实际长度,常用于向主机端指示压缩后数据的实际长度,以便用于不定长压缩方式的数据输出。inbuffer/outbuffer的实际数据的起始位置是可以根据应用自定义的。传输程序不负责这些问题,只管从buffer的第一个字节开始传输数据。
软件设计
DSP片上实现了一次数据输入输出的函数dataIO,它采用C语言编写,返回值1表示运行过程均正常。有4个参数,分别是输出Buffer起始位置,输出Buffer的大小,输入Buffer的起始位置,输入Buffer的大小。使用时,在主函数中使用两个RTDX宏声明:RTDX_CreateOutput Channel(ochan),RTDX_CreateInput Channel(ichan),然后可以直接调用dataIO进行数据传输,dataIO会在第一次运行中自动初始化环境。如图7所示。dataIO函数经过简单的修改甚至不修改即可以适用于不同的环境。
主机端的RTDX过程使用C++实现,因为程序的主要目的就是向目标板传递数据和取得数据,所以直接在主程序中作了一个大的循环,同目标板一样用了4个参数:inbuffer,outbuffer,inbufferlength,outbufferleng。执行时,主程序首先被阻塞,不停的试图从目标板读取经过压缩的数据,直到目标板DSP把压缩好的数据放到输出通道上。得到数据后,主程序把这些数据存放在本地文件中,然后把要压缩的数据写到输入通道上传递给DSP。这样反复执行直到传输双方中的一方表示传输终止。
执行过程
首先把程序写入目标板DSP中,然后在DSP集成开发环境CCS的tools菜单中选择RTDX,启用输入通道和输出通道。先后运行DSP程序和主机端程序即可实现数据的双向传输。因为两边都使用了阻塞机制,所以程序运行的先后顺序无所谓。
结语
本应用实现了如下功能:主机端把44.1KHz,16bit采样的音频数据传递到DSP内存中,每次传递1152个数据。DSP对这些数据进行Mp3格式的压缩,压缩后的数据长度不确定,最后DSP把这些数据传回主机端,然后等待下一次传输开始。实现基于DSK5416,用CCS2.0作为DSP综合开发环境。主机端程序用MS VC6.0编译。
这种RTDX的实现方法用于2003年德州仪器公司数字信号处理大学挑战赛决赛项目“使用TMS320C547X实现多媒体数据在TCP/IP网络传输”的设计中,该项目最终获得大赛三等奖。
参考文献:
1. 彭启琮,‘TMS320C54x 实用教程’ ,电子科技大学出版社,1999
2. 张雄伟、陈亮、徐光辉,‘DSP集成开发与应用实例’,电子工业出版社,2002
RTDX_CreateOutputChannel( ochan );              //创建一个输出通道,该操作为宏操作
...
TARGET_INITIALIZE();
RTDX_enableOutput( &ochan );                //初始化目标板以及通道使能
...
status =RTDX_write( &ochan, outp ,RTDXBLOCK );
//发送outp指针所指数据到输出通道,数据长度由RTDXBLOCK指定,返回实际发送的数据长度*
*:数据长度指类型为发送数据类型转换为16位无符号所占长度,outp的数据类型也应为16位无符号数。
图1  目标板向主机输出数据
RTDX_CreateInputChannel( ochan );           //创建一个输入通道,该操作为宏操作
...
TARGET_INITIALIZE();
RTDX_enableInput( &ochan );                     //初始化目标板以及通道使能
...
status =RTDX_read( &ichan, inp,RTDXBLOCK )
//发送inp指针所指数据到输出通道,数据长度由RTDXBLOCK指定,返回实际接收的数据长度*
*:数据长度指类型为发送数据类型转换为16位无符号所占长度,inp的数据类型也应为16位无符号数。
图2   目标板从主机端获取数据
hr = rtdx_in.CreateInstance( __uuidof(RTDXINTLib::RtdxExp) ); //创建rtdx实例
status = rtdx_in->Open( "ichan", "W" );              //创建ichan ,以便向目标板输入数据*
status = rtdx_in->Write( sa, &bufferstate);       //把安全数组sa**中的数据写入目标板
status = rtdx_in->Close();    //关闭输入通道
*:读写状态标志"W"应该大写,否则会带来不可预知的错误。
**:在写入数据时,应该把要写入的数据放在一个安全数组中。然后调用Write。
图3  主机端向目标板传输数据
hr = rtdx_out.CreateInstance( __uuidof(RTDXINTLib::RtdxExp) ); //创建rtdx实例
status = rtdx_out->Open( "ochan", "R" );       //创建ochan ,以便从目标板获取数据
status = rtdx_out->ReadSAI2( &sb );              //把目标板上的数据写入安全数组sb*,**
status = rtdx_out->Close();  //关闭输出通道
*:从目标板读取的数据首先被放在安全数组中,然后由使用者读出。
**:可以根据目标板的数据格式,通过调用ReadSAI1,ReadSAI2,ReadSAI4,读取所占字节数不同的数据。例如读取占用4个8位字节的word类型数据,应该使用ReadSAI4。
图4  主机端从目标板获取数据
图5  输入输出Buffer的数据格式
图6  主机端与目标板的数据传输过程图
int dataIO(unsigned int * inbuffer,
unsigned int * outbuffer,
int inbuffer_length,
int outbuffer_length);
int main()
{     unsigned int inbuffer[FLUSH+2];
unsigned int outbuffer[FRAME+2];
while(1)
{
if (dataIO(inbuffer,outbuffer,FLUSH+2,FRAME+2)!=1)
return;
encode();/*进行数据处理*/
}
}
图7  经过封装的RTDX函数