Chinaunix首页 | 论坛 | 博客
  • 博客访问: 658406
  • 博文数量: 175
  • 博客积分: 2457
  • 博客等级: 大尉
  • 技术积分: 1488
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-13 20:31
文章分类

全部博文(175)

文章存档

2012年(22)

2011年(153)

分类: 嵌入式

2011-07-28 19:49:39

1  引言

       CCS(Code Composer Studio)是TI公司的DSP集成开发环境。它提供了环境配置、源文件编辑、程序调试、跟踪和分析等工具,帮助用户在一个软件环境下完成编辑、编译链接、调试和数据分析等工作。与TI提供的早期软件开发工具相比,利用CCS能够加快软件开发进程,提高工作效率。CCS一般工作在两种模式下:软件仿真器和与硬件开发板相结合的在线编程。前者可以脱离DSP芯片,在PC机上模拟DSP指令集与工作机制,主要用于前期算法实现和调试。后者实时运行在DSP芯片上,可以在线编制和调试应用程序。

       2  C语言和汇编语言的混合编程

       TMS320 C5000系列的软件设计通常有三种方法:

       (1) 用C语言开发;

       (2) 用汇编语言开发;

       (3) C和汇编的混合开发。

       其中用C语言开发具有兼容性和可移植的优点,有利于缩短开发周期和减少开发难度,但是在运算量较大的情况下,C代码的效率还是无法和手工编写的汇编代码的效率相比,比如FFT运算,用汇编语言开发的效率高,程序执行速度快,而且可以合理利用芯片的硬件资源,但是开发难度较大,开发周期长,而且可读性和可移植性差。C和汇编的混合编程则可以充分利用前两者的优点,以达到最佳利用DSP资源的目的。但是,采用C和汇编语言混合编程必须遵循相关函数调用规则和寄存器调用规则,否则会给程序的开发带来意想不到的问题。

       2.1  C语言和汇编语言混合编程的四种方法

       (1) 独立编写汇编程序和C程序,分开编译或汇编成各自的目标代码模块,再用链接器将二者链接起来。这种方法比较灵活,但是设计者必须自己维护各汇编模块的入口和出口代码,自己计算传递的参数在堆栈中的偏移量,工作量较大,但是能做到对程序的绝对控制。

       (2) 在C程序中使用汇编程序中定义的变量和常数。

       (3) 在C程序中内嵌汇编语句。这种方法可以实现C语言无法实现的一些硬件控制功能,如修改中断控制寄存器。

       (4) 将C语言编译生成相应的汇编代码,手工修改和优化C编译器生成的汇编代码。采用这种方法可以控制C编译器,从而产生具有交叉列表的汇编程序,而设计者可以对其中的汇编语句进行修改,然后对汇编程序进行编译,产生目标文件。

       后3种方法由于在C中直接嵌入了汇编语言,易造成程序混乱,破坏C环境,甚至导致程序崩溃,而开发者又很难对不良结果进行预期和有效控制。而如果采用第一种方法,只要遵循有关C语言函数调用规则和寄存器规则,就能预见到程序运行的结果,保证程序正确。

       2.2  编程注意事项

       C编译器对函数调用制定了一组严格的规则。除了特殊的运行时间支持库函数外,任何调用函数和被C函数调用的函数都必须遵守这些规则。结合作者在编程中的实际情况和切身体会,提出在编程时要注意以下几点:

       (1) 必须保护任何被函数修正的专用寄存器。这些专用寄存器包括:AR1,AR6,AR72和堆栈指针(SP)。其中,如果对SP正常使用,则不必明显的保存。换句话说,只要汇编函数在调用返回时弹出压入的对象,实际上就已经保护了SP。

       (2) 中断函数必须保存其使用的所有寄存器。

       (3) 从汇编函数中调用C函数时,第一个参数(最左边的)必须放入累加器A中,剩下的参数按照自右向左的顺序压入堆栈。

       (4) 如果函数有返回值,则返回值存放在累加器A中。

       (5) 调用C函数时,注意C函数只保护了几个特定的寄存器,对于其他寄存器C函数是可以自由使用的。

       (6) 长整数和浮点数存储在存储器中的方法是最高有效字在低位地址。

       (7) 汇编语言模块不能改变由C模块产生的.cinit段,如果改变其中的内容将会引起不可预测的后果。

       (8) 在汇编语言模块中,对可以从C中访问的变量和函数名需加上前缀“_”。对于仅用于汇编语言模块中的标识符,不用加下划线。而且如果仅在汇编中使用,只要不加下划线,即使与C程序中定义的对象名相同,也不会造成冲突。

       (9) 任何在汇编语言模块中声明的将要从C访问或调用的对象或函数,都必须在汇编语言中用.global伪指令声明为全局变量。同样,任何在C程序中定义而将在汇编中访问或调用的对象或函数,在汇编中也必须用.global声明。

       (10) 在默认的情况下,编译器总是认为CPL为1。因此,若在汇编程序中将CPL清0,则在返回C环境时,必须将其恢复为1;在默认的情况下,编译器总是认为 OVM为0。因此,若在汇编程序中将OVM置为1,则返回C环境时,必须将其恢复为0;ARP在函数进入和返回时,必须为0,即当前辅助寄存器为AR0。函数执行时可以为其他值。

       3  编程实例

       3.1  FFT算法简介


       FFT是一种高效实现离散傅立叶变换的算法,在数字信号处理系统中,FFT作为一个非常重要的工具,甚至成为DSP运算能力的一个考核因素。如何将FFT算法很好的应用到DSP系统中对于DSP系统的设计具有重要的意义。

       一个优化的实数FFT算法是一个组合以后的算法。该算法主要分为以下几步,首先将输入的2N点实序列进行位倒序组合成一个N点的复序列,之后对复序列进行N 点的FFT运算,最后再由N点的复数输出拆散成2N点的复数序列,这2N点的复数序列与原始的2N点的实数输入序列的DFT输出一致。(详细的算法介绍可参考相关信号处理书籍)。

       3.2  C主程序

#include "stdlib.h"
extern void fft();  // FFT运算函数
int DisData[256];  // 输出结果
int SimData[256]={
0,6270,11585,15137, 16384, 15137, 11585,6270,
0, -6270, -11585,-15137,-16384,-15137,-11585,-6270,
……
0,6270,11585,15137,16384,15137,11585,6270,
0,-6270,-11585,-15137,-16384,-15137,-11585,-6270
};  
// 输入数据
int  main()
{
rfft();  
// 调用FFT函数
while(1)  ;
}

       本程序中FFT运算所用到的数据是通过matlab仿真产生的,然后通过全局数组进行传值,这种方式的优点是数据的通用性强,方便对数据进行其他相关处理; 也可通过其他C程序产生然后保存到一个文本文件中,再由汇编程序将该数据文件拷到数据存储器中参与FFT运算。这种方式的优点是程序的可读性强,缺点是当输入数据修改后,必须进行重新编译、汇编和链接。

       3.3  汇编程序

  .mmregs
  .global  sav_sin,sav_idx,sav_grp,_rFFT,_DisData
  .data 
DATA .space 1024   ;数据缓冲区
INPUT .set     0x9000 ;输入数据起始地址
N  .set 128  ;复数点数
LOGN .set 7     ;碟形运算级数
sav_grp .usect "tempv",3 ;定义组变量值
sav_sin .set sav_grp+1 ;定义旋转因子表
sav_idx .set sav_grp+2
  .copy  "twiddle1.inc" ;正弦表系数
  .copy  "twiddle2.inc" ;余弦表系数
  .text
_rfft:
  SSBX TC
  SSBX C
  RSBX OVA
  RSBX OVB
  LD  #0,DP
  RSBX CPL
  SSBX XF
  SSBX SXM
  LD  #00,ASM   
  SSBX FRCT
  ……  

       本程序主要是对输入的256点实数作FFT运算,通过修改N和LOGN可以完成16-1024点的FFT运算。在编写汇编程序的时候要注意以下几个方面:

       (1) 由于采用循环寻址来对旋转因子表寻址,因此每张表的开始地址必须是10个LSB位为0的地址。如:正弦表系数可以放在0400h开始的地址,余弦表系数可以放在0800h开始的地址;

       (2) 在汇编程序的入口处要注意设置好汇编程序所需要的运行环境(见前述程序),如果此处按照编译器默认的环境将得不到正确的结果。详细的汇编程序可参考TI公司提供的例程。

       3.4  运算结果

       输入正弦信号的频率为f=16Hz,幅值为1(单位),采样长度为2N=256点,采样频率为fs=256Hz。CCS提供了很多方法将程序产生的数据画图显示,包括时域/频域波形显示等。可通过查看相关图像来检验FFT运算的正确性。由链接命令文件可以知道输入信号存储在程序存储区0900h开始的256 个单元中,经程序计算得到的信号幅值谱存放在数据存储区0200h开始的256个单元中。在CCS中选择View——>Graph——> Time/Frequency命令,相关设置可参考图1:

       

                         图1  FFT运算结果查看选项设置参考

       输入信号的时域波形见图2。

点击看原图

 

 

 

                                                            图2     输入信号的时域波形

  

;     经FFT运算后得到的信号幅值谱图见图3。

 

 

点击看原图

 

 

                                                           图3     信号幅值谱图

       将输入信号通过Matlab仿真进行验证。输入信号的时域波形见图4。

 

点击看原图

 

 

                                                      图4     输入信号的时域波形

       经FFT运算后得到的信号幅值谱图见图5。

 

点击看原图

 

 

                                                图5     信号幅值谱图

       通过比较CCS中的输出图形和Matlab中的仿真输出图形, 可以看到二者是一致的,说明本程序的结果是正确的。

       4  结束语

       本文通过实例,说明了TMS320 C5000系列DSP芯片的混合编程方法,利用混合编程达到了提高程序的可读性与编程效率的目的,是开发DSP软件的常用方法。本文介绍的混合编程方法不但适用于TI C5000系列DSP芯片,同样也适用于TI其他系列的DSP芯片,如C2000系列、C6000系列,甚至对其他芯片,如51系列单片机等,实现混合编程也有很大参考价值。

 

阅读(1228) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~