DSP学习初阶的一些笔记
2019-07-13 09:45发布
生成海报
这些内容都是一些基础的、概述性的知识,是本人在学习、使用DSP开始阶段的一些总结,对于DSP内部结构:各个寄存器的配置使用、各种外设的详细配置、中断处理机制、内存管理以及各种编程、调试的经验,以后有空会另外贴出。
一、DSP芯片概述:
1、各平台:
C6000平台,包含定点C62x和C64x以及浮点C67x,追求至高性能,最高达1GHz。
C5000平台,TI公司推出双核处理器OMAP,包含一个ARM和一个C5000系列的DSP。
C2000平台,包含16位的C24xx和32位的C28xx定点DSP。
C5000和C6000和C28xx系列都配有实时操作系统RTOS内核和C/C++编译器;C24xx系列仅有C编译器。
2、C28xx系列主要特 {MOD}:
1) 峰值速度高达150MIPS;
2) 具有4K字的RAM和最高达128K字的FLASH;
3) 采用双电压设计,外设电压3.3V,内核电压1.8V;
4) 12位A/D,采样速度高达80ns;
5) 软件上支持C++和实时操作系统RTOS,其数学库:智能Q格式数学库。
3、分页机制:
数据存储空间采用分页机制,2407整个空间分成512页,通过寄存器的9位指针DP来指定。分页机制有助于缩短汇编指令长短,提高访问速度。
4、外设:
SCI:经电平转换后,可用作RS-232通信。
SPI:带有同步时钟,可用来连接一些带有SPI器件,如串行E2PROM等。
EV:事件管理器,主要用途:通用定时器和PWM发生器,还包括捕获单元,QEP解码器。
10位A/D:F240采样转换时间最快是6.1us,LF<
xmlnamespace prefix ="st1" ns ="urn:schemas-microsoft-com:office:smarttags" />2407A最快500ns。
5、GEL:通用扩展语言的缩写:
GEL是一个大小写敏感但缺少类型检查的解释性语言,语法上可看作是C语言的一个子集。GEL主要用来扩展CC的功能,方便调试。
二、Q格式:
1、定点微处理器不能直接处理小数,比如要表达精度为0.01Hz的频率变量f,有三种方法:
1)把f定义为float类型。C语言中自动调用运行时函数来处理浮点运算,float类型精度最高,运算速度也最慢。一个简单的浮点加法也要好多汇编指令来实现。
2)仍定义为整型,采用放大若干倍来表示小数,但做法僵硬,精度变化时,要修改很多地方以防止溢出。
3)仍定义为整型,采用定标法。常用Q格式来表示定标,当假定小数点位于第0位的右侧时,为Q0,当小数点位于第15位的右侧时,为Q15.
浮点数Xf转换为定点数Xq时,Xq
= (int)(Xf * 2^Q)
定点数Xf转换为浮点数Xq时,Xf
– (float)(Xq * 2^-Q)
有符号32位数的Q15格式表示范围为-65536<=X<=65535.9999695。
2、定点运算:
任何数制运算都要考虑溢出,定点数之间的运算也要考虑溢出。
1)定点加减法< xmlnamespace prefix ="v" ns ="urn:schemas-microsoft-com:vml" />
必须是具有相同Q格式的数据才能相加,不同Q格式的数据必须先通过移位至相同Q格式,然后才能相加。
2)定点乘法:( )
不同Q格式数据相乘,相当于Q值相加。
3)定点除法:( )
不同Q格式数据相除,相当于Q值相减。
3、Q15格式:
程序中最常用的是Q0和Q15格式,int型变量的Q15格式数值范围是一个不超过1的小数。小数间乘法仍是小数,永远不会溢出。
如果一个数既包含整数又有小数,使用Q格式时,选定一个合适的Q格式来表示。还可以:把全部数据转化为小数,再用Q15格式表示。
假设整数x取值范围不会超过某一极限最大值,设此极限最大值为MAX,将x除以MAX转换成一个小数,再转换成Q15格式。
三、可重入性:
当被两个以上线程调用时,函数的结果仍能保证正确,当然是插入式调用的。
保障可重入性的技术:
(1) 只使用局部变量,不使用全局变量。
(2) 全局变量设定为只读类型(加关键词const),由于不进行写操作,则程序仍具有可重入性。
(3) 如果将函数和全局变量封装在一起,即封装成一个对象,且函数只能访问此对象内的成员变量,则函数具有可重入性。这就是面向对象语言(C++)的好处,提高可重入性。
(4) 屏蔽中断:当函数访问到全局变量时,为保证可重入性,在变量修改前禁止中断,修改完后再开中断。
(5) 函数只能返回一个值,当想要通过一个函数返回多个变量值时,可以采取的措施是直接在函数体内处理全局变量或传递全局变量的地址。此时的全局变量就变成了过程量(状态量),此时可用局部变量在函数内代替全局变量。
(6) 16位DSP中,若输出变量是32位,赋值操作会用两条指令——先赋值变量低16位,再赋值高16位,这中间就可能因发生中断而不能得到正确结果。解决方法是赋值前禁止中断即可。
四、C语言生成的段和CMD文件:
通用目标文件格式COFF,是一种很流行的二进制可执行文件格式。二进制可执行文件包括库文件(.lib结尾)、目标文件(.obj)、最终可执行文件(.out)等。
详细的COFF文件格式包括有段头、可执行代码和初始化数据、可重定位信息、行号入口、符号表、字符串表等。这些属于编写操作系统和编译器人员关心的范畴,从应用的层面讲,DSP的C语言应掌握两点:通过伪指令定义段,并给段分配空间。
编译器处理段得过程为:每个源文件都编译成独立的目标文件(.obj),每个目标文件含有自己的段;连接器把这些目标文件中相同段名得部分连接在一起,生成最终的可执行文件(.out)。
1、段分两大类:已初始化段和未初始化段。
1)已初始化段含有真实的指令和数据,存放在程序存储空间。程序存储空间在DSP片内是FLASH。调试代码时,下载代码到片外的程序存储空间——此时多为RAM。
.text:包含可执行的汇编指令代码。如果不声明,代码就归属.text段;
.data:一般包括常数数据。如用来对变量初始化的数据或一个正弦表格等;
.sect:用户可自行定义已初始化段;
.asect:作用类似于.sect,但多了绝对地址定位功能。
.cinit:存放用来对全局和静态变量初始化的常数。
.switch:存放switch语句产生的常数表格。
2)未初始化的段只是保留变量的地址空间,未初始化的段存放在数据存储空间中,数据存储空间多为RAM存储单元。
.bss:定义变量存放空间;
.usect:用户可自行定义未初始化段;
.stack:存放C语言的栈;
.sysmen:存放C语言的堆;
.const:简单而言,是用来存放一些特殊的常数和字符等。
2、DSP C24系列堆栈向高地址方向增长,所以堆栈段定义在数据存储空间的最后区域,即使堆栈发生溢出,也不会覆盖其他有用的数据。
3、#pragma CODE_SECTION(symbol,”section name”);
symbol是符号,可以是函数名也可是全局变量名,section name是用户自己定义的段名。
CODE_SECTION用来定义代码段,DATA_SECTION定义数据段。二者在汇编层次上分别是由伪指令.sect和.usect实现的。
使用注意:不能在函数体内声明#pragma。必须在符号被定义和使用前使用#pragma。
4、CMD文件中,page0代表程序空间,page1代表数据空间。
page0:.text,.cinit,通过#pragma
CODE_SECTION定义的段;
page1:.switch,.const,.bss,.stack,.sysmen,通过#pragma
DATA_SECTION定义的段。
CMD文件支持C语言的块注释符“/**/”,但不支持“//”。
CMD文件两大功能:指示存储空间和分配段到存储空间:
1)通过MEMORY来指示存储空间:
MEMORY
{
PAGE0:name 0 [(attr)] : origin=constant, length=constant
PAGEn:name 0 [(attr)] : origin=constant, length=constant
}
2)通过SECTIONS来分配段到存储空间:
SECTIONS
{
name:[property,property,property,…]
name:[property,property,property,…]
}
(1) name输出端的名;
(2) property输出段的属性。
A、load:定义输出段被装载到哪里的关键字,load
= allocation
Allocation可以是强制地址,如:load=0x100,更多时候,allocation是存储空间的名称。
B、run:定义输出段将会在哪里运行的关键字。CMD文件规定当只出现一个关键字load或run时,表示load地址和run地址是重叠的。
5、复杂的.const段:
三种情况会产生.const段:
1)关键词const:
由关键词const限定的带有全局变量的初始值。但由const限定的局部变量的初始值,不会产生.const段。局部变量都是运行时开辟在.bss段中的。
2)字符串常数:
出现在表达式中的字符串常数,如“strcpy(s,“abc”);”字符串常数用来初始化指针变量,如“char
*p=“abc”;”,但当字符串常数用来初始化数组变量时,不论是全局还是局部数组,都不会产生.const段,此时字符串常数生成的是.cinit段。
3)数组和结构体的初始值:
数组和结构体是局部变量,其初始化值会产生.const段。但当数组和结构体时全局变量时,其初始化值不会产生.const段,此时生成的是.cinit段。
.const段存放的是初始化的常数值,理应存放在page0才对,否则一掉电,岂不是这些常数都没有了?这是基于灵活性考虑的,程序中常会有大量的常数占用数据空间。
把.const段从page0搬移到page1,需要在两个地方设置:
A、CMD文件中的位置
B、修改连接的rts2xx.lib
六、CCS设置及TI中FFT库:
1、CCS的设置:
主要就是设置路径(头文件Linker、库文件linker、目标文件compiler—Files等的路径),堆栈大小,入口地址以及Linker
Order等。
2、TI的FFT算法:
TI公司为了加快实数FFT,巧妙的使用了压缩算法:对2N点的实数做N点复数FFT,最后再劈分还原,得到实数2N点实数FFT计算结果。
补充:
1)如果采样数据不足2的幂次方,补零,虽然很多地方说没影响,但实际补零对输出的影响,是一个复杂的插值函数关系。
2)考虑到共轭关系,对[1,N-1]点幅值结果应该乘以2,才是真正的某次谐波的幅值平方。(TI的程序只给出幅值平方,没给出幅值,如果是幅值平方则应该乘以4.)
TI手册中列出结构体类型FFT128R如下:
Typedef struct{
int *ipcbptr;
int *magptr;
int peakmag;
int peakfrq;
int normflag;
int size;
int *winptr;
void (*init1)(void);
void (*init2)(void);
void (*calc)(void *);
void (*split)(void *);
void (*mag)(void *);
void (*win)(void *);
}FFT128R;
例示:
#include “fft.h”
#pragma DATA_SECTION(ipcb,”FFTipcb”)
#define TWON 128
int ipcb[TWON+2]; //存放FFT处理的数据,Q15格式
FFT128R fft=FFT128R_DEFAULTS;
-------
}
以下是个人节选,内容来自
http://www.weeqoo.com/zhuanti/dsp/,都是些有用的知识,贴在这里,共同学习。
1、DSP的应用:
语音处理:语音编码、语音合成、语音识别、语音增强、语音邮件、语音储存等。
图像/图形处理:二维和三维图形处理、图像压缩与传输、图像识别、动画、机器人视觉、多媒体、电子地图、图像增强等。
军事:保密通信、雷达处理、声呐处理、导航、全球定位、跳频电台、搜索和反搜索等。
仪器仪表:频谱分析、函数发生、数据采集、地震处理等。
自动控制:控制、深空作业、自动驾驶、机器人控制、磁盘控制等。
医疗:助听、超声设备、诊断工具、病人监护、心电图等、CT、CAT。
家用电器:数字音响、数字电视、可视电话、音乐合成、音调控制、玩具与游戏等。
2、TI DSP的选型:
主要考虑处理速度、功耗、程序存储器和数据存储器的容量、片内的资源,如定时器的数量、 I/O 口数量、中断数量、DMA 通道数等。DSP 的主要供应商有 TI,ADI,Motorola,Lucent 和 Zilog 等,其中 TI 占有最大的市场份额。
TI 公司现在主推四大系列 DSP
1)C5000 系列(定点、低功耗):C54X,C54XX,C55X 相比其它系列的主要特点是低功
耗,所以最适合个人与便携式上网以及无线通信应用,如手机、PDA、GPS 等应用。处理
速度在 80MIPS--400MIPS 之间。C54XX 和 C55XX 一般只具有 McBSP 同步串口、HPI 并行
接口、定时器、DMA 等外设。值得注意的是 C55XX 提供了 EMIF 外部存储器扩展接口,
可以直接使用 SDRAM,而 C54XX 则不能直接使用。两个系列的数字 IO 都只有两条。
2)C2000 系列(定点、控制器):C20X,F20X,F24X,F24XX ,C28x 该系芯片具有大量 外设资源,如:A/D、定时器、各种串口(同步和异步),WATCHDOG、CAN 总线/PWM 发 生器、数字 IO 脚等。是针对控制应用最佳化的 DSP,在 TI 所有的 DSP 中,只有 C2000 有 FLASH,也只有该系列有异步串口可以和 PC的 UART 相连。
3)C6000 系列:C62XX,C67XX,C64X 该系列以高性能著称,最适合宽带网络和数字影
像应用。32bit,其中:C62XX 和<
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮