原创 用RTDX实现数据的实时双向传输(转帖)

2008-5-21 23:14 3473 4 4 分类: 处理器与DSP

   要:讲述实时数据传输(RTDX)的使用,描述一个用RTDX双向传递大量多媒体数据的实现方法。该方法可以方便的应用于其他TI DSP的系统设计中。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


关键词:TI DSP;RTDX


引言


TI DSP在数字电路中作为信号处理、电路控制的核心设备,广泛应用于各个行业。在TI DSP系统设计阶段,实时数据交换(RTDX)提供了一种目标板和主机之间的双向实时数据传输的方法。它可以应用于大量数据的双向传输,例如应用在多媒体数据进行仿真处理中。但是由于它的实现难度较大以及不处于系统设计的核心位置,所以没有得到广泛使用。本文的目的是向读者描述一种RTDX的具体实现。


 


RTDX的使用方法


RTDX提供了目标板与主机之间的实时数据通信。当系统使用该功能时,DSP上驻留一个小的RTDX片上软件库,片上程序通过调用这个软件库的API实现JTAG与主机之间的数据传输。与DSP目标板相连的主机上也存在一个相应的RTDX主机端软件库,客户编写的主机端程序通过对象嵌入,实现DSP目标板的实时数据分析,以及向目标板提供新的数据。


       在编写DSP的软件上,RTDX的使用方式和C语言文件的IO操作非常相似,如图12所示,在实现数据由DSP到主机的过程中,首先声明一个RTDX输出通道,然后对该通道进行操作,最后查询状态,看数据是否被发送出去;而从主机端到DSP端的数据传输过程中,则声明一个RTDX输入通道,然后读取该通道上的数据。


在主机端,TI 提供的RTDX库使用了微软公司的COM技术,数据的传输过程分别如图3、图4所示。


 


RTDX实现多媒体数据的


双向传输


       多媒体数据原始信息往往拥有极大的数据量,DSP在多媒体数据处理中的应用主要是压缩和解压缩,但由于DSP自身的限制,它没有大量的空间存储多媒体数据,即便这些数据是已经被压缩过的。在系统的调试阶段,如何单独测试DSP的编码效率呢?一种可行的解决办法就是借用DSP目标板相连的主机空间,用RTDX把原始数据传递给DSP,DSP对数据处理后再通过RTDX传回主机。


 


系统的整体构架


由于DSP片上存储空间有限, TIRTDX一次在主机和目标DSP之间传输的数据长度做了限制,此值不应该超过253个字长为16bit的数据,如果一次传输的数据量超过253,则要对数据分片传递。本应用中每次传递的数据远远大于253,所以主机端和目标板都定义了分片长度RTDXBLOCK,RTDXBLOCK=200。传输时两边同时进行相反的工作,目标板写数据的时候主机等着读数据,主机写数据的时候目标板进行相反的操作。每传输RTDXBLOCK大小的数据,两者的工作进行交换。分段传递数据还带来了很多好处,它可以方便主机与目标板之间的同步,每次数据的发出也是对上一次收到数据的应答;RTDX的特性是读一个字节,写一个字节,读写采用相同大小段节省了将近一半的时间;inbufferoutbuffer可以指向相同的地址,又节省了一些内存。


采用相同大小的段传输数据还有一些细节问题要考虑,目标板的第一次操作是否应该先是写出?以便空出地方来接收下一次被处理的数据。由于每次传输数据总量的不对称性,大部分情况下是输入的数据比输出的数据多,目标板先写出数据会多占用一次传输的时间。另一个问题就是数据总量的不对称性,总是主机或目标板先写完数据,只剩下某一种操作,这部分时间没有办法节省。


对于数据传递过程中可能传送的一些命令字如,跳过当前帧、程序终止等。做了这样的考虑,由主机和目标板主程序来填写和解释这些命令字,命令字不单独传输,本应用中放在inbuffer\outbuffer的第0个位置,与下一块数据同时传送。另外,本应用中inbufferoutbuffer的第1个位置存放的是数据段的实际长度,常用于向主机端指示压缩后数据的实际长度,以便用于不定长压缩方式的数据输出。inbuffer/outbuffer的实际数据的起始位置是可以根据应用自定义的。传输程序不负责这些问题,只管从buffer的第一个字节开始传输数据。


软件的整体构架如图6所示。


软件设计


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集成开发环境CCStools菜单中选择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,读取所占字节数不同的数据。例如读取占用48位字节的word类型数据,应该使用ReadSAI4


4  主机端从目标板获取数据


 


2006_9_22_13_15_30_1.jpg

>5  输入输出Buffer的数据格式


 


2006_9_22_13_15_30_2.jpg

>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();/*进行数据处理*/


       }


}


 
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条