首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

DSP资料,为需要的朋友提供一些帮助!

DSP资料,为需要的朋友提供一些帮助!

一 DSP定点算数运算 1 数的定标 在定点DSP芯片中,采用定点数进行数值运算,其操作数一般采用整型数来表示。一个整型数的最大表示范围取决于DSP芯片所给定的字长,一般为16位或24位。显然,字长越长,所能表示的数的范围越大,精度也越高。如无特别说明,本书均以16位字长为例。 DSP芯片的数以2的补码形式表示。每个16位数用一个符号位来表示数的正负,0表示数值为正,l则表示数值为负。其余15位表示数值的大小。因此, 二进制数0010000000000011b=8195 二进制数1111111111111100b= -4 对DSP芯片而言,参与数值运算的数就是16位的整型数。但在许多情况下,数学运算过程中的数不一定都是整数。那么,DSP芯片是如何处理小数的呢?应该说,DSP芯片本身无能为力。那么是不是说DSP芯片就不能处理各种小数呢?当然不是。这其中的关键就是由程序员来确定一个数的小数点处于16位中的哪一位。这就是数的定标。 通过设定小数点在16位数中的不同位置,就可以表示不同大小和不同精度的小数了。数的定标有Q表示法和S表示法两种。表1.1列出了一个16位数的16种Q表示、S表示及它们所能表示的十进制数值范围。 从表1.1可以看出,同样一个16位数,若小数点设定的位置不同,它所表示的数也就不同。例如, 16进制数2000H=8192,用Q0表示 16进制数2000H=0.25,用Q15表示 但对于DSP芯片来说,处理方法是完全相同的。 从表1.1还可以看出,不同的Q所表示的数不仅范围不同,而且精度也不相同。Q越大,数值范围越小,但精度越高;相反,Q越小,数值范围越大,但精度就越低。例如,Q0 的数值范围是一32768到+32767,其精度为1,而Q15的数值范围为-1到0.9999695,精度为1/32768=0.00003051。因此,对定点数而言,数值范围与精度是一对矛盾,一个变量要想能够表示比较大的数值范围,必须以牺牲精度为代价;而想精度提高,则数的表示范围就相应地减小。在实际的定点算法中,为了达到最佳的性能,必须充分考虑到这一点。 浮点数与定点数的转换关系可表示为: 浮点数(x)转换为定点数(xq):xq=(int)x* 2Q 定点数(xq)转换为浮点数(x):x=(float)xq*2-Q 例如,浮点数x=0.5,定标Q=15,则定点数xq=L0.5*32768J=16384,式中LJ表示下取整。反之,一个用Q=15表示的定点数16384,其浮点数为163幼*2-15=16384/32768=0.5。浮点数转换为定点数时,为了降低截尾误差,在取整前可以先加上0.5。 表1.1 Q表示、S表示及数值范围 Q表示 S表示 十进制数表示范围 Q15 S0.15 -1≤x≤0.9999695 Q14 S1.14 -2≤x≤1.9999390 Q13 S2.13 -4≤x≤3.9998779 Q12 S3.12 -8≤x≤7.9997559 Q11 S4.11 -16≤x≤15.9995117 Q10 S5.10 -32≤x≤31.9990234 Q9 S6.9 -64≤x≤63.9980469 Q8 S7.8 -128≤x≤127.9960938 Q7 S8.7 -256≤x≤255.9921875 Q6 S9.6 -512≤x≤511.9804375 Q5 S10.5 -1024≤x≤1023.96875 Q4 S11.4 -2048≤x≤2047.9375 Q3 S12.3 -4096≤x≤4095.875 Q2 S13.2 -8192≤x≤8191.75 Q1 S14.1 -16384≤x≤16383.5 Q0 S15.0 -32768≤x≤32767 2 高级语言:从浮点到定点 我们在编写DSP模拟算法时,为了方便,一般都是采用高级语言(如C语言)来编写模拟程序。程序中所用的变量一般既有整型数,又有浮点数。如例1.1程序中的变量i是整型数,而pi是浮点数,hamwindow则是浮点数组。 例1.1 256点汉明窗计算 int i;+ float pi=3.14l59; float hamwindow[256]; for(i=0;i<256;i++) hamwindow=0.54-0.46*cos(2.0*pi*i/255); 如果我们要将上述程序用某种足点DSP芯片来实现,则需将上述程序改写为DSP芯片的汇编语言程序。为了DSP程序调试的方便及模拟定点DSP实现时的算法性能,在编写DSP汇编程序之前一般需将高级语言浮点算法改写为高级语言定点算法。下面我们讨论基本算术运算的定点实现方法。 2.1 加法/减法运算的C语言定点摸拟 设浮点加法运算的表达式为: float x,y,z; z=x+y; 将浮点加法/减法转化为定点加法/减法时最重要的一点就是必须保证两个操作数的定标 temp=x+temp; z=temp>>(Qx-Qz),若Qx>=Qz z=temp<<(Qz-Qx),若Qx<=Qz 例1.4结果超过16位的定点加法 设x=l5000,y=20000,则浮点运算值为z=x+y=35000,显然z>32767,因此 Qx=1,Qy=0,Qz=0,则定点加法为: x=30000;y=20000; temp=20000<<1=40000; temp=temp+x=40000+30000=70000; z=70000L>>1=35000; 因为z的Q值为0,所以定点值z=35000就是浮点值,这里z是一个长整型数。当加法或加法的结果超过16位表示范围时,如果程序员事先能够了解到这种情况,并且需要保持运算精度时,则必须保持32位结果。如果程序中是按照16位数进行运算的,则超过16位实际上就是出现了溢出。如果不采取适当的措施,则数据溢出会导致运算精度的严重恶化。一般的定点DSP芯片都没有溢出保护功能,当溢出保护功能有效时,一旦出现溢出,则累加器ACC的结果为最大的饱和值(上溢为7FFFH,下溢为8001H),从而达到防止溢出引起精度严重恶化的目的。 2.2乘法运算的C语言定点模拟 设浮点乘法运算的表达式为: float x,y,z; z=xy; 假设经过统计后x的定标值为Qx,y的定标值为Qy,乘积z的定标值为Qz,则 z=xy zq*2-Qx=xq*yq*2-(Qx+Qy) zq=(xqyq)2Qz-(Qx+Qy) 所以定点表示的乘法为: int x,y,z; long temp; temp=(long)x; z=(temp*y)>>(Qx+Qy-Qz); 例1.5定点乘法。 设x=18.4,y=36.8,则浮点运算值为=18.4*36.8=677.12; 根据上节,得Qx=10,Qy=9,Qz=5,所以 x=18841;y=18841; temp=18841L; z=(18841L*18841)>>(10+9-5)=354983281L>>14=21666; 因为z的定标值为5,故定点z=21666,即为浮点的z=21666/32=677.08。 2.3除法运算的C语言定点摸拟 设浮点除法运算的表达式为: float x,y,z; z=x/y; 假设经过统计后被除数x的定标值为Qx,除数y的定标值为Qy,商z的定标值为Qz,则 z=x/y zq*2-Qz=(xq*2-Qx)/(yq*2-Qy) zq=(xq*2(Qz-Qx+Qy))/yq 所以定点表示的除法为: int x,y,z; long temp; temp=(long)x; z=(temp<<(Qz-Qx+Qy))/y; 例1.6定点除法。 设x=18.4,y=36.8,浮点运算值为z=x/y=18.4/36.8=0.5; 根据上节,得Qx=10,Qy=9,Qz=15;所以有 z=18841,y=18841; temp=(long)18841; z=(18841L<<(15-10+9)/18841=3O8690944L/18841=16384; 因为商z的定标值为15,所以定点z=16384,即为浮点z=16384/215=0.5。 2.4程序变量的Q值确定 在前面几节介绍的例子中,由于x,y,z的值都是已知的,因此从浮点变为定点时Q值很好确定。在实际的DSP应用中,程序中参与运算的都是变量,那么如何确定浮点程序中变量的Q值呢?从前面的分析可以知道,确定变量的Q值实际上就是确定变量的动态范围,动态范围确定了,则Q值也就确定了。 设变量的绝对值的最大值为|max|,注意|max|必须小于或等于32767。取一个整数n,使满足 2n-1<|max|<2n 则有 2-Q=2-15*2n=2-(15-n) Q=15-n 例如,某变量的值在-1至+1之间,即|max|<1,因此n=0,Q=15-n=15。 既然确定了变量的|max|就可以确定其Q值,那么变量的|max|又是如何确定的呢?一般来说,确定变量的|max|有两种方法。一种是理论分析法,另一种是统计分析法。 1. 理论分析法 有些变量的动态范围通过理论分析是可以确定的。例如: (1)三角函数。y=sin(x)或y=cos(x),由三角函数知识可知,|y|<=1。 (2)汉明窗。y(n)=0.54一0.46cos[nπn/(N-1)],0<=n<=N-1。因为-1<=cos[2πn/(N-1)]<=1,所以0.08<=y(n)<=1.0。 (3)FIR卷积。y(n)=∑h(k)x(n-k),设∑|h(k)|=1.0,且x(n)是模拟信号12位量化值,即有|x(n)|<=211,则|y(n)|<=211。 (4)理论已经证明,在自相关线性预测编码(LPC)的程序设计中,反射系数ki满足下列不等式:|ki|<1.0,i=1,2,...,p,p为LPC的阶数。
2. 统计分析法
对于理论上无法确定范围的变量,一般采用统计分析的方法来确定其动态范围。所谓统计分析,就是用足够多的输入信号样值来确定程序中变量的动态范围,这里输入信号一方面要有一定的数量,另一方面必须尽可能地涉及各种情况。例如,在语音信号分析中,统计分析时就必须来集足够多的语音信号样值,并且在所采集的语音样值中,应尽可能地包含各种情况。如音量的大小,声音的种类(男声、女声等)。只有这样,统计出来的结果才能具有典型性。
当然,统计分析毕竟不可能涉及所有可能发生的情况,因此,对统计得出的结果在程序设计时可采取一些保护措施,如适当牺牲一些精度,Q值取比统计值稍大些,使用DSP芯片提供的溢出保护功能等。
2.5浮点至定点变换的C程序举例
本节我们通过一个例子来说明C程序从浮点变换至定点的方法。这是一个对语音信号(0.3~3.4kHz)进行低通滤波的C语言程序,低通滤波的截止频率为800Hz,滤波器采用19点的有限冲击响应FIR滤波。语音信号的采样频率为8kHz,每个语音样值按16位整型数存放在insp.dat文件中。
例1.7语音信号800Hz 19点FIR低通滤波C语言浮点程序。
#include
const int length=180/*语音帧长为180点=22.5ms@8kHz采样*/
void filter(int xin[],int xout[],int n,float h[]);/*滤波子程序说明*/
/*19点滤波器系数*/
static float h[19]=
{0.01218354,-0.009012882,-0.02881839,-0.04743239,-0.04584568,
-0.008692503,0.06446265,0.1544655,0.2289794,0.257883,
0.2289794,0.1544655,0.06446265,-0.008692503,-0.04584568,
-0.04743239,-0.02881839,-0.009012882,O.01218354};
static int xl[length+20];
/*低通滤波浮点子程序*/
void filter(int xin[],int xout[],int n,float h[])
{
int i,j;
float sum;
for(i=0;i for(i=0;i<length;i++)
{
sum=0.0;
for(j=0;j<n;j++)sum+=h[j]*x1[i-j+n-1];
xout=(int)sum;
for(i=0;i<(n-l);i++)x1[n-i-2]=xin[length-1-i];
}
/*主程序*/
void main()
FILE *fp1,*fp2;
int frame,indata[length],outdata[length];
fp1=fopen(insp.dat,"rb");/* 输入语音文件*/
fp2=fopen(Outsp.dat,"wb");/* 滤波后语音文件*/
frame=0;
while(feof(fp1) ==0)
{
frame++;
printf(“frame=%d\n”,frame);
for(i=0;i<length;i++)indata=getw(fp1); /*取一帧语音数据*/
filter(indata,outdata,19,h);/*调用低通滤波子程序*/
for(i=0;i<length;i++)putw(outdata,fp2);/*将滤波后的样值写入文件*/
}
fcloseall();/*关闭文件*/
return(0);
}
例1.8语音信号800Hz l9点FIR低通滤波C语言定点程序。
#include
const int length=180;
void filter (int xin[],int xout[],int n,int h[]);
static int h[19]={399,-296,-945,-1555,-1503,-285,2112,5061,7503,8450,
7503,5061,2112,-285,-1503,-1555,-945,-296,399};/*Q15*/
static int x1[length+20];
/*低通滤波定点子程序*/
void filter(int xin[],int xout[],int n,int h[])
int i,j;
long sum;
for(i=0;i<length;i++)x1[n+i-111=xin]
for(i=0;i<1ength;i++)
sum=0;
for(j=0;j<n;j++)sum+=(long)h[j]*x1[i-j+n-1];
xout=sum>>15;
for(i=0;i<(n-1);i++)x1[n-i-2]=xin[length-i-1];
}
主程序与浮点的完全一样。“
3 DSP定点算术运算
定点DSP芯片的数值表示基于2的补码表示形式。每个16位数用l个符号位、i个整数位和15-i个小数位来表示。因此:
00000010.10100000
表示的值为:
21+2-1+2-3=2.625
这个数可用Q8格式(8个小数位)来表示,其表示的数值范围为-128至+l27.996,一个Q8定点数的小数精度为1/256=0.004。
虽然特殊情况(如动态范围和精度要求)必须使用混合表示法。但是,更通常的是全部以Q15格式表示的小数或以Q0格式表示的整数来工作。这一点对于主要是乘法和累加的信号处理算法特别现实,小数乘以小数得小数,整数乘以整数得整数。当然,乘积累加时可能会出现溢出现象,在这种情况下,程序员应当了解数学里面的物理过程以注意可能的溢出情况。下面我们来讨论乘法、加法和除法的DSP定点运算,汇编程序以TMS320C25为例。
3.1定点乘法
两个定点数相乘时可以分为下列三种情况:
1. 小数乘小数
例1.9 Q15*Q15=Q30
0.5*0.5=0.25
0.100000000000000;Q15
* 0.100000000000000;Q15
--------------------------------------------
00.010000000000000000000000000000=0.25;Q30
两个Q15的小数相乘后得到一个Q30的小数,即有两个符号位。一般情况下相乘后得到的满精度数不必全部保留,而只需保留16位单精度数。由于相乘后得到的高16位不满15位的小数据度,为了达到15位精度,可将乘积左移一位,下面是上述乘法的TMS320C25程序:
LT OP1;OP1=4000H(0.5/Q15)
MPY OP2;oP2=4000H(0.5/Ql5)
PAC
SACH ANS,1;ANS=2000H(0.25/Q15)
2. 整数乘整数
例1.10 Q0*Q0=Q0
17*(-5)=-85
0000000000010001=l7
*1111111111111011=-5
-------------------------------------------
11111111111111111111111110101011=-85
3. 混合表示法
许多情况下,运算过程中为了既满足数值的动态范围又保证一定的精度,就必须采用Q0与Q15之间的表示法。比如,数值1.2345,显然Q15无法表示,而若用Q0表示,则最接近的数是1,精度无法保证。因此,数1.2345最佳的表示法是Q14。
例1.11 1.5*0.75= 1.125
01.10000000000000=1.5;Q14
*00.11000000000000=0.75;Q14
---------------------------------------
0001.0010000000000000000000000000=1.125 Q28
Q14的最大值不大于2,因此,两个Q14数相乘得到的乘积不大于4。
一般地,若一个数的整数位为i位,小数位为j位,另一个数的整数位为m位,小数位为n位,则这两个数的乘积为(i+m)位整数位和(j+n)位小数位。这个乘积的最高16位可能的精度为(i+m)整数位和(15- i- m)小数位。
但是,若事先了解数的动态范围,就可以增加数的精度。例如,程序员了解到上述乘积不会大于1.8,就可以用Q14数表示乘积,而不是理论上的最佳情况Q13。例3.11的TMS320C25程序如下:
LT OP1;OP1 = 6000H(1.5/Ql4)
MPY OP2;OP2 = 3000H(0.75/Q14)
PAC
SACH ANS,1;ANS=2400H(1.125/Q13)
上述方法,为了精度均对乘的结果舍位,结果所产生的误差相当于减去一个LSB(最低位)。采用下面简单的舍人方法,可使误差减少二分之一。
LT OP1
MPY OP2
PAC
ADD ONE,14(上舍入)
SACH ANS,1
上述程序说明,不管ANS为正或负,所产生的误差是l/2 LSB,其中存储单元ONE的值为1。
3.2定点加法
乘的过程中,程序员可不考虑溢出而只需调整运算中的小数点。而加法则是一个更加复杂的过程。首先,加法运算必须用相同的Q点表示,其次,程序员或者允许其结果有足够的高位以适应位的增长,或者必须准备解决溢出问题。如果操作数仅为16位长,其结果可用双精度数表示。下面举例说明16位数相加的两种途径。
1.保留32位结果
LAC OP1;(Q15)
ADD OP2;(Ql5)
SACH ANSHI ;(高16位结果)
SACL ANSLO :(低16位结果)
2.调整小数点保留16位结果
LAC OP1,15;(Q14数用ACCH表示)
ADD OP2,15;(Q14数用ACCH表示)
SACH ANS;(Q14)
加法运算最可能出现的问题是运算结果溢出。TMS320提供了检查溢出的专用指令BV,此外,使用溢出保护功芸墒估奂咏峁绯鍪崩奂悠鞅ズ臀畲蟮恼蚋菏5比唬词谷绱耍怂憔然故谴蟠蠼档汀R虼耍詈玫姆椒ㄊ峭耆斫饣镜奈锢砉滩⒆⒁庋≡袷谋泶锓绞健?br /> 3.3定点除法
在通用DSP芯片中,一般不提供单周期的除法指令,为此必须采用除法子程序来实现。二进制除法是乘法的逆运算。乘法包括一系列的移位和加法,而除法可分解为一系列的减法和移位。下面我们来说明除法的实现过程。
设累加器为8位,且除法运算为10除以3。除的过程包括与被除法有关的除数逐步移位,在每一步进行减法运算,如果能减则将位插入商中。
(1)除数的最低有效位对齐被除数的最高有效位。
0000l0l0
- 00011000
--------------------------------------
11110010
(2)由于减法结果为负,放弃减法结果,将被除数左移一位,再减。
00010100
- 00011000
----------------------------------------
11111000
(3)结果仍为负,放弃减法结果,被除数左移一位,再减。
00101000
- 00011000
------------------------------------------
00010000
(4)结果为正,将减法结果左移一位后加1,作最后一次减。
00100001
- 00011000
----------------------------------------
00001001
(5)结果为正,将结果左移一位加1 得最后结果。高4位代表余数,低4位表示商。
00010011
即,商为0011= 3.余数为0001= 1。
TMS320没有专门的除法指令,但使用条件减指令SUBC可以完成有效灵活的除法功能。使用这一指令的唯一限制是两个操作数必须为正。程序员必须事先了解其可能的运算数的特性,如其商是否可以用小数表示及商的精度是否可被计算出来。这里每一种考虑可影响如何使用SUBC指令的问题。下面我们给出两种不同情况下的TMS320C25除法程序。
(1)分子小于分母
DIV_A:
LT NUMERA
MPY DENOM
PAC
SACH TEMSGN;取商的符号
LAC DENOM
ABS
SACL DENOM;使分母为正
ZALH NUMERA; 分子为正
ABS
RPTK 14
SUBC DENOM;除循环15次
SACL QUOT
LAC TEMSGN
BGEZ A1;若符号为正,则完成
ZAC
SUB QUOT
SACL QUOT;若为负,则商为负
A1: RET
这个程序中,分子在NUMERA中,分母在DENOM中,商存在QUOT中,TEMSGN为暂存单元。
(2)规定商的精度
DIV_B:
LT NUMERA
MPY DENOM
PAC
SACH TEMSGN;取商的符号
LAC DENOM
ABS
SACL DENOM; 使分母为正
LACK 15
ADD FRAC
SACL FRAC;计算循环计数器
LAC NUMERA
ABS ; 使分子为正
RPT FRAC
SUBC DENOM; 除循环16+FRAC次
SACL QUOT
LAC TEMSGN
BGEZ B1;若符号为正,则完成
ZAC
SUB QUOT
SACL QUOT;若为负,则商为负
B1: RET
与DIV_A相同,这个程序中,分子在NUMERA中,分母在DENOM中,商存在QUOT中,TEMSGN为暂存单元。FRAC中规定商的精度,如商的精度为Q13,则调用程序前FRAC单元中的值应为13。
4 非线性运算的定点快速实现 在数值运算中,除基本的加减乘除运算外,还有其它许多非线性运算,如,对数运算,开方运算,指数运算,三角函数运算等,实现这些非线性运算的方法一般有:(1)调用DSP编译系统的库函数;(2)查表法;(3)混合法。下面我们分别介绍这三种方法。 1.调用DSP编译系统的库函数 TMS320C2X/C5X的C编译器提供了比较丰富的运行支持库函数。在这些库函数中,包含了诸如对数、开方、三角函数、指数等常用的非线性函数。在C程序中(也可在汇编程序中)只要采用与库函数相同的变量定义,就可以直接调用。例如,在库函数中,定义了以10为底的常用对数log10(): #include<math.h> double,log10(double x); 在C程序中按如下方式调用: float x,y; X=10.0; y=log10(x); 从上例可以看出,库函数中的常用对数log10()要求的输入值为浮点数,返回值也为浮点数,运算的精度完全可以保证。直接调用库函数非常方便,但由于运算量大,很难在实时DSP中得到应用。 2.查表法 在实时DSP应用中实现非线性运算,一般都采取适当降低运算精度来提高程序的运算速度。查表法是快速实现非线性运算最常用的方法。采用这种方法必须根据自变量的范围和精度要求制作一张表格。显然输人的范围越大,精度要求越高,则所需的表格就越大,即存储量也越大。查表法求值所需的计算就是根据输入值确定表的地址,根据地址就可得到相应的值,因而运算量较小。查表法比较适合于非线性函数是周期函数或已知非线性函数输入值范围这两种情况、例1.12和例1. 13分别说明这两种情况。 例1.12 已知正弦函数y=cos(x),制作一个512点表格,并说明查表方法。由于正弦函数是周期函数,函数值在-1至+1之间,用查表法比较合适。由于Q15的表示范围为1-至32767/32768之间,原则上讲-1至+1的范围必须用Q14表示。但一般从方便和总体精度考虑,类似情况仍用Q15表示,此时+1用32767来表示。 (1)产生5l2点值的C语言程序如下所示。 #define N 512 #define pi 3.14l59 int sin_tab[5l2]; void main() { int i; for(i=0;i<N;i++)sin_tab=(int)(32767*sin(2*pi*i/N)); (2)查表 查表实际上就是根据输人值确定表的地址。设输入x在0~2π之间,则x对应于512点表的地址为:index=(int)(512*x/2π),则y=sin(x)=sin_tab[index]如果x用Q12定点数表示,将512/2π用Q8表示为20861,则计算正弦表的地址的公式为。 index=(x*20861L)>>20; 例1.12用查表法求以2为底的对数,已知自变量值范围为0.5-1,要求将自变量范围均匀划分为10等分。试制作这个表格并说明查表方法。 (1)作表: y=log2(x),由于x在0.5到1之间,因此y在-1到0之间,x和y均可用Q15表示。由于对x均匀划分为10段,因此,10段对应于输入x的范围如表3.2所示。若每一段的对数值都取第一点的对数值,则表中第一段的对数值为y0(Q15)=(int)(log(O.5)*32768),第二段的对数值为y1(Q15)=(int)(log2(0.55)*32768),依次类推,如表3.2所示。 (2)查表: 查表时,先根据输人值计算表的地址,计算方法为: index=((x-16384)*20)>>15; 式中, index就是查表用的地址。例如,已知输人x=26869,则index=6,因此,y= -10549。 表1.2 logtab0 10点对数表 地址 输入值 对数值(Q15) 0 0.50-0.55 -32768 1 0.55-0.60 -28262 2 0.60-0.65 -24149 3 0.65-0.70 -20365 4 0.70-0.75 -16862 5 0.75-0.80 -13600 6 0.80-0.85 -10549 7 0.85-0.90 -7683 8 0.90-0.95 -4981 9 0.95-1.00 -2425 3.混合法 (1)提高查表法的精度 上述方法查表所得结果的精度随表的大小而变化,表越大,则精度越高,但存储量也越大。当系统的存储量有限而精度要求也较高时,查表法就不太适合。那么能否在适当增加运算量的情况下提高非线性运算的精度呢?下面介绍一种查表结合少量运算来计算非线性函数的混合法,这种方法适用于在输入变量的范围内函数呈单调变化的情形。混合法是在查表的基础上来用计算的方法以提高当输入值处于表格两点之间时的精度。提高精度的一个简便方法是采用折线近似法,如图1.1所示。 图1.1提高精度的折线近似法” 仍以求以2为底的对数为例(例1.12)。设输入值为x,则精确的对数值为y,在表格值的两点之间作一直线,用y'作为y的近似值,则有: y'=y0+△y 其中y0由查表求得。现在只需在查表求得y0的基础上增加△y既可。△y的计算方法如下: △y=(△x/△x0)△y=△x(△y0/△x0) 其中△y0/△x0对每一段来说是一个恒定值,可作一个表格直接查得。此外计算此时需用到每段横坐标的起始值,这个值也可作一个表格。这佯共有三个大小均为10的表格,分别为存储每段起点对数值的表logtab0、存储每段△y0/△x0值的表logtab1和存储每段输入起始值x0的表logtab2,表logtab1和表logtab2可用下列两个数组表示。 int logtab1[10]={22529,20567,18920,17517,16308, 15255,14330,13511,12780,12124};/*△y0/△x0:Q13*/ int logtab2[10]={16384,18022,19660,21299,22938, 24576,26214,27853,29491,31130};/*x0:Q15*/ 综上所述,采用混合法计算对数值的方法可归纳为: (1)根据输人值,计算查表地址:index=((x-16384)*20)>>15; (2)查表得y0=logtab0[index]; (3)计算△x=x-logtab2[index]; (4)计算△y=(△x*logtab1[index])>>13; (5)计算得结果y=y0+△y。 例1.13已知x=0.54,求log2(x)。 0.54的精确对数值为y=log2(0.54)=-0.889。 混合法求对数值的过程为: (1)定标Q15,定标值x=0.54*32768=17694; (2)表地址index=((x-16384)*20)>>15=0; (3)查表得y0=logtab0[0]=-32768; (4)计算△x=x-logtab2[0]=17694-16384=1310; (5)计算△y=(△xlogtab1[0]>>13=(13l0*22529L)>>13=3602 (6)计算结果y=y0+△y=-32768+3602=-29166。 结果y为Q15定标,析算成浮点数为-29166/32768=-0.89,可见精度较高。 (2)扩大自变量范围 如上所述,查表法比较适用于周期函数或自变量的动态范围不是太大的情形。对于像对数这样的非线性函数,输入值和函数值的变化范围都很大。如果输入值的变化范围很大,则作表就比较困难。那么能否比较好地解决这个问题,即不便表格太大,又能得到比较高的精度呢?下面我们来讨论一种切实可行的方法。 设x是一个大于0.5的数,则x可以表示为下列形式: x=m*2e 式中,0.5<=m<=1.0,e为整数。则求x的对数可以表示为: log2(x)=log2(m*2e)=log2(m)+log2(2e)=e+log2(m) 也就是说,求x的对数实际上只要求m的对数就可以了,而由于m的数值在0.5和1.0之间,用上面介绍的方法是完全可以实现的。例如: log2(10000)=log2(0.61035*214)=log2(0.61035)+14 =13.2877 可见,如果一个数可以用比较简便的方法表示为上面的形式,则求任意大小数的对数也比较方便的。TMS320C2X/C5X指令集提供了一条用于对ACC中的数进行规格化的指令NORM,该指令的作用就是使累加器中的数左移,直至数的最高位被移至累加器的第30位。例如,对数值10000进行规格化的TMS320C25程序为。 LAC #10000 SACL TEMP ZALH TEMP LAR AR1,#0FH RPT 14 NORM * - 上述程序执行后,AR1=#0eH,ACCH=2000(10进制)。对一个16位整数x进行上述程序处理实际上就是作这样一个等效变换: x=[(x*2e)/32768]*215-Q 其中,寄存器AR1包含的值为15-Q累加器ACC高16位包含的值为x.2Q,其数值在16384至32768之间。 例1.14实现以2为底的对数的C定点模拟程序。 int logtab0[10]={-32768,-28262,-24149,-20365,-16862, -13600),-1O549,-7683,-4981,-2425};/*Q15*/ int logtab1[10]={122529,20567,18920,175l7,16308, 15255,14330,13511,12780,12124};/*Q13*/ int logtab2[10]={16384,l8022,19660,21299,22938, 24576,26214,27853,29491,31130};/*Q15*/ int log2_fast(int Am) { int point,point1; int index,x0,dx,dy,y; point=0; while(Am<16384){point++;Am=Am<<1;}/*对Am进行规格化*/ point1=(15-point-4)*512;/*输入为Q4,输出为Q9*/ index=((Am-16384)*20L)>>15;/*求查表地址*/ dx=Am-logtab2[index]; dy=((long)dx*logtab1[index])>>13; y=(dy+longtab0[index])>>6;/*Q9*/ y=point1+y; return(y); } 上述程序中,输入值Am采用Q4表示,输出采用Q9表示,如果输入输出的Q值与上面程序中的不同,则应作相应的修改。 以上讨论了DSP芯片进行定点运算所涉及的一些基本问题,这些问题包括:数的定标,DSP程序的定点模拟,DSP芯片的足点运算以及定点实现非线性函数的快速实现方法等。充分理解这些问题对于用定点芯片实现DSP算法具有非常重要的作用。
二 用C语言设计TMS320C2X/C5X应用程序
一、存储器模式
TMS320C2X/C5X定点处理器有两种类型的存储器:程序存储器和数据存储器。在程序存储器中主要包含可执行的程序代码,在数据存储器中,则主要包含外部变量、静态变量和系统堆栈。由C程序生成的每一块程序或数据存放于存储空间的一个连续块中。
(一)C编译器生成的块
由TMS320C2X/C5X编译器编译生成的块共有六种,可分为两大类。在六种块中,除了具有浮点C编译器生成的五种块之外,还有一个.switch块,它是一个已初始化块,包含为 .switoh语句建立的表格。
(二)C系统堆栈
定点C系统堆栈的作用与浮点c编译器的C系统堆栈的作用完全相同,管理堆栈的方法也基本类似。但管理C相同堆栈所用的寄存器是不一样的。定点C编译器采用下面两个寄存器来管理这个堆栈:
AR1——是堆栈指针(SP)。它指向堆栈的顶部。
AR0——帧指针(FP)。指向当前帧的开始。
激活每个函数时,都在堆栈中建立一个新的帧,以用于分配局部变量和临时变量。C环境能够自动管理这些寄存器。如果需要编写用到运行堆栈的汇编程序,必须正确使用这些寄存器。
与浮点C编译器一样,定点C编译器的堆栈长度也由链接器确定,全局符号_STACK_SIZE的值等于堆栈长度,单位为字节,缺省值为1K字节。同样,需要改变堆栈长度时,在链接时用-stack选项,并在其后指定一个数值。
(三)动态存储器分配
在运行支持库中,有几个允许在运行时进行动态存储器分配的函数,如malloc、calloc、realloc,动态存储器分配的方法与浮点C编译器的动态存储器分配完全相同。
(四)静态和全局变量的存储器分配
在C程序中说明的每一个外部或静态变量被分配给一个唯一的连续空间。空间的地址
由链接器确定。编译器保证这些变量的空间分配在多个字中以使每个变量按字边界对准。
(五)域/结构的对准
编译器为结构分配空间时,它分配足够的字以包含所有的结构成员,在一组结构中,每个结构开始于字边界。
所有的非域类型对准于字的边界。对域分配足够多的比特,相邻域组装进一个字的相邻比特,但不跨越两个字。如果一个域要跨越两个字,则整个域分配到下一个字中。
二、寄存器规则
与浮点C编译器一样,在定点c编译器中也定义了严格的寄存器使用规则。这些规则对于编写汇编语言与C语言的接口非常重要。如果编写的汇编程序不符合寄存器使用规则,则C环境将被破坏。
C编译器使用寄存器的方法在使用和不使用优化器时是不一样的。因为优化器需要使用额外的寄存器作为寄存器变量以提高程序的运行效率。但函数调用时保护寄存器的规则在使用和不使用优化器时是一样的。下面我们来介绍定点C编译器使用寄存器的规则。
(一)特定寄存器
定点C环境中保留了三个寄存器:AR0、AR1、AR2, 它们的作用如下:
AR0——帧指针
AR1——堆栈指针
AR2——局部变量指针(用于计算局部变量的地址)
(二)寄存器使用
汇编用于函数中,可以使用辅助寄存器、T寄存器和P寄存器、各种状态寄存器,在使用时必须符合下列规则:
1. 辅助寄存器(ARP和AR0 ~ AR7)
函数进入和返回时,ARP必须为1,也就是说当前的辅助寄存器为AR1。函数执行时可以是其它值。
AR0和AR1可以在函数执行过程中修改,但它们必须恢复。
AR2、AR3、AR4和AR5可以自由使用,也就是说,在函数执行过程中可以修改,也不必恢复。
AR6和AR7用作寄存器变量。如果在函数中被修改,必须加以保护和恢复。
2. 状态寄存器
在C编译器中,始终假定PM状态位为0。如果函数改变PM值,则在函数返回时必须将PM重新设置为0。在TMS320C5X中,TRM位必须保持为0,硬件复位时TRM为0。对其它状态位既可以修改,也不必恢复。如DP、C、FSM、HM、INTM、OV、OVM、SXM、TC、TXM、CNF、FO和XF等。
3. 其它寄存器
累加器ACC可以自由使用,不必保护和恢复。ACC可以用来返回整数、指针和浮点值、P和T寄存器也可以自由使用。
(三)寄存器变量
在一个函数中,定点C编译器可以自由使用多至两个寄存器变量。如果要在函数中使用寄存器变量,则应在函数的参数表或函数的第一块中定义。否则,作为一般的变量处理。编译器用AR6和AR7作为寄存器变量,其中AR6分配给第一个寄存器变量,AR7分配给第二个寄存器变量。由于在运行时建立一个寄存器变量约需4个指令周期,因此,只有当一个变量访问2次以上,使用寄存器变量的效果才能明显地体现出来。
三、函数调用规则
定点C编译器也规定了一组严格的函数调用规则。除了特殊的运行支持函数外,任何调用C函数或被C函数所调用的函数都必须遵循这些规则,否则就会破坏C环境,造成不可预测的后果。
(一)参数传递
将参数传递给一个C函数时,必须遵循下列规则:
(1)函数调用前,将多数压入运行堆栈。。
(2)以逆序传递参数。也就是说。第一个参数(最左边)最后压栈,而最后一个参数(最右边)最先压栈。
(3)若参数是浮点数或长整型数,则低位字先压栈,高位字后压栈。
(4)传递结构时,采用多字方式。
(二)局部帧的产生
函数被调用时,编译器在运行栈中建立一个帧以存储信息。当前函数帧称为局部帧。C环境利用局部帧来保护调用者的有关信息、传递参数和生成局部变量。每调用一个函数,就建立一个新的帧。
上面已经介绍,寄存器AR1为SP,AR0为FP,SP指向栈顶,FP指向局部帧。编译器在建立局部帧时完成如下工作:
(1)从TMS320C2X/C5X的内部堆栈中弹出返回地址,并压人C运行堆栈。
(2)将旧的FP的内容压人C运行堆栈,并将FP设置为当前的SP。
(3)增加SP。增加的值等于需要保存的局部变量的字的个数加1,其中,额外的一个字位于帧的开始,用于存储临时变量。
(4)若函数使用AR6和AN7作为寄存器变量,则将它们的内容压人堆栈,然后装人相应局部变量的地址。
下面是完成上述工作的TMS320C2X的汇编程序,其中SIZE是局部帧的长度。
例2.1 调用函数时的初始处理
POPD * + ;将返回地址压人C堆栈
SAR AR0, * + ;保护旧FP
SAR AR1, *
LARK AR0, SIZE
LAR ARO, * 0 + ;FP= 旧的SP,SP=SP+ SIZE
SAR AR6,* + ;保护AR6
SAR AR7, * + ;保护AR7
下面是一些产生局部帧时的注意事项:
(1)函数进入时,编译器认为ARP为1。
(2)没有独立的参数表指针。指向参数时,帧指针用负偏移,指向局部变量时,用正偏移;
(3)帧指针AR0指向一个独立的字,这个字在局部变量前分配,用于存储临存值,通过AR0直接访问。
(4)编译器用AR2来计算局部变量的地址。一般来说,局部变量的偏移值放在AR2中,然后加上AR0。
(5)对TMS320C5X来说上面的程序稍有不同,但作用是一样的。
(三)函数结束
函数结束返回时,必须完成如下工作以恢复C调用环境:
(1)处理要传递给调用者的返回值;
(2)如果使用了AR6和AR7,则必须予以恢复;
(3)撤销为局部变量和临存值分配的空间;
(4)恢复原来的帧指针;
(5)将返回地址压人TMS320C2X/C5X的堆栈并返回调用程序。
下面是完成上述工作的TMS320C2X汇编程序。
例2.2 TMS320C2X C函数的结束处理
LAR AR7,* - ;恢复AR7
LAR AR6, * - ;恢复0柏
SBRK SIZE ;撤销局部帧
LAR AR0,* - ;恢复FP
PSHD* ;返回地址压人内部堆栈
RET ;返回
需要注意的是:
(1)函数在ACC中返回函数值。整数和指针在ACC的低16位中返回,浮点数和长整型数使用ACC全部32位返回。
(2)由于用ACC返回函数值,因此,必须保证ACC不被结束程序所修改。
(3)参数不是由被调用的函数弹出堆栈,而是必须由调用函数弹出。因此,调用者可以传递任意数目的参数至函数,同时,函数也不必知道有多少个参数传递。
(4)从函数返回时,ARP指向AR1。
四、中断函数
在定点C编译器中,中断可以用C函数直接处理。每个中断采用固定的程序名。如下所示:
c_int0 系统复位中断
c_int1 外部中断0
c_int2 外部中断1
c_int3 外部中断2
c_int4 内部定时器中断
C_int5 串行口接收中断
c_int6 串行口发送中断
c_int7 TDM 口接收中断
c_int8 TDM口发送中断
c_int9 外部中断3
调用上述中断程序时,首先调用一个名为I$$SAVE的子程序,这个子程序保护了所有的寄存器。同样,在函数返回时,调用一个名为1$$REST的子程序用于恢复被保护的寄存器。
用C语言编写中断程序时,必须注意以下几点:
(1)对由SP(AR1)指向的字,编译器可能正在使用,因此必须加以保护。
(2)中断的屏蔽和使能必须由程序员设置,设置的方法是用嵌人汇编语句的方法修改IMR寄存器。这样修改不会破坏C环境或C指针。
(3)中断程序没有参数传递,即使说明,也将被忽略。
(4)由于用C编写中断程序时,需要保护所有的寄存器,因此效率不高。
(5)将一个程序与某个中断关联时,必须在相应的中断矢量处放置一条跳转指令。采用.sect汇编指令建立一个简单的跳转指令表就可以实现这个功能。
(6)在汇编语言中,注意必须在中断程序名前加一下划杠。例如,c语言中的c_int1,在汇编语言中为_c_int1。
(7)中断程序或在中断程序中需要调用的程序都不能用_oe选项进行优化编译。
五、表达式分析
当C程序中需要计算整型表达式时,必须注意到以下几点:
1. 算术上溢和下溢。即使采用16位操作数,TMS320C2X/C5X也产生32位结果。因此,算术溢出是不能以一种可预测的方式进行处理的。
2. 整除和取模。TMS320C2X/C5X没有直接提供整除指令,因此,所有的整除和取模运算都需要调用库函数来实现。这些函数将运算表达式的右操作数压人堆栈,将左操作数放入累加器的低16位。函数的计算结果在累加器中返回。
3. 32位表达式分析。下面的的一些运算在函数调用时并不遵循标准的C调用规则,目的在于提高程序运行速度和减少程序代码空间。
(1)通过变量的左移(2)通过变量的右移(3)除法(4)取模(5)乘法
4. C代码访问16位乘法结果的高16位。采用如下方法可以访问16乘法结果的高16位。无需调用32位乘法的库函数。
(1)有符号结果:
int m1,m2,result;
result=((long)ml*(long)m2) >> 16;
(2)无符号结果:
unsign m1,m2,result;
result=((unsigned long)m1*(unsigned long)m2) >> 16;
TMS320C2X/C5X的C编译器将浮点数表示为IEEE单精度格式。单精度数和双精度数都表示位32位,两者没有任何区别。在TMS320C2X/C5X的浮点库中提供了一组浮点数学库函数,如加法、减法。乘法、除法、比较、整数和浮点数转换、标准的错误处理等。这些函数也不遵循标准的C调用规则。调用这些函数时,C编译器先将参数压人运行堆栈,然后调用浮点库函数。函数执行时,首先将参数从堆栈中弹出,然后执行函数运算,最后将运算结果压人堆栈返回。
有些浮点库函数需要整型或长整型参数或返回整型或长整型结果,对这些函数,用累加器的低16位传递或返回整型数,而用累加器的所有32位传递或返回长整型数。
六、TMS320C2X/C5X C语言程序开发举例 本节我们以TMS320C2X为例,说明定点DSP芯片C程序的开发过程。软件开发过程与浮点DSP芯片的开发过程相类似,主要分以下几个步骤: 1. 用编辑器(如EDIT、PE2等)编辑一个或多个C程序,如example1.c,example2.c。 2. 用一步编译程序dspcl.exe对C程序编译汇编形成目标文件,如example1.obj,example2.obj: dspcl_v25_g_mn_o2 example1.c dspc_v25_g_mn_o2 example2.c 命令选项中的_v25表示是TMS320C2X,若是TMS320C5X,则选项为_v50。 3. 根据实际应用编辑一个链接命令文件,如example.cmd。下面是一个典型的TMS320C25的链接命令文件: 例2.3 TMS320C25链接命令文件 example.cmd /* 命令文件名*/ -c /*ROM初始化*/ -o example.out /*输出文件名为example.out*/ -m example.map /*同时产生映象文件example.map*/ example1.obj /*第一个C目标文件*/ example2.obj /*第二个C目标文件*/ -l rts25.lib /*链入TMS320C25运行支持库*/ -l flib25.lib /*链入TMS320C25浮点库*/ MEMORY PAGE0:VECS: origin=0h len=30h PAGE0ROG: orgin=30h len=0EFDOh /*程序空间*/ PAGE1ATA: origin=800h len=OE800h /*数据空间*/ SECTIONS vecs:{}>VECS /*中断矢量*/ .text:{}>PROG PAGE0 /*代码*/ .cinit:{}> PROG PAGE0 /*C初始化表*/ .switch:{}>PROG PAGE0 /*switch语句表*/ .bss:{}>DATA PAGE1 /*变量*/ .const:{}>DATA PAGE1 /*常数变量*/ .stack:{}>DATA PAGE1 /*系统堆栈*/ .sysmem:{}>DATA PAGE1 /*动态存储器*/ 4. 链接形成example.out: dsplnk example.cmd 5. 用C源码调试器进行调试(模拟器、硬件仿真器等)。 例2.4 用C语言编写一个TMS320C5X的输入输出程序,并用simulator进行调试。 /*本程序是TMS320C5X的一个I/O口输入和输出程序,程序从I/O口地址0x0读人8位数据并存人数组中,同时将另一数组的数值写至I/O口地址0x1*/ #include "ioports.h" /*包含ioports.h头文件*/ #define RD_PORT Ox00; /*定义输入I/O口*/ #define WR_PORT Ox01; /*定义输出I/O口*/ 1nt indata[5],outdata[5]; /*定义全局数组*/ main() int i; for(i=0;i<5;i++) outdata=i<<2; /*初始化outdata数组*/ for(i=0;i<5;i++) /*循环5次*/ inport(RD_PORT,&indata); /*读I/O口*/ outport(WR_PORT,outdata); /*写I/O口*/ 用TMS320C5X simulator调试I/O口时,将I/O口与一文件相关联。这里我们建立两个文件RD.DAT和WR.DAT,并将RD.DAT文件初始化为: 0x0011 0x0022 0x0033 0x0044 0x0055 上述程序运行结束后,可以观察数组indata及文件WR.DAT。正确的结果应为indata[5]={0x11,0x22,0x33,0x44,0x55},文件WR.DAT应为 0x0000 0x0004 0x0008 0x00C0 0x0010 例2.5 用C语言编写一个具有中断功能的TMS320C50程序,用硬件仿真器进行调试。 /*本程序是TMS320C50的一个串行口输入输出程序。TMS320C50与PCM编译码器MC14LC5480通过串行口相接。中断程序从串行口读人8位数据,并将它写回串行口*/ #define VEC_ADDR(volatile int * )0x00; /*矢量地址*/ Fvolatile int * RCV_ADD=(volatile int *)0x20; /*C50串行口接收寄存器地址*/ volatile int * XMT_ADD=(volatile int *)0x21; /*C50串行口发送寄存器地址*/ int indata; /*定义全局变量*/ main() { volatile int * INTVEC=VEC_ADDR; /*矢量指针*/ INTVEC[]=(volatile int)c_int5; /*置串行口接收中断矢量*/ /*初始化串行口*/ asm("SPLK #0CH,SPC "); /*F0=FSM=1,DLB=MCM=TXM=0*/ asm("OPL #0C0H,SPC "); /*XRST=RRST=1*/ for(;; /*等待中断*/ } void c_int5() /*串行口接收中断*/ { indata=RCV_ADD[0]; XMT_ADD[0]=indata; 以上附录中我们介绍了用C语言开发DSP芯片的方法。用C语言开发DSP芯片缩短了开发周期,提高了程序开发的效率,也使程序的可读性和可移植性大大提高,对于系统的改进和升级换代也带来了极大的便利。当然,用目前的C编译器生成的程序代码,其效率还不能完全与手工编写的效率相比拟“,因此实际DSP应用系统中往往采用C和汇编的混合编写方法。 __________________
三 TMS320C2X/C5X 软件应用
这里介绍 TMS320C2X/C5X 若干软件编程技巧问题及一些典型的应用程序。
3.1软件编程技巧:
A.充分利用片内RAM
TMS320C2X大部分指令的执行时间是一个指令周期,但是在实际实现时由于采用的程序存储器和数据存储器是片内还是片外,实际执行的时间是不相同的。按照指令在内部存储器和外部存储器以及数据在内部存储器和外部存储器,可以分为四种情况,即:(1)指令在内部存器、数据在内部存储器(PU/DI);(2)指令在内部存储器、数据在外部存储器(PI/DE);(3)指令在外部存储器、数据在内部存储器(PE/DI);(4)指令在外部存储器、数据在外部存储器(PE/DE)。设P表示外部程序存储器所需的等待状态数,d表示外部数据存榜器所需的等待状态数,则执行LAC指令在四种情况下所需的周期数如表2.1所示。

表2.1 LAC指令周期数
PI/DI PI/DE PE/DI PE/DE
1 2+d 1+p 2+P+d
显然,即使外部的存储器是高速存储器不需要等待态,在PI/DE和PE/DE两种情况下,执行LAC所需的时间是两个指令周期,而不是一个指令周期。PI/DI和PE/DI两种情况是一个指令周期。因此,在程序在外部存储器中运行的情况下,应尽量使用片内RAM存储器存储数据。虽然一条指令只相差一个周期,但当指令在多级嵌套循环内部时就相当可观了。
B,利用单指令重复指令。
TMS320C2x提供了重复指令RPT和RPTK,这两条指令可以使下一条指令重复执行指定的次数而不增加额外的执行时间。TMS320C2X的重复计数器为8位,因此最大值为255,即最多可以便下一条指令执行256次。 RPT和RPTK与TBLR/TBLW、BLKD/BLKP、IN/OUT及MAC、MACD等指令结合使用可以提高程序运行的效率。例如下面的一段程序将存放在外部数据存储器地址400H开始的256个数据搬移至片内的Bl块。
LARP AR1
LRLK AR1,300H
RPTK 255
BLKD 400H,* +
C.利用高效指令和特殊寻址方式、
TMS320C2X的指令集中提供了一些高效的指令。如乘累加并移位的MACD指令、平方并累加或减指令SQRS以及LACT、LTA、LTD、SPAC、APAC等。除了常用的寻址方式外,还提供了用于FFT的比特反转寻址方式。灵活使用这些指令和寻址方式可以提高程序的效率。
3.2提高TMS320C5x软件效率
TMSS320C5X是TMS320C2X的增强型DSP芯片,其增强的并行结构使得TMS320C5X的速度是TMS320C25的二倍以上。TMS320C2X的汇编语言在源代码级与TMS320C5X向上兼容, TMS320C2X的汇编程序稍作修改并用TMS320C5X的汇编器重新汇编后就可以在TMS320C5X 上运行。TMS320C5X的指令集是TMSS320C25指令集的超集,它在TMS320C2X的基础上作了改进并增加了一些功能更强的指令,充分利用这些增强特性可大大提高TMS320C5X的程序效率。
A.利用片内存储器的双映射特性
TMS320C5X具有1O56字的片内双存取存储器,比TMS320C25多5l2字。虽然使用这种类型存储器的效率很高,但同时成本也较高。TMS320C5X内部另一种存储器是单存取存储器,TMS320C53和C5l分别具有3K和IK字的单存取存储器,而C50具有8K字。这种存储器块的一个特点是同时可以映射至程序和数据空间。这种双映射的特点对于实现诸如自适应FIR滤波器(如横向滤波器)非常有用。乘/加循环要求F1R滤波器的系数在程序空间中,但同时相同的系数表需在数据空间中被更新。将这个系数表存放于片内的单存取存储器中并利用其双映射特点可使横向滤波器实现的效率更高。’
B.利用无开销循环。
在TMS320C25中,只提供了用于单指令重复的RPR/RPTK指令,要实现多于一条指令的循环必须来用寄存器不为零跳转的BANZ指令,这样每次循环实际上增加了3个指令周期。 TMS320C5X不仅提供了单指令重复指令RPT,而且提供了块指令重复指令RPTB,因此, TMS320C5X可以实现块指令的无开销循环。例如。
LACL #99
SAMM BRCR ;循环100次
RPTB LOOP-1
LAC *,16,AR1
MPYA *,+AR2
SACH *0-
LOOP:
C.嵌套循环的商效编程
在许多DSP应用程序中需要用到嵌套循环。如求10阶自相关需要用到二级嵌套循环,内循环计算每个自相关系数,外循环进行计数。如果内循环可以用RPT实现,则外循环可以用RPTB指令实现。如果内循环不能用一个RPT实现循环,也可以用延迟跳转循环来实现(如AR不为零延迟跳转BANZD)。最多可以有8个这佯的BANZD循环嵌套,每个循环用一个辅助寄存器作循环计数器。
D.使用CRGT和CRLT搜索最大/最小值
TMS320C5X提供了用于高效搜索最大和最小值的特殊指令CRGT和CRLT,这两个指令比较累加器ACC和累加器缓冲器ACCB之间的大小,比较之后将最大或最小值存放于ACCB中。例如下面一段程序用于在300H至309H存储单元中搜浆最大值并得到其地址。
MAXADR .set 60H
MAXVAL .set 61Hu
.TEXT
LDP #0 ;DP=0
LAR AR0,0300H
SETC SXM
LACC #0800H ;装人-个是小值
;(如果找最小值则装入7FFFH)
SACB ;送至ACCB
SPLK #9,BRCR ;重复10次。。
RPTB endb-1
LACC * ;取数至ACC
CRGT ;比较(如果找到最小值CRGT指令)
SACL MAXVAL ;保存具大值
XC #1.c
SAR AR0,MAXADR ;保存地址
MAR *+
Endb: RET。
E.利用循环寻址方式
TMS320C5X提供了循环寻址方式,这种寻址方式在实现F1R滤波器时非常有用。一般实现自适应FIR滤波器采用具有数据移动操作的乘/加指令MACD,在C5X中,可以用循环寻址方式代替数据移动操作来更新滤波器的铀头系数。如果滤波器的抽头在片内的单存取存储器,则这种方式的运行速度更快。
F.利用延迟跳转和条件运行
TMS320C2x具有3级深度的流水线,而C5X具有4级深度的流水线。C5X 4级深度的流水线使芯片的并行性能更强。然而,流水线越深,清空流水线的周期越长。正常眺转时,由于需要清空流水线,因此需要4个周期才能实现。相比而言,C2X仅需3个周期。但是,对C5X而言,所有需要清空流水线的指令都支持延迟执行功能,使运行开销降低至2个周期。此外果是仅跳转一个或两个指令这种特殊情况,可以使用速度更快的条件运行指令XC,此时仅一个周期。
G.并行进辑单元
TMS320C5X的比特操作单元与算术逻辑单元是独立运行的。这可使C5X在没有ACC或
ACCB参与的倩说下对片内或片外存储器单元(包括存储器陕射的寄存器)进行进辑操作。例如:
SMMR DRR, #DRR_DATA
LMMR DXR, #DXR_DATA
0PL #RXDATA, SP_FLG
APL #TXDATA, SP_FLG
H,增强的移位功能
TMS320C2X具有较强的移位功能,如取操作数至ACC时带0--16位左移、存ACC时带0--
7位左移、根据TREG1寄存器进行左移的取数指令LACT、ACC左移一位ROL和ACC右移一位ROR等。TMS320C5X在此基础上增加了ACC右移1--16位的指令BSAR和根据TREGl寄存
器值进行16位右移指令SATH及0--15位右移指令SATL。例如:
BASR 7 ;ACC=ACC >> 7
LMMR TREG1,1BH
SATH ;ACC=ACC >> 16,因为TREG1.4=1
SATL ;ACCC=ACCD >> ll
此外,C5X还具有对ACC、ACCB和进位位组成的65位数据进行移位的指令。
I.存储器映射寄存器
TMS320C5X提供了累加器与寄存器之间的直接通路,这是将寄存器映射至数据存储器而实现的。同时,TMS320C5X也支持存储器和寄存器之间的直接数据交换。例如:
SPLK #l6, INDX
SAMM PRD
L.系数表的动态寻址
在用乘/加指令实现F1R滤波器时,TMS320C2X/C5X从数据存储器取输入样值,而从程序空间取滤波器系数。由于同时从存储器中取两个操作数,使乘/加操作得以在一个周期内完成。在C25中,系数表的地址只能用直接寻址方式指定,这可满足大部分的应用。但是如果系数表的地址事先不能确定,而需在程序运行过程中确定时,C25实现就比较困难。对这种情况,C5X提供了一个称为块移动地址寄存器(BMAR)的专用寄存器,使乘/加操作可以用间接方式寻址,BMAR指向程序存储器中的系数表地址。例如
LACL table_add
SAMM BMAR ;更新系数表的地址
LAC ONE, 14
ZPR REG=0
RPT num_a-1 ;重复
MADD * - ;乘/加
APAC ;加最后一个乘积
SACH result,1 ;保存结果
3.3 软件应用
A.压缩与扩张程序。
与PCM Codec接口时,由于Codec输出和输入的数据均采用8位压缩格式,因此DSP处理前和处理后的数据均需进行变换。从Cedec来的压缩数据先要进行扩张变换为线性数据才能进行处理,同样,在送给Cedec前也需将线性数据变换为压缩数据。下面我们分别给出相应的应用程序。
(1)扩张程序
由于8位数据只有256个数值,因此扩张变换一般可以采用查表法实现,表的大小为256, 根据给出的V律扩张的数据表。TMs320c25的查表程序如下。
ULOT: LAC IN
ANDK #OFFH
ADLK _ulawtab
TBLR OUT
RET
上述程序中,待扩张的数据在IN中,扩张后的数据在OUT中,,ulawtab为256点数据表的起始地址。
(2)压缩程序
线性到压缩数据的变换一般采用程序计算实现,下面是线性数据到(律压缩数据的TMSC25程序。
;初始化
LDPK 0
LALK 132
SACL BIAS2
LALK -7
SACL NEG7
LARP ARO
;压缩子程序
LTOU: ZALH IN
SFL
SFL
BLZ NEGCMP
ADDH BIAS2
LAR AR0,NEG7
RBTK 6
NORM
ANDK OF000H,14
SACH Q
SAR AR0,S
ZALH S
ABS
ADD Q,2
XORK 0FF00H,4
B SATCH。
NEGCMP: ABS
ADDH BIAS2
LAR AR0,NEG7
RBTK 6
NORM
ANDK 0F000H,14
SACH Q
SAR AR0,S
ZALH S
ABS
ADD Q,2
XORK 07F00H,4
SACH OUT,4
RET
上述程序中,待压缩的数据在IN中,压缩后的数据在OUT中。数据存储单元都定义在第 0页中。需要注意的是,应保证待压缩数据的数值范围在一7774”+7774之间。
B.内部定时器的应用
TMS320C2X内部具有一个定时器,可产生周期中断,可以用来设置诸如A/D的采佯频率,在外部标志引脚XF上产生周期脉冲等。TMS320C2X的定时器由一个16位的定时器寄存器和一个16位的周期寄存器组成。在每个CLKOUT1周期,定时器寄存器的值减1,当该寄存器的值为0时,产生一个定时器中断(TINT)。在下一个CLKOUT1周期,周期寄存器的内容(PRD)装入至定时器寄存器。因此,定时器中断的周期是PRD+l个CLKOUT1周期,即中断频率为 CLKOUTl/(PRD+1)。设晶体的时钟为40MHz,要产生一个10KHz的定时器中断,则周期寄存器的值为:
f = CLKOUT1/(PRD+1)
PRD = (CLKOUT1/f)-1 =(10MHz/10KHz)-1 = 999
下面是一个在XF引脚上产生一个10KHz正脉冲的TMS320C2x程序。
PRD .set 3
IMR .set 4。
.text
LDPK 0
LALK #999
SACL PRD ;置定时器周期寄存器 = 999
LACL #8
0R IMR
SACL IMR ;开放定时器中断
RXF ;XF 置低
EINT :开中断
LO0P: B LOOP
;定时器中断服务程序
TINT_ISR:
SXF ;XF置高
SXF ;XF置低
EINT ;开中断
RET ;中断返回。
TMS320C5X的定时器在TMS320C2X的基础上增加了一些控制功能,通过设置定时器控制寄存器TCR可以启动、停止定时器,也可以设定定时器分频比。定时器的中断频苹为
f = CLKOUT1/[(TDDR+1)(PRD+1)]
式中,TDDR为分颇比,PRD为周期寄存器的值。
C.中断的保护和恢复
中断程序的状态保护和恢复只要根据中断程序中寄存器的使用情况进行保护和恢复即可。但是在保护两个状态寄存器ST0和STl时必须特别注意恢复时的先后顺序。TMS320C2X
保护ST0和STl寄存器时使用专门的指令SST0和SST1,恢复时使用LST0和LST1,如果采用间接寻址进行保护,则保护和恢复的顺序无关紧要。但是如果采用直接寻址,则必须注意恢复时的先后顺序。下面是采用直接寻址方式时TMS320C2x中断保护和恢复的正确方法,程序中TST0、TST1等都是定义在数据空间第O页的存储单元。
ISR_SUB:
SST0 TST0 ;保存ST0至TST0单元(强制DP = 0)
SST1 TST1 ;保存ST1至TST1单元(强制DP = 0)
LDPK 0 ;DP = 0
SACL TACCL ;保存ACC的高16位
SACH TACCH ;保存ACC的低16位,“
ZAIS TACCL ;恢复ACC的低16位
ADDH TACCH :恢复ACC的高16位
LST1 TST1 ; 恢复 ST1
LST0 TST0 ;恢复ST0
EINT :中断使能。
RETI ; 中断返回
如果将恢复的顺序颠倒过来,即首先执行LST0指令然后执行LST1指令,则数据页指针DP就不能正确地加以恢复。因为,数据页指针DP在状态寄存器ST0中,执行了LST0实际上就将当前数据页改为ST0中的DP值,再执行LSTl时,由于不像SST1那样强迫将DP置为0。因此数据页不对,恢复的ST1内容就不正确了。
D.TMS320C5X矢量表的重定位
TMS320C2x中断矢量表的地址固定在程序空间o地址开始的一段位置,固定中断矢量表地址在某些情况下会带来一定的麻烦。例如.当系统采用低速EPROM加高速RAM的存储器配置时,虽然程序可以在系统加电运行时从EPROM搬移至高速RAM运行,但由于中断矢量的地址是固定的,因此系统产生中断时,在中断矢量地址的跳转指令将不得不多运行几个指令周期。TMS320C5x作了改进,使中断矢量表的地址可以通过程序进行重定位,可以将矢量地址重新定位至程序空间中任何2K字页面的开始,如800H。重定位的方法是在PMST寄存器的IPTR域中设置对应的值,复位时,IPTR =0,中断矢量表的首地址为0H,若IPTR=1则首地址为800H。复位后执行下面的指令将矢量表地址重定位在800H:
OPL #800H,PMST
执行上述指令后,后面产生的中断将从新的矢量表中获取中断矢量,例如复位后定时器中断的矢量地址为BH,而新的矢量地址为808H。
E.TMS320C5X等待状态产生的软件实现
为了与低速的存储器或I/O设备接口, TMS320C2x需要采用硬件等待状态产生器实现,这使硬件设计复杂化。TMS320C5X支持硬件等待状态产生,也可采用软件控制等待状态的产生,从而使硬件设计简单化,节省了系统体积。软件可编程等待状态产生器是由两个16位等待状态寄存器PDWSR和IOWSR及一个5位控制寄存器CWSR控制的.
F.TMS320C2x至TMS320C5X的软件移植
TMS320C2x的指令集在源代码级是向上兼容的。因此,原则上说,TMS320C2X的程序经
过TMS320C5X的汇编器重新汇编后就可以在TMS320C5x上运行。但是,由于TMS32l0C5x在
串行口、定时器和全局控制等方面与TMS320C2x不同, 因此在TMS320C2x至TMS320C5X的软件移植时,还必须作-些迎要的修改,例如表2.2列出了有关串行口设置的一些指令的侈改。此外,还必须注意有些寄存器的地址也不相同。

表2.2 串行口指令的修改
TMS320C25 TMS320C50
RFSM APL #0FFF7H,SPC
SFSM OPL #8,SPC
RTXM APL #0FFDFH,SPC
STXM OPL #020H,SPC
FORT0 APL #0FFFBH,PC
FORT1 OPL #4,SPC
四 代码调试工具
开发DSP芯片,调试工具是必不可少的。TMS320系列DSP芯片的系统集成和调试工具主要有:
(1)C/汇编语言源码调试器。
(2)初学者工具DSK
(3)软件模拟器(Simulator)。
(4)评价模块EVM。
(5)软件开发系统SWDS
(6)仿真器XDS
下面我们分别介绍这几种调试工具。
4.1 C/汇编源码调试器
c/汇编源码调试器是一种工作在PC机上的先进的软件揍口,它与调试工具(如软件模拟器、评价模块、软件开发系统、仿真器)配合使用。调试器可以完全控制用C或汇编语言编写的程序。用户程序既可用C语言调试,也可用汇编语言调试,还可以进行C和汇编的混合调试。调试器提供了非常友好的用户界面,面向窗口、支持鼠标和莱单式的接口使用户不必记忆复杂的命令,使用十分方便。
A 调试器的主要特征
调试器的主要特征包括:
(1)提供完善的控制程序运行的特征,如:条件执行,单步执行,断点设置和清除,批文件执行命令。
(2)多操作支持:增强了并行处理能力以支持TMS320C40的多处埋器的调试。
(3)多级调试:可同时调试C和汇编语言“,调试C语言时,用户可同时观察C源码及由C源码产生的目标代码的反汇编,调试器也可用作汇编语言调试器。
(4)可灵活配置的界面:由于调试器的显示界面是可配置的,因此用户可根据需要设置不同的界面。显示的颜色、窗口的边界、尺寸和位置等都可以改变。
(5)灵活的命令输人:输入命令的方式灵活多样,可用键人命令法。鼠标、功能键或下拉莱单输入。调试器具有命令记忆功能,不必重新输人即可执行以前输人的命令。
(6)全屏幕编辑:任何窗口中显示的数据值可很容易地更改。
(7)连续更新:调试器可连续更新屏幕上的信息,并高亮显示更改的数据。
(8)综合数据显示:用户可方便地在屏幕上建立窗口以显示和编辑变量、数组、结构及指针等数据类型。
(9)功能强大的命令集:调试器提供了一个充分利用C表达式的命令集。
B 调试器的调试模式
调试器提供三种调试模式:自动模式,汇编模式,混合模式。
(1)自动模式:在自动模式中,调试器自动显示当前正在运行的代码,或者是汇编语言,或者是C语言。这也是缺省的调试模式。
(2)汇编模式:在这种模式下,显示的是汇编语言,不管运行的是C语言还是汇编语言。
(3)混合模式:在这种模式下,可以同时显示C语言程序和汇编程序。
C 调试器窗口
调试器能显示多种不同类型的窗口。窗口的名称显示在窗口的顶行。调试器共有八种类型的窗口,可以分为三大类。
1.命令显示窗:命令窗口提供一个可以键入各种命令的区域,并显示各种信息,如进程信息、错误信息或命令输出。
2.代码显示窗:显示汇编语言代码或C语言代码。有三种代码显示窗口:
(1)反汇编囱口——显示内存的反汇编码。
(2)文件窗口——显示任何文本文件,主要是C语言源程序。
(3)进程调用窗口——运行C代码时显示当前跟踪运行的函数进程。
3.数据显示窗:观察和修改各种类型的数据。有四种数据显示窗口:
(1)内存显示窗口——显示一定范围的内存内容。
(2)CPU窗口——显示处理器各个寄存器的内容。
(3)数据显示窗口——显示一个集合的数据类型,如数组、结构等。
(4)观察窗口一显示已选定的数据,如变量、寄存器或内存的某个单元。
调试器的窗口可任意移动或改变大小,在数据显示窗口中可以编辑其中的任一个值,当然,在作这些工作之前,必须首先选择好窗口并使之成为活动窗口。
D 调试器的命令输入
调试器提供了非常灵活方便的命令输人方法。调试器提供的命令输入方法主要有以下几种:
1.命令行输入
命令行输入就是在调试器的命令窗口中键人命令。如:
go main ;执行到程序的main处
win CPU :激活CPU窗口
利用调试器的记忆功能可以用简便的方法输入以前键人过的命令。如用TAB键可以向后逐条移动执行过的命令,用TAB加SHIFT键可以向前逐条移动执行过的命令,选择好以后按回车键即可。
2.菜单输入
菜单输入是一种常用的输入方法。选择菜单可以来用三种不同的方法:鼠标输入、按键输入和热键输入。热键输入主要用于没有下拉菜单的主莱单,如RUN、STEP和NEXT。鼠标输入比较方便,用鼠标左键点中相应的主菜单和下拉菜单即可。按键输入时首先同时按下ALT键和代表主莱单的高亮字母以选择主菜单,然后按下代表下拉莱单的高亮字母即可,当然也可以用方向键选择好下拉菜单再按回车键。
3.批文件输人
调试器提供的take命令可以使调试器执行一个批处理文件。设有一个批处理文件
batcom.fil的内容为:
reset
load sample.out
go main
则在调试器的命令行中键入take batcom.fil就使调试器在复位系统之后,装人sample.out 并执行至程序的main处。
E 调试器使用方法简介
使用调试器调试程序主要有以下几个步骤:调试器配置;装人程序;运行程序;观察运行结果;编辑更改数据。
1.调试器配置
在使用调试器之前,首先必须根据需要配置调试器。调试器配置包括内存配置和显示配置,其中内存配置尤为重要。内存配置用于告诉凋试器哪些内存有效,哪些内存不能进行存取。因此提供给调试器的内存映象应与实际目标系统的内存配置相一致,当然内存映象也应与链接命令文件中的 MEMORY定义相匹配。当内存映象配置好以后,启动调试器运行程序时,如果访问一个没有定义的存储区,则调试器将显示一个错误信息。一般地,配置内存可在启动调试器之前进行。方法就是在调试器能够自动读到的批文件 init.cmd中放入内存映象命令。启动调试器,在初始化过程中读入init.cmd的命令,从而完成内存配置。需要注意的是,对于不同的调试环境,init.cmd的文件名有所不同,如模拟器中的文件名为siminit.cmd,仿真器中的文件名为emuinit.cmd等。图4.1示出了TMS320C50的init.cmd的一个例子。
;TMS320C50存储映象配置
MR ;重设内存映象
MA 0,0,0x0FFFF,RAM ;程序存储器0-0x0FFFF
MA 0,1,0x7F,RAM :数据存储器 0-0x7F
MA 0x100,1,0x400,RAM ;程序存储器 0x100-0x4FF
MA 0x800,1,0,0x0FFFF,RAM ; 数据存储器 0x800-0x0FFFF
MAP ON ;启动内存映象
图4.1 TMS320C50 的内存映象例子
其中,MA(Map Add)命令定义了有效的内存范围,并标识这些范围的读写特征。对TMS320C5X而言,MA的命令格式为:MA地址,页,长度,类型
其中,地址表示一段存储器的起始地址,长度表示该段存储器的长度,类型表示这段存储器的读写特征。其中,ROM表示只读,RAM表示可读可写,WOM表示只写,PROTECT表示不可存取。IPORT表示输入口,OPORT表示输出口,IOPORT表示输入/输出口。在MA命令格式中,注意TMS320C5X有一个域“页”,分别用0,1,2表示程序存储器空间、数据存储器空间和I/O空间。MAP ON命令用于启动内存映象。
Init.cmd是在启动调试器时自动装人的。如果在启动后不想用init.cmd中的内存配置,则也可以调人另一个存储器配置。方法是可以创建另外一个内存配置文件。文件内容的格式如下:
MR :重设内存映象
MA命令 ;定义新的内存映象
MAP ON ;启动内存映象
设文件名为mem.new,则在启动调试器后,用下列命令读入即可对内存重新配置为mem.new的内容:
take mem.new
在调试过程中也可以修改内存映象。如用MA命令可增加一段内存,用MD命令可删除一段内存,用MR命令则删除内存映象中的所有内存段,还可以用ML命令列出已经定义的内存及其读写特征。除了可对内存进行配置外,其它如屏幕颜色、窗口位置、窗口大小和边框类型等也可以进行配置。缺省情况下,启动调试器自动调入init.clr文件中的配置。如果要修改配置,则在修改后将当前配置存人一个文件,下次启动调试器后再装入这个配置文件即可,也可将修改后的配直存入init.clr中,则启动调试器自动装入修改的配置,不必重新装入。
2.装人程序
调试器装入运行调试的程序是编译汇编链接后生成的 .out文件。装入的方法是在主菜单的FILE命令下选择LOAD命令,然后键入文件名即可。如果是由C程序得到的文件,则同时在FILE窗口中显示相应的C语言程序。
3.运行程序
运行程序的方法主要有:run,runb,go,单步运行等,使用方法如下:
run是最基本的运行命令,执行run命令后,程序开始运行直至遇到断点或按了ESC键或鼠标左键。
runb用来运行并计算一段程序的时钟周期数。若要计算某一段程序执行的周期数,首先在这段程序的开始和结束处各设置一个断点,然后运行run至第一个断点,再运行runb至第二个断点,在命令窗口输入? clk命令就可以得到该段程序的执行周期数。
go命令用来执行至程序的某一点,如go main就使程序执行至main标号处。
单步运行分step和next两种。用:step命令调试C语言时,每执行一次执行一条C语句,调试汇编语言时,则每执行一次执行一条汇编语句。 next命令与:step命令类似,所不同的是在遇到函数调用时,不进入函数内部,而直接执行到调用语句的下一条语句。 运行程序时,还可以有条件的运行。如,
run i< 100 即只要i< l00,调试器就一直运行。
Step 50 即step单步运行50次。
next 100 即next单步运行100次。
4.观察运行结果。
调试程序时,观察运行结果是检验程序运行正确与否的重要一步。调试器提供了灵活的观察运行结果的手段。观察数据一般有下列三种方法:
(1)直接在已有的显示窗口中观察。如在CPU窗口中可以观察到处理器的寄存器值,在存储器窗口中可以观察到一段内存的内容,首先在命令窗口中键入要观察的内存的首地址,如要观察TMS320C50从OX809800开始的一段内存,则键入
mem 0x809800
(2)在命令窗口中用?命令观察。这种方法比较适合于观察一些临时的变量。如
?I 观察变皇i的内容
?AR0 观察寄存器AR0
?Ox809800,x 以16进制观察Ox809800内存的内容
(3)增加显示窗口跟踪变量。这类显示窗口又有两种。一种是WA1CH窗,可以观察单个变量、寄存器或指定的存储单元。如
wa I 观察变量i;
wa sp 观察堆栈指针;
wa Ox809800 观察Ox809800内存的内容。
另一种是DISP窗,可以观察集合数据类型,如数组、结构等。例如
disp indata 观察数组indata;
5.编辑和更改数据。
编辑更改数据的方法主要有两种,一是直接在数据显示窗口中更改。如在CPU窗口中可以更改寄存器值,在存储器窗口中可以更改内存的内容,也可在DISP窗口和WATCH窗口中更改数据内容,另一种方法是利用表达式的附加作用更改数据。如
?AR3 + + AR3内容加l”
?AR0 = 8 AR0等于8
4.2 初学者工具 DSK
初学者工具DSK(DSP Starter Kit)是TI公司提供给初学者进行DSP编程练习的一套廉价的实时软件调试工具,每套售价仅99美元。DSK板上除了有一片DSP芯片之外,还提供了可用于声音输入和输出接口的模数模接口芯片(一般为一片TLC32044),它可以与PC机进行通信,在PC上汇编后的程序可以通过串行或并行接口下载到DSP芯片的内部RAM执行。此外,DSK板上还将DSP芯片的地址和数据总线引出,便于用户对DSK板进行存储器等硬件资源的扩充,并在DSK硬件的基础上形成用户独立的DSP系统。以下是TMS320C5X DSK所提供的软硬件资源。
TMS320C5X的DSK提供了如下软硬件资源:
40MHZ的TMS320C50(内部具有10K字的RAM);
32K字节的BOOT EPROM;
A/D和D/A转换芯片TLC32044;
与PC的RS-232C接口
汇编器;
调试器软件接口。
4.3 软件模拟器
软件模拟器是一种模拟DSP芯片各种功能并在非实时条件下进行软件调试的调试工具,它不需要目标硬件支持,只需在计算机(如PC)上运行,是一种廉价方便的调试工具。当然,由于DSP芯片用软件模拟实现,运行速度慢是软件模拟器的一个突出的缺点。软件模拟器模拟DSP芯片的I/O 口时采用与文件关联的方法来实现,因而调试中所需的I/O值可从文件中读取,输出到I/O口的值也可存储在文件中。
软件模拟器的主要特征有。
(1)在计算机上执行用户DSP程序;
(2)可修改和查看寄存器;。
(3)可修改和显示数据和程序存储器:任何时候都可进行存储器的修改,也可在程序装人前进行存储器初始化;
(4)可模拟外设、高速缓存(cache)及流水线、定时等功能;
(5)可计算指令周期数;
(6)可编程的断点设置:可在取指令、读写存储器及错误条件满足时设置断点;
(7)可进行累加器、程序计数器、辅助寄存器的跟踪;
(8)指令的单步执行;
(9)用户可设定中断产生间隔;
(10)在遇到非法操作码和无效数据访问时提示错误信息;
(ll)从文件中执行命令。
在用模拟器调试程序前,首先必须对源文件进行汇编,如果程序由多个模块组成,还迎须进行链接。链接后的绝对代码可以装人模拟器进行调试。
TI 提供的软件模拟器有:
·TMs320CIX软件模拟器
·TMs320C2X软件模拟器
·TMs320C2XX软件模拟器。
·wi320C3X软件模拟器
·TMS320C4X软件模拟器
·TMs320C5X软件模拟器
·TMs320C54X软件模拟器
在上述软件模拟器中,新版本的模拟器都采用了C和汇编源码调试器接口,允许用户用C语言或汇编语言进行调试,也可进行两种语言的混合调试,用户接口界面非常友好。其程序执行的方式有下列几种方式:单条指令/多条指令、单周期/多周期、执行到条件满足,如果条件满足一直执行、执行设置的循环次数、无条件执行至键输入等。
用软件模拟器模拟I/O口时,首先用与存储器配置相同的方法将I/O口增加到存储器映象中,然后用关联命令MC将I/O口与一个文件相关联,MC命令的格式为:
MC 口地址,页,文件名,{READ/WRITE}
其中的“页”分别用1和2表示,“1’’表示串行口,“2”表示并行口。
下面我们以TMS320C50为例说明软件模拟器模拟I/O口时的使用方法。
在TMS320C5X中,若要将50H口配置为输入口,并与in.dat文件关联,命令如下:
MC 0x50,1,0xl,IPORT ;口地址50H配置为输人口
MC 0x50,1,in.dat,READ ;口地址50H与文件in.dat关联
TMs320C50具有两个串行口,一个是标准的同步串行口,一个是TDM串行口。两个串行口的配置方法如下。
MA 0x20,1,1,IPORT ;配置DRR(0x20)为输入口
MA OX21,1,1,0PORT ;配置DXR(Ox2l)为输出口
MA 0x30,1,1,IPORT ;配置TRCV(0X30)为输入口
MA Ox31,1,1,OPORT ;配置TDXR(Ox31)为往出口
MC 0x20,1,RECV.DAT,READ ;将DRR与RECV.DAT文件关联
MC Ox2l,1,XMIT.DAT,WRITE ;将DXR与XMIT.DAT文件关联
MC 0x30,1,TRCV.DAT,READ ;将TRCV与TRCV.DAT文件关联
MC OX31,1,TXMT.DAT,WRITE ;将TDXR与TXMT.DAT文件关联
上述配置可以放人Simlator的初始配置命令文件simlaor.cmd中,则每次启动simlator调试器自动进行配置,当然在调试过程中也可以重新进行配置。
关联文件具有特定的格式,对一般的I/O口和标准的同步串行口,文件格式为每行一个16进制数,如:
OxO123
0x4567
Ox89ab
对TDM串行口,输入和输出文件格式需要三个区域:地址、数据和通道号,每个区域都是16进制格式,中间用空格分开,如:
0x80 OxO123 0
0x40 0x4567 1
0x20 Ox89ab 2
0x10 0xcdef 3
0x01 0x0123 4
Simlator模拟串行口中断和外部中断是通过设置伪寄存器的方法实现的。每一个中断设置两个伪寄存器,一个是中断周期寄存器,另一个是中断定时器寄存器。中断周期寄存器内设置的是两个中断间隔的机器周期数。中断定时器寄存器内包含的是当前至下一个中断之间的机器周期数,中断定时器寄存器以机器周期的速率进行递减,若中断使能,则递减至0时就产生一个中断,同时将中断周期寄存器中的值装人。表4.2列出了TMS320C5X串行口的伪寄存器


表4.2 串行口伪寄存器
伪寄存器 作 用 缺省值
XIRP 发送中断周期寄存器 64
XIRT 发送中断定时器寄存器 从XIRP装入
RIRP 接收中断周期寄存器 64
RIRT 接收中断定时器寄存器 从XIRT装入
TXIRP 独立方式TDM发送中断周期寄存器 64
TXIRT 独立方式TDM发送中断定时器寄存器 从TXIRP装入
TRIRP 独立方式TDM接收中断周期寄存器 64
TRIRT 独立方式TDM接收中断定时器寄存器 从TRIRP装入
TDMP TDM串行口周期寄存器 64
TDMT TDM串行口定时器寄存器 从TDMP装入

MS320C50的四个外部中断INTl、IN12、IN13和INT4的模拟也用同样的方法实现。每个中断用两个伪寄存器,一个是外部中断周期寄存器,寄存器名分别为TIC1P,TIC2P,TIC3P和TIC4P,另一个是外部中断走时器寄存器,寄存器名分别为TICIT、TIC2T、TIC3T和TIC4T。调试过程中可以用下列方法设置中断产生的间隔:
?RIRP=100 ;设置串行口接收中断间隔为100
?XIRP=100 ; 设直串行口发送中断间隔为100
?TDMP=1000 ;设置TDM串行口间隔为1000
?TIC1P=128 ;设置INT1中断间隔为128
4.4 评价模块 (EVM)
评价模块是一种低成本的开发板,在EVM板上一般配置了一定数量的硬件资源,可用来进行DSP芯片评价、性能坪估和有限的系统调试。调试接口也采用上述的C/汇编源码调试器。
4.5 软件开发系统 (SWDS)
软件开发系统是一块PC插卡,可提供低成本的评价和实时软件开发。可用来进行实时的软件调试,程序在DSP芯片上实时运行。与仿真器不同的是软件开发系统不提供实时硬件调试功能,因此涉及目标I/O操作一般用文件I/O代替。TI提供了TMS320C2X和TMS320C5X
等软件开发系统
4.6 仿真器 (XDS)
仿真器,也即扩展开发系统(XDS),可用来进行系统级的集成调试,是进行DSP芯片软硬件开发的最佳工具。目前主要有两种类型的仿真器:一种是传统的电路仿真器,主要用于早期的TMS320CIX和TMS320C2X两代DSP芯片的仿真,这两代DSP芯片没有仿真信号线;另一种是先进的扫描仿真器,主要用于TMS320C3X、TMS320C4X、TMS320C5X、TMS320C54X。
TMS320C2XX和TMS320C8X等DSP芯片的仿真,在这些DSP芯片上提供了用于仿真的一些信号线。
采用传统的电路仿真器对用户板进行硬件仿真时,仿真器的电缆插头必须插入到用户硬件电路中DSP芯片的相应位置,也就是说,仿真电缆的插头引脚必须与DSP芯片的引脚一一对应。TI的XDS/22仿真器就属于这一类,主要用于TMS320CIX和TMS20C2X等芯片的仿真。
扫描仿真器不采用插入仿真的方法,而是通过DSP芯片上提供的几个仿真引脚实现仿真功能。这种方法为TI公司所开发,可用来解决高速DSP芯片的仿真。由于高速DSP芯片具有高度并行的结构、快速的指令周期、高密度的封装等特点,采用传统的电路仿真方法很难实现可靠的仿真。扫描仿真消除了传统的电路仿真存在的问题,例如,仿真电缆过长会引起信号失真,仿真插头会引起可靠性差等问题。用户程序可在目标系统的片内或片外存储器实时运行,而不会因仿真器引入额外的等待状态。
DSP芯片内部是通过移位寄存器扫描链实现扫描仿真,这个扫描链被外部的串行口访问。采用扫描仿真,即使芯片已经焊在电路板上,也可进行仿真调试,这对于在生产过程中调试DSP系统也带来极大的方便。
TI为TMS320C3X、TMS320C4X、TMS320C5X、TMS320C2XX、TMS320C54X和TMs320C8X等
DSP芯片都提供了相应的仿真器。其中,TMS320C3X的仿真器采用了12线的仿真头,仿真器通过这个仿真头与目标系统的TMS320C3X相接进行仿真。其12线仿真头如图4.1所示。其中,EMU0-EMU3为四根仿真线,H3为时钟线,由TMS320C3X提供,第7脚的PD为存在检测线,用于指示仿真头与目标系统的连接,在目标系统中,此脚接至+5V。第8脚为空脚,其余均为地线。
除TMS320C3X之外,其它仿真器的仿真信号线都采用JTAG标准IEEE ll49.1。如TMS320C4X和TMS320C5X的仿真头均采用14根信号线,14线仿真头如图4.3所示,表4.3是仿真信号的定义。其中TDO信号与TCK时钟的下降沿对齐,TMS和TDI在TCK时钟的上升沿取样。扫描仿真器的用户界面均采用上面介绍的C/汇编源码调试器界面,与软件模拟器的用户界面完全相同。目标代码可通过扫描接口从PC机下载到目标系统的存储器中,一般下载1K字节的代码约需100mS的时间。


EMU1 1 2 GND TMS 1 2 TRSTEMU0 3 4 GND TDI 3 4 GND
WMU2 5 6 GND PD(+5V) 5 6 空
PD(+5v) 7 8 空 GND TDO 7 8 GND
EMU3 9 10 GND TCK_RET 9 10 GND
H3 11 12 GND TCK 11 12 GND
EMU0 13 14 EMU1

(a)TMS320C3X (b)TMX320C5X

图4.3 仿真器的仿真头

表4.3 JTAG仿真信号定义
仿真头信号 仿真头状态 DSP芯片状态 信号说明
TMS 输出 输入 JTAG测试方式选择。
TDI 输出 输入 JTAG测试数据输入。
TDO 输入 输出 JTAG测试数据输出。
TCK 输出 输入 JTAG测试时钟。TCK是仿真电缆头输出的10MHz时钟源。这个信号可以用来驱动系统测试时钟。
TRST\ 输出 输入 JTAG测试复位。
EMU0 输入 输入/输出 仿真脚0。
EMU1 输入 输入/输出 仿真脚1。
PD 输入 输出 存在检测。此信号用来指示仿真电缆连接正确,目标系统已加电。PD在目标系统中应接至+5V。
TCK_RET 输入 输出 JTAG测试时钟返回。测试时钟输入至仿真头,此信号是缓冲或非缓冲的TCK信号。

以上介绍了TMS320系列DSP的代码生成和代码调试两类开发工具。在代码生成工具中,介绍了C编译器、汇编器和链接器及使用方法,在代码调试工具中,介绍了C/源码调试器、初学者工具DSK、软件模拟器、评价模块EVM、软件开发相同SWDS和仿真器,并介绍了源码调试器的使用方法。了解并熟练掌握这些开发工具对于加快开发的速度提高开发效率十分重要。
返回列表