TMS320C6X是TI公司针对通信应用推出的高档32位定点、浮点DSP系列产品,采用352脚BGA封装。该系列
器件中C62X为定点型、C67X为浮点型,代码兼容,皆采用VelociTI结构。这种高性能、超长指令字VLIW
的结构使得其成为多信道、多功能应用的首选对象。VLIW通过提高指令级的并行性获得高性能。
VelociTI结构灵活,对如何及何时取指令、执行指令或存储指令的限制很少。VelociTI结构的突出特点
包括:指令打包减少代码大小、可条件执行所有指令提高灵活性、根据数据类型指令的宽度可变、完全
流水线的跳转。
TMS320C6X的CPU核由32个32bit宽的通用寄存器和8个功能单元(6个ALU和2个乘法器)组成。C6X的
地址空间为32bit的可字节寻址空间,片内存储区分成独立的数据、程序空间,通过各自的内部端口访问
。C6X的外围设备用于配合CPU工作,主要包括多通道缓冲串口McBSP、定时器Timer、外部存储器接口
EMIF、DMA控制器、HPI及降功耗单元。
TMS320C6X功能强大、灵活,在性能上具有以下突出优点:C62X的指令周期为5ns、时钟速率200MHz
、C67X的指令周期为6.5ns、时钟速率167MHz、每时钟周期可执行8条32bit的指令、最高峰值运算速度达
1600MIPS. TMS320C6X的指令集更为丰富,且功能分类明确、编程简单。TI公司为TMS320C6X提供了功能
强大的C编译器,支持优化功能。本文根据作者在实际工程中使用C62 01的一些具体体会,介绍了
TMS320C6X应用中的几个关键问题。作者在实践中使用的TMS320C6X C编译器的版本为2.0版,以下的讨论
都基于该版本。
加载程序:1 问题的提出:利用外部引脚BOOTMODE[4……0]来选择BOOT配置,在MAP1及ROM BOOT方
式下,C620 1以DMA方式将32KB的程序从CE1空间加载到地址0上。
C或汇编写的程序经链接生成。obj目标文件,目标码是以段为单位组织的。可将所有的段分为两类
:已初始化段和未初始化段。已初始化段。text 段中包含所有可执行的代码以及常量,被固定连接至程
序空间,存储器类型可以是ROM或RAM(一般为ROM,具体取决于编译时RAM或ROM方式的选择);其有两个
地址:load地址和run地址。。text段在C6201上电复位后会由默认的引导程序(boot.c)从外部F LASH
中BOOT到内部程序存储区PMEM里,可引导加载的程序大小为32KB,一般应用下可以满足要求,但是当系
统比较复杂、程序代码超过32KB时,在这种默认方式下程序就不能正常运行了。
2 解决方案:编写一段小程序使其在上电复位后由引导程序加载到PMEM中,而它的作用就是利用DMA
搬移一段程序。将真正需运行的主程序生成的。obj文件中的。text段命名为自己定义的一个段,将其
LOAD(安装)到外部FLASH中,BOOT(引导)到PMEM中的程序运行后启动DMA,将其搬移到PMEM中。具体
实现时需注意:(1)DMA的初始化配置,源地址为外部FLASH,目的地址为内部PMEM;若以字为单位传送
,则DMA计数寄存器中的值给出的搬移块的大小也是以字为单位,必须匹配,实际搬的程序大小换算成以
字为单位。
(2)DMA的搬移需判断是否完成。DMA基本控制寄存器中的STATUS位会有指示,当搬移完成后才可进
入真正需运行的主程序。
(3)因默认的BOOT程序大小为32KB,所以需要DMA搬移的程序应LOAD到32KB空间以外。且映射到一
个不同于。text段的自定义段中,这可在lnk.cmd文件中定义。
举例说明(其中example.c为需要DMA搬移的程序,。examp为自定义段,未给出其它与本例无关的内
存分配及段的映射):lnk.cmd中相关定义:PMEM1 o=0x00000200 l=0x00000A00 PMEM2 o=0x00000C00
l=0x0000F000 CE1PMEM1 o=0x01400200 l=0x00000A00 CE1PMEM2 o=0x01408000 l=0x0000F000。text
load=CE1PMEM1 run=PMEM1。examp: {example.obj(。text)} load=CE1PMEM2 run=PMEM2中断处理:
C62X/C67X的CPU根据优先级有三种类型的中断:RESET、NMI、INT4~INT15.RES ET为低有效,具有最高
优先级,在上电复位时正确初始化CPU;NMI为次高优先级中断,当发生严重的硬件错误时,会保护CPU;
INT4~INT15为12个可屏蔽中断,它们与外部器件、片内外设有关,可软件控制。
处理中断时必须包含库中提供的相关函数(intr.h、intr.c、intr_.asm),它们给出了与中断有关的函
数和变量定义。用C写中断服务子程序包括以下4部分:(1)选择中断源并写中断服务子程序ISR;(2)
产生并初始化中断向量表;(3)设置相应的寄存器使能并处理中断;(4)在链接命令文件中将各部分
链接在一起。
下面以响应外部中断4为例,给出具体的中断处理流程:(1)初始化中断intr_init(),初始化
ISTP,其值为中断服务表的首地址;(2)将外部中断源4映射到CPU中断4上:intr map(CPU INT4,ISN
EXT INT4),置中断选择寄存器相应位置处值为中断服务号4;(3)装载中断服务子程序:intr_hook(
fp,CPU_INT4),函数指针指向中断处理表中的相应表项;(4)手动清除中断标志寄存器IFR中的中断
标志位:INT_CLR_FLAG(CPU_INT4),保证IFR任何比特域中没有不必要的值;(5)使能非屏蔽中断NMI
,否则其余中断皆不能处理,中断使能寄存器IER中的NMI E位置1:INTR_ENABLE(CPU INT NMI);(6
)使能CPU中断4,中断使能寄存器IER中的相应位置1:INTR_ENABLE(CPU INT4);(7)通过设置控
制状态寄存器CSR中的GIE位,全局使能所有可屏蔽中断:INTR_GL OBAL_ENABLE()。
CPU实际处理中断时,参考中断服务表IST.IST是一个用于服务中断的含代码的取包表,IST包含16个
FP,每个ISFP包含8条指令,一个中断服务子程序匹配一个FP。中断到达时,将该ISR的入口地址装入到
跳转表isr_jump_table中相应的表项里,中断执行完后,“中断返回指针”指令B IRP保证可返回到主程
序中。C中可直接处理中断,或用关键字interrupt void 函数名()来定义一个中断服务子程序,或用
#pragma INTERRUPT(函数名)。下面举例说明:#include<intr.c> int n=0;interrupt void
intr_prg(void) 定义中断服务子程序{ n=1; } void main()
{ intr_init();intr_map(CPU_INT4,ISN_EXT_INT4);intr_hook(&intr_prg,CPU_INT4);
INT_CLR_FLAG(CPU_INT4);INTR_ENABLE(CPU_INT_NMI);INTR_ENABLE(CPU_INT4);
INTR_GLOBAL_ENABLE();while(n==1) {……} } C与汇编的嵌套调用:虽然,C语言是一种相对高效
的高级语言,并且TI提供的C编译器还结合硬件特点支持三级优化功能,但生成的汇编代码效率仍可能会
不尽人意。采用C与汇编的混合调用,既可以用C做高层控制,又可以通过汇编提高效率。
1 C调汇编:在C语言中使用汇编语言,可采取两种方式:一是调用汇编子程序,二是使用嵌入汇编
。
(1)调用汇编子程序TMS320C6X C编译器在处理函数调用时,关于如何传递入口参数以及如何返回
出口参数制定了一套严格的规则。在TMS320C6X C程序中调用汇编语言子程序,必须遵循这些规则。首先
在C中声明调用的汇编函数为外部的,若其返回值为整形则可不声明。在严格遵循入出口参数传递及寄存
器约定的前提下,调用汇编子程序和调用C子程序一样。
(2)嵌入汇编在C中调用汇编语言子程序,要求严格遵循其参数传递规则。由于TMS320C6X C编译器
支持在C源代码中直接用asm语句嵌入汇编,故在C编译器所产生的中间汇编代码的基础上,可局部使用嵌
入汇编,格式为:asm(" assemble statement")。这样,一方面可大大提高一些频繁使用的代码段的
效率,另一方面,又不用改变原来的程序框架,也便于对照仿真结果进行调试。在进行嵌入汇编时,要
特别注意流水线的冲突。TMS320C6X 采用3级流水线结构,在出现流水线冲突的地方,可插入空操作
(nop)指令来解决。
TMS320C6X 的应用一般较为复杂,因此,完全采用汇编语言进行编程将是一件很困难、也很低效的事
情。而C语言以其灵活性、易移植性,已成为单片机开发的一种趋势,对于更为复杂的DSP应用来说,更
是如此。在汇编中调用C子程序同样必须遵循其函数调用规则和寄存器使用规则。首先在汇编中声明C子
程序为。global型,传递的参数依次在A4、B4、A6、B6、A8、B8、A10、B10、A12、B12或堆栈中,传递
数组或指针皆只是将其地址置于相应的参数寄存器中,返回值存在A4中。
汇编中必须给出C的出口地址,C会自动返回到主函数中。