《TMS320C3X系列-DSP原理与开发技术》课件第5章_第1页
《TMS320C3X系列-DSP原理与开发技术》课件第5章_第2页
《TMS320C3X系列-DSP原理与开发技术》课件第5章_第3页
《TMS320C3X系列-DSP原理与开发技术》课件第5章_第4页
《TMS320C3X系列-DSP原理与开发技术》课件第5章_第5页
已阅读5页,还剩239页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章基于汇编语言的程序设计

5.1汇编语言源程序格式

5.2用汇编语言编程的技巧

5.3流水线操作5.4初始化程序设计

5.5典型流程控制程序设计举例

5.6算术运算和数据转换程序设计

5.7典型的信号处理算法程序设计

本章小结

思考题与习题

5.1汇编语言源程序格式

汇编语言源程序以.asm为扩展名。汇编语言源程序的每一行都可以由下面4个部分组成:

[标号][:]助记符[操作数][;注释]

标号——供本程序的其它部分或其它程序调用。助记符——助记符指令、汇编指令、宏指令和宏调用。操作数——指令中操作数或汇编命令中定义的内容。

注释——注释从分号“;”开始,可以放在指令或汇编命令的后面,也可以放在单独的一行或数行。注释是任选项。例:标号助记符源操作数目的操作数注释LOOP:SUBF3,R1;主循环体5.2用汇编语言编程的技巧

用汇编语言编写TMS320VC33程序时,为了提高程序的效率,必须充分考虑VC33本身提供的各种软硬件资源,充分发挥它们的作用。下面的编程方法有助于提高程序的效率,在实际编程过程中值得借鉴。

1.利用延迟跳转跳转分为条件跳转和无条件跳转两类。不管是有条件的标准跳转还是无条件的标准跳转,都需要执行4个指令周期。TMS320C3x提供的延迟跳转指令则可以在1个指令周期内完成。在延迟跳转指令后面的三条指令不管跳转条件满足与否都正常执行。若少于3条指令,可采用延迟跳转加NOP指令的方法。例如:

BDLOOP

ADDFR0,R1

FIX R1

STI R1,*AR1上述指令就使得跳转至LOOP的指令在STI指令执行后执行。延迟跳转也可以结合条件跳转,例如:

DBNZDAR2,LOOP

ADDFR0,R1

FIXR1

SITR1,*AR1

上述指令使得跳转持续执行到AR2中所对应地址的数据小于0为止。

2.利用单指令重复或块重复

在重复方式下,可实现无开销循环。RPTS指令用来实现单指令重复,RPTB指令用来实现块指令重复。采用RPTB指令,块起始地址被装入到寄存器RS中,块结束地址被装入到寄存器RE,而重复执行的次数由重复计数器寄存器RC的数值决定,重复的次数为RC中的数值加1。另外需要注意的是:采用RPTS指令是禁止中断的,因此在需要中断的场合,不能用RPTS指令,可改为块重复指令RPTB。

3.利用并行指令

在TMS320C3x的指令集中提供了一些可并行操作的指令,这可增加在单周期内执行的操作次数。为了达到效率最高,应注意正确使用寻址方式和安排数据。

4.利用寄存器

寄存器是访问存储器的一种有效的方式,大量准确地采用寄存器可方便并行指令的使用,并且当在寻址方式中使用寄存器时有助于避免流水线的冲突。

5.充分利用Cache

TMS320VC33芯片内提供了64×32位的高速程序缓冲Cache,对于存于Cache中的指令,可以节省取指时间,从而加快程序运行速度。因此,编程时应确保在程序初始化时使能Cache。

6.合理安排片内RAM

TMS320VC33内部提供了34K字的RAM,分为4块,其中RAM0和RAM1每块为2K字,RAM2和RAM3每块为16K字。对这些RAM的存取操作速度特别快,在单个指令周期内,可以从内部RAM中存取两次。如果采用CPU和DMA并行操作将数据传送到内部RAM中,则可使性能达到最佳。

7.避免流水线冲突

流水线操作是处理器实现高速运行的重要手段。若用户程序的执行速度没有问题,则不必考虑这个问题。但对于影响程序执行速度的关键之处,必须确认不是由于流水线冲突而造成的执行时间的增加。确认冲突的方法是运行模拟器或仿真器的跟踪功能。

8.利用循环寻址

循环寻址尤其在卷积运算中有特别功能,可大大方便数字滤波器的实现。5.3流 水 线 操 作

流水线操作是体现TMS320C3x系列DSP高性能的主要特征。任何一条指令都要经过取指令、译码、读操作数、执行等4个过程,对同一条指令不能同时进行上述4个过程的操作,但可以对不同的指令同时进行这4种操作,即每一个CPU周期中,有4条指令分别处于取指令、译码、读操作数和执行阶段,这种作业方式就称为流水线操作。流水线作业不仅提高了运算和处理速度,而且减少了总线拥挤的现象,提高了CPU的吞吐量。5.3.1流水线结构

TMS320C3x系列DSP流水线结构的四个主要阶段是:

(1)取指令:从寄存器中取指令字并更新程序计数器PC的值;

(2)译码:对指令字进行译码并产生地址。如果是间接寻址指令,还要对ARn寄存器的内容进行修改或调整,而且当数据存入堆栈或者从堆栈弹出时,控制堆栈指针的修改;

(3)读操作数:即从存储器或寄存器中读操作数;

(4)执行:从寄存器中读出操作数后,执行相应的操作,并向目的地址写结果。所有指令都必须经过上述4个阶段的处理。图5.1说明了流水线的结构,图中W、X、Y、Z代表具体指令。由图可见,在第m个周期,这4个阶段处于完全的并行状态,即完全重叠在一起,从而进入了正常的流水线作业过程。图5.1TMS320C3x流水线的结构流水线操作过程中,DMA也可能要工作,这时,优先级顺序由高到低规定为:执行、读指令、译码、取指令、DMA,即执行的优先级最高,DMA的优先级最低。尽管DMA控制器的优先级是最低的,但因为DMA有它自己的数据总线和地址总线,所以可以使其与CPU的冲突减少到最低,通过合理的设计,甚至可以完全消除冲突。5.3.2流水线冲突

1.跳转冲突

跳转冲突是由无延时的跳转指令引起的,这些跳转指令包括BR、Bcond、Dbcond、CALL、IDLE、RPTB、RPTS、RETIcond、RETScond。另外,中断和复位也会使程序的流程发生变化,所以也会引起这类冲突。由于遇到了跳转指令而产生这类冲突,因而需要跳转到相应的地址处理相关的指令,而在现行流水线上已经完成了取指等作业的指令将不再被进行后续的处理,从而导致了现行流水线的无效,因此必须对流水线进行刷新。例5.1由跳转指令引起的流水线冲突。

BRTHREE ;无条件跳转

MPYF ;没有执行

ADDF ;没有执行

SUBF ;没有执行

AND ;没有执行

THREE: OR;执行跳转指令后才取指

STI

指令执行过程如图5.2所示。图5.2由跳转指令引起的流水线冲突在这个例子中,MPYF指令的取指与BR指令的译码是同时进行的,BR指令译码后不再对紧随MPYF后面的下一条指令进行取指,而是处于等待状态,以便等BR指令执行后得到新的跳转地址或PC值时再取指,BR指令执行的结果是PC = 3。显然,由于跳转指令BR而使正常的流水线作业的顺序被打破了,在流水线上插入了许多“(nop)”。本例及今后的例子中,在取指、译码、读操作数、执行等各个阶段,如果由于某种原因而不能执行特定的功能时,都用“(nop)”填充。需要指出的是:能够引起这类冲突的指令中也包括了RPTS和RPTB,它们同样可以引起流水线的刷新,原因是这些指令需要对RS、RE和RC寄存器进行装载。如果对这些寄存器的装载没有使用RPTS和RPTB指令,而是将RS、RE和RC用作为通用寄存器,通过LDI等指令装载,就不会产生流水线冲突。总之,当RS、RE和RC作为32位通用寄存器使用时是不会发生冲突的。由于中断嵌套而引起RPTB的嵌套时,在采用重复方式的时候有必要直接装载和存储这些寄存器。由于在进入重复方式之前最多可以取4条指令,执行装载操作时需采用一条跳转指令来刷新流水线。当一条指令在装载RC时且RC正发生变化,则直接装载操作的优先级别高于重复方式的修改操作。

在跳转指令引起的这类冲突中,所述的跳转指令不包括延时跳转指令,这是因为延时跳转本身的含义是要延时三个周期后再跳转,这就允许紧跟其后的三条指令被取指后再跳转,可以保证每个CPU周期中都有一条指令处于被执行的状态。例5.2延时跳转指令可以保证紧跟其后的三条指令被执行。

BRDTHREE ;无条件延时跳转

MPYF ;执行

ADDF ;执行

SUBF ;执行

AND ;不执行

THREE:MPYF;在取SUBF之后取指

指令执行过程如图5.3所示。图5.3延时跳转指令可以使其后的三条指令被执行延时跳转包括BRD、Bcond和DbcondD,在本例中,虽然由于延时指令的延时作用保证了每个CPU周期都有一条指令被执行,但如果在等待三条指令的过程中遇到了中断,则中断也将被延时三个周期后才响应,这就造成了中断响应不及时的问题。对于一些需要精确定时间的场合,会造成很大的误差。以TMS320VC33为例,如果CPU的指令周期为18 ns,则三个周期的时间为54 ns,如果将DSP用于超声波测量流速的场合,根据时间差法求出的流速的最小分辨率将比原来降低3倍,同时也会造成测量结果的不稳定。因此,在使用延时跳转指令时,必须考虑到这一点。

2.寄存器冲突

寄存器冲突是在对产生地址的寄存器进行读、写等操作的过程中,如果相应的寄存器还没有做好被使用的准备而发生的冲突。这类寄存器可分为三组:

(1)辅助寄存器AR0~AR7,索引寄存器IR0、IR1,程序块规模寄存器BK;

(2)数据页指针DP;

(3)系统堆栈指针SP。对这三组寄存器中的某一个寄存器进行写操作时,直到写操作完成之前,译码器是不能使用该寄存器所在组中的任何寄存器的,这就造成了译码的延时,从而也就造成了执行的停顿,即不能保证每个CPU周期都有一条指令处于被执行的状态。这里所述的寄存器写操作是指LDF、LDI、LDII或DB等指令所执行的写操作,不包指令执行前或执行后对ARn寄存器内容所进行的增、减等调整。例5.3写ARn指令的后面紧随着一条用ARn产生地址的指令,这时会产生流水线冲突。

LDI 7,AR2 ;7→AR2

NEXT

MPYF *AR2,R0 ;译码延时2个周期

ADDF

FLOAT

这时会产生流水线冲突,如图5.4所示。图5.4产生流水线冲突(一)在该例中,先对辅助寄存器AR2进行写操作,下一条指令用AR2产生地址,由于在完成AR2的写操作之前不能使用该寄存器,而第二条指令也要用到该寄存器,所以第二条指令的译码就延时了两个周期。因为第二条指令的译码被延时,所以对第三条指令的取指便重复执行,在本例中,ADDF指令被取指3次。

前面是对寄存器进行写操作的例子,对其进行读操作也会产生类似的情况。例5.4读ARn指令的后面紧随着一条用ARn产生地址的指令而产生流水线冲突。

ADDIAR0,AR1,R1 ;AR0+AR1→R1

NEXT MPYF*++AR2,R0;译码延时一个周期

ADDF

FLOAT

指令执行过程如图5.5所示。图5.5产生流水线冲突(二)该例中,第一条指令对AR0和AR1进行读操作,这两个辅助寄存器的内容相加后将结果写到扩展精度寄存器R1中,下一条指令使用了一个不同的辅助寄存器AR2产生地址,因为这些寄存器处于同一组中,所以在完成读操作之前,不能使用该组中的任何寄存器,这就产生了流水线冲突。等ADDI指令完成读操作后,就可对第二条指令进行译码了,这就产生了一个周期的延时。需要注意的是:①对IR0、IR1、BK或DP等4个寄存器进行读操作时不会引起延时,而对其它的寄存器进行操作时均会发生延时;②在一条指令中通过辅助寄存器产生地址不认为是一次读操作,如*ARn、*++ARn、*-ARn等。

3.存储器冲突

当物理存储空间中的存储器在一个CPU周期内被访问的次数超过规定的次数时,就会发生存储器冲突。例如:RAM0、RAM1、RAM2、RAM3等存储器在每个周期内只支持两次存取操作,外部扩展的存储器每周期只支持一次存取。如果超过这种规定,就会发生冲突。存储器存取引起的流水线冲突有四种类型:

(1)在一个周期内对存储器进行多次访问引起的冲突。由于在一个CPU周期内对片内RAM或外部端口的存取超过了规定的次数而阻止了程序的取指,由此引起的等待称为程序等待。

(2)取指需要多个周期而引起的冲突。程序取操作已经开始,但在一个周期内仍没有完成。

(3)相邻两条指令对存储器多次存取及互锁装载指令引起的冲突。

(4)外部端口操作及条件调用和条件陷阱引起的冲突。下面对这四种类型的冲突分别进行讨论。

(1)在一个周期内对存储器进行多次访问引起的冲突。有两种情况会阻止程序取指操作的开始,分别是:①有两个CPU数据需要在RAM中存取,但同时又必须对同一RAM进行程序取指,或者正在对一外部端口进行数据存取的同时,又必须对该端口进行取指操作;②一个多周期的CPU数据或DMA数据需要在外部端口上进行存取。例5.5在一个CPU周期内对存储器进行二次以上的存取而引起的冲突。

ADDF3*AR0,*AR1,R0

FIX

MPYF

ADDF3

NEGB

这时会产生流水线冲突,如图5.6所示。图5.6产生流水线冲突(三)该例说明了程序等待直到CPU数据存取完成。在这种情况下,*AR0和*AR1二者都指向RAM块0中的数据,并且MPYF指令取自RAM块0,导致了在n+2周期中需要对存储器存取三次,由于在单周期内不能对RAM块0进行两次以上的存取操作,所以在n+2周期中MPYF指令不能进行取指,必须等待CPU数据存取完之后才能开始程序的取指操作。

例5.6由于多周期数据的存取产生的程序等待。

ADDF ;代码在内部存储器

MPYF ;代码在内部存储器

SUBF ;代码在内部存储器

CALL ;代码在外部存储器

这时会产生程序等待,如图5.7所示。图5.7产生程序等待该例给出了由于多周期数据存取或多周期DMA存取操作而发生程序等待的例子。ADDF、MPYF和SUBF指令取自内部存储器,DMA是对外部端口进行操作,但在DMA存取的同时,CALL指令的取指采用了与DMA相同的端口,从而造成了在一个CPU周期内对同一外部端口进行两次存取的情况。由于在同一周期内只能对外部端口进行一次存取,从而造成了流水线冲突。

(2)取指需要多个周期而引起的冲突。当取指令需要多于一个周期的时间来完成时,就会发生冲突。

例5.7多周期取指引起的冲突。

多周期取指引起的冲突如图5.8所示。图5.8多周期取指引起的冲突本例中,MPYF和ADDF指令取自支持单周期存取的存储器,但SUBF指令取自需要插入一个等待状态的存储器,即需要两个周期才能完成取指,这就造成了在一个CPU周期内不能完成单条指令取指的现象,从而导致了流水线冲突。

(3)相邻两条指令对存储器多次存取及互锁装载指令引起的冲突。有三种情况可以导致这种现象的发生:①一条指令进行存储操作,随后一条指令进行两次存储器读操作;②一条指令执行两次存储操作,随后一条指令至少执行一次存储器读操作;③执行一条互锁装载(LDII或LDFI)指令,并且XF = 1。例5.8一条指令进行单次存储器存取,随后一条指令进行两次读操作而引起的流水线冲突。

STF0,*AR1 ;R0→*AR1

LDF*AR2,R1 ;*AR2→R1 ;两条指令并行执行

||LDF*AR3,R2 ;*AR3→R2

这时会产生流水线冲突,如图5.9所示。图5.9产生流水线冲突(四)本例中,W、X、Y代表具体指令。第一条指令STF对存储器进行一次写操作,第二条指令为并行指令,需要对存储器进行两次读操作,由于这个序列需要第n+3周期中试图完成三次存储器数据存取,但只允许进行两次存取操作,因此只有在第一条指令STF完成了写操作后,第二条指令才能开始读操作数,所以LDF‖LDF指令所需的双重读操作将延时一个周期。例5.9一条指令并行存储,随后一条指令进行一次读操作而引起的流水线冲突。

STFR0,*AR0 ;R0→*AR0并行执行

‖STFR2,*AR1 ;R2→*AR1

ADDF@SUM,R1 ;R1+@SUM→R1

IACK

ASH

这时会产生流水线冲突,如图5.10所示。图5.10产生流水线冲突(五)该例中,并行指令LDF‖LDF执行时,需要进行两次写操作,所以在该指令被执行的第n+3周期中,不能同时对紧随其后的ADDF指令进行读操作数,只有等待第一条指令执行后,第二条指令才能读操作数。

例5.10互锁加载操作引起的流水线冲突。

NOT R1,R0

LDII 300h,AR2

ADDI *AR2,R2

CMPI R0,R2

这时会产生流水线冲突,如图5.11所示。图5.11产生流水线冲突(六)由于互锁加载使用XF1引脚作为读操作完成的响应,加载可能需要扩展读操作周期。

(4)外部端口操作及条件调用和条件陷阱引起的冲突。这类流水线冲突的三种情况包括:①因为外部端口忙而不能执行CPU数据加载或存储;②外部加载占用一个以上周期;③条件调用和陷阱,二者的执行时间比执行条件跳转多一个周期。例5.11外部端口繁忙引起的流水线冲突。

STFR0,@DMA1

LDF@DMA2,R0

这时会产生流水线冲突,如图5.12所示。图5.12产生流水线冲突(七)在该例中,W、X、Y代表具体指令。因为外部端口的速度较慢,第一次存储操作要用两个周期才能使CPU把数据写到一个外部端口,但LDF指令所完成的操作是在同一外部端口上进行的一次读操作,只有等待STF指令执行完后,LDF指令才能获得端口。

例5.12读操作数需要多个CPU周期而引起的流水线冲突。

LDF@DMA,R0

这时会产生流水线冲突,如图5.13所示。图5.13产生流水线冲突(八)本例中,I、J、K代表具体指令。LDF指令在读操作数期间,需要两个周期才能完成,从外部的低速存储器中读操作数就是典型的例子。

例5.13条件调用和陷阱。

条件调用和陷阱如图5.14所示。图5.14条件调用和陷阱本例中,I代表具体指令。条件调用(CALLcond)和条件陷阱(TRAPcond)指令不同于其他条件跳转指令,其他条件跳转指令只是完成条件加载操作,而这两条指令则必须完成条件存储操作,它们比条件跳转指令多占用一个周期。调用条件满足之后,这个多占用的附加周期用以将返回地址推入堆栈。5.3.3解除寄存器冲突

在5.3.2节中曾讨论了寄存器引起的流水线冲突的例子,下面结合例5.14、5.15和5.16给出一些常见的消除流水线冲突的具体方法。

例5.14不产生流水线冲突。第一条指令用AR产生地址,并在指令执行前对ARn的内容进行调整,该指令的后面紧随一条用ARn产生地址的指令。

LDF7.0,R0 ;7.0→R0

MPYF*++AR0(IR1),R0

ADDF*AR2,R0

FIX

MPYF

ADDF

这时不会产生流水线冲突,如图5.15所示。图5.15不产生流水线冲突(一)例5.15无流水线冲突。流水线序列中的一条指令写ARn,该指令后面的第三条指令用ARn产生地址。

LDI@TABLE,AR2

MPYF@VALUE,R1

ADDFR2,R1

MPYF*AR2++,R1

SUBF

STF

这时无流水线冲突,如图5.16所示。图5.16无流水线冲突例5.16一条指令对DP进行写操作,在同一流水线上出现的另一条指令以直接寻址方式对存储器进行读操作,避免产生流水线冲突。

LDPTABLE_ADDR

POPR0

LDF*–AR3(2),R1

LDI@TABLE_ADDR,AR0

PUSHF R6

PUSHR4

这时不会产生流水线冲突,如图5.17所示。图5.17不产生流水线冲突(二)5.4初始化程序设计

在操作DSP硬件系统时必须先初始化,在大多数场合,对使用的寄存器和总线也要进行初始化。但若DSP芯片的硬件资源被充分利用,则需要对处理器初始化。执行数字信号处理算法以前,必须对处理器初始化,通常初始化可在复位后的任何时候进行。复位后,DSP结束正在执行的程序,跳转到装载存储复位向量的地址,并从该点开始执行程序。复位向量通常包含系统初始化地址。通常初始化程序需要执行以下几个任务:

(1)设置数据页指针;

(2)设置堆栈指针;

(3)设置中断向量表;

(4)设置陷阱向量表;

(5)设置外部存储器控制寄存器;

(6)清除/使能高速缓冲存储器。

如果仅使用汇编环境,初始化程序在硬件复位时执行,TMS320C3x初始化的源程序略。

下面给出了两个具体的实例,说明重要寄存器和中断初始化方法。例5.17DP、SP、ST寄存器和主总线初始化。

init:LDP0,DP ;DP初始化

LDI@STACK,SP;SP初始化

LDI1800H,ST;ST初始化

LDI@MCTL,AR0;MCTL主总线控制寄存器地址

LDIMBUS,R0 ;主总线赋初值

LDIR0,*AR0

MCTL .word808064H

STACK .word809e00H

MBUS .set1038H;主总线设置初值,插入了1个等待状态例5.18定时器中断初始化。

定时参数的计算公式为

定时参数=外部时钟频率× ÷ 采样频率

若采样频率为8192 Hz,外部时钟频率为12 MHz,即CPU工作在120 MHz,则定时参数设置为732H。initt0: LDI 0,R0

LDI 808H,AR0

LSH 12,AR0

ADDI 20H,AR0

STI R0,*+AR0(4)

LDIsample_f,R0, ;设置采样频率周期

STI R0,*+AR0(8)

LDI 3C1H,R0

STIR0,*AR0

RETS

sample_f.set727H ;根据VC33的工作时钟,设置采样频率

定时中断启动语句

LDI100H,IE ;定时器0中断使能

LDI2000H,ST;启动定时器中断

对于定时器、串行口以及DMA控制器的初始化程序在第2章的片内外设一节已给出,可参阅该部分的内容。5.5典型流程控制程序设计举例

5.5.1子程序调用

TMS320C3x有一个24位的程序计数器(PC)和不受限制的堆栈空间。使用CALL和CALLcond指令调用子程序时,堆栈指针增加,并且存储下一个PC值到堆栈中。在子程序结束时,RETScond指令执行有条件返回操作。例5.19如何用一个子程序实现两个矢量的点乘。假定两个长度为N的矢量,分别用数组a[0],a[1],,a[N-1]和b[0],b[1],,b[N-1]表示,点乘由下式计算:

d = a[0]·b[0] + a[1]·b[1] + … + a[N-1]·b[N-1]

在子程序中计算点乘时,首先假定子程序变量已被适当初始化,用CALL指令调用子程序,传送控制到执行子程序的程序存储器部分,然后在子程序执行完成后,由RETS指令将控制返回到调用程序。子程序调用(点乘计算)LDI@blk0,AR0 ;AR0指向矢量aLDI@blk1,AR1 ;AR1指向矢量bLDIN,RC CALLDOT;点乘方程:d = a[0]·b[0] + a[1]·b[1] + … + a[N-1]·b[N-1];AR0a(0)的地址;AR1b(0)的地址;RC——向量N的长度;AR0,AR1,RC为输入寄存器;R0存放结果globalDOTDOT:PUSHST ;保存状态寄存器PUSHR2 ;将R2内容放入堆栈PUSHFR2 ;低32位和高32位PUSHAR0 ;保存AR0内容PUSHAR1 ;保存AR1内容PUSHRC ;保存RCMPYF3*AR0,*AR1,R0 ;a(0)*b(0)→R0LDF0.0,R2 ;初始化R2SUBI2,RC ;设置RC

=

N-2;DOTPRODUCT(1<=i<N)RPTSRC ;建立单指令重复MPYF3*++AR0(1),*++AR1(1),R0 ;a(i)*b(i)→R0||ADDF3R0,R2,R2 ;a(i-1)*b(i-1)+R2→R2ADDF3R0,R2,R0 ;a(N-1)*b(N-1)+R2→R0RETURNSEQUENCEPOPRC ;恢复RCPOPAR1 ;恢复AR1POPAR0 ;恢复AR0POPFR2 ;恢复R2中的高32位POPR2 ;恢复R2中的低32位POPST ;恢复STRETS ;子程序返回.end5.5.2中断服务程序

TMS320C3x的中断是矢量化的,并具有一定的优先级。当发生中断时,相应的标记置入中断标志寄存器(IF)中。如果中断允许寄存器(IE)中的相应位已置位,状态寄存器中全局中断使能(GIE)位置1,则中断使能,开始中断处理。也可以写中断标志寄存器(IF),允许用户用软件强迫产生一个中断或不作任何处理清除中断。要使中断正确工作,须执行下列步骤:①在合适的存储器中,创建并放置一个中断向量表;②创建软件堆栈;③使能相应的中断;④使能全局中断;⑤产生中断信号。

1.软件查询中断读中断标志寄存器的目的是看中断是否发生,甚至在中断禁止时也可以读。在中断驱动接口不工作时,查询非常有用。例5.20表示外部中断1不工作时,调用程序的情况。例5.20软件查询中断的用法。

TITLINTERRUPTPOLLING

TSTB2,IF ;查询中断INT1是否发生

CALLZSUBROUTINE ;如果没有中断,调用子程序当中断处理开始时,程序计数器PC被压入堆栈,中断向量装入PC中。中断可用GIE = 0禁止,程序可以PC装入的地址继续执行。由于所有中断被禁止,该中断处理可不被打断地继续执行,除非中断服务程序重新允许中断。除了十分简单的中断服务程序以外,在执行中断程序时,保护好处理器的状态是十分重要的。执行中断程序之前,必须保护状态,且在中断程序结束后要恢复状态,这个过程被称为上下状态转换。上下状态转换在子程序调用时也十分有用,特别是执行子程序要用到辅助寄存器和扩展精度寄存器时。

2.上下状态转换当处理子程序调用或中断时,通常需要上下状态转换,它可以很复杂也可以很简单,这取决于系统的要求。在TMS320C3x中,程序计数器自动压入堆栈,如果要将这些重要信息存放在状态寄存器、辅助寄存器和扩展精度寄存器中,就必须使用专门的存储指令。堆栈用来保护寄存器内容,利用PUSH指令向高地址扩展。如果不希望用SP指向的堆栈,可用一个辅助寄存器作为堆栈指针产生另一个独立的堆栈。堆栈中被保护的寄存器有:扩展精度寄存器(R0~R7)、辅助寄存器(AR0~AR7)、数据页指针(DP)、变址寄存器(IR0和IR1)、块大小寄存器(BK)、状态寄存器(ST)、有关中断的寄存器(IE和IF)、I/O标志(IOF)、有关重复的寄存器(RS、RE和RC)。在上下状态切换时,仅仅保护在子程序或者中断服务程序中改变的寄存器以及受上下程序影响的寄存器。

3.中断优先级

TMS320C3x的中断是自动设置优先级的,允许同时发生的中断按预定的次序服务,不经常出现的而且较长的中断程序可以被经常出现的中断打断。例5.21中,INT2的中断服务程序临时修改中断允许寄存器IE,这样当发生INT0中断(不是别的中断)时,允许处理INT0的中断,当这个中断程序处理结束时,寄存器IE恢复到它原来的状态。注意:REIT指令不仅从堆栈中弹出下一个程序计数器的地址,同时也置状态寄存器的GIE位,这使所有相应的中断使能。例5.21中断服务程序。

.globalISR2

ENABLE.set2000h

MASK.set1

PUSHST;保存状态寄存器ST

PUSHDP;保存数据页指针DP

PUSHIE;保存中断使能寄存器IE

PUSHR0;保存R0的低32位

PUSHFR0;保存R0的高32位

PUSHR1;保存R1的低32位

PUSHFR1;保存R1的高32位LDIMASK,IE;INT0中断使能ORENABLE,ST;开中断XORENABLE,ST;关中断POPFR1 ;恢复R1的高32位POPR1 ;恢复R1的低32位POPFR0 ;恢复R0的高32位POPR0 ;恢复R0的低32位POPIE ;恢复中断使能寄存IEPOPDP ;恢复数据页指针DPPOPST ;恢复状态寄存器STRETI ;中断返回,开中断5.5.3延时跳转延时跳转与非延时跳转的操作过程是类似的,但是它不刷新流水线,而是执行紧跟在延时跳转指令后的三条指令。紧跟在延时跳转指令后的三条指令不允许为如下类型:跳转(无延时)、对子程序调用、从子程序返回、从中断返回、重复指令、软中断指令TRAP以及空等待指令IDLE。条件延时跳转指令所用的条件放在指令后面紧靠延时跳转符号D的前面。有时在程序流中必须跳转,但是在延时跳转指令后又少于三条指令,为快速执行,仍可取延时跳转的优点。例5.22中,NOP放在无用指令的位置就是起这作用。当然这里采用了一个折中的方法,即用较少执行时间但用了较多的指令字。例5.22执行延时跳转。

LDF*+AR1(5),R2 ;装载存储器的内容到R2

BGEDSKIP ;如果装载值>0,则延时跳转

LDFNR2,R1 ;如果装载值<0,则装载到

R1

SUBF3.0,R1 ;R1-3

NOP ;空操作完成,则执行延时跳转

MPYF1.5,R1

SKIP:LDFR1,R35.5.4重复操作

TMS320C3x具有不需要增加执行时间的重复循环方式,对应有两条指令:重复块程序的RPTB指令和重复单条指令的RPTS指令。还有三个控制寄存器:重复起始地址(RS)、重复结束地址(RE)和重复计数器(RC),它们包含循环执行的参数。

1.块重复

例5.23块重复结构的应用举例。

在此例中,一个包含64个元素的数组通过交换元素位置而使其倒装,即数组单元从末尾开始。换言之,如原始数组排列为

a[1],a[2],…,a[31],a[32],…,a[64]

则最后数组的排列为

a[64],…,a[32],a[31],…,a[2],a[1]注意:因为交换操作是两个元素同时进行的,因此需要32次操作,重复计数器RC初始化为31。通常如RC包含值N,则循环执行N+1次。循环由RPTB指令和EXCH标志所决定。例5.24用块重复方式循环。

LDI@ADDR,AR0 ;AR0指向数组的开始地

LDIAR0,AR1

ADDI63,AR1 ;AR1指向包含64个元素

的数组的结束地址

LDI31,RC ;初始化块重复计数器

RPTBEXCH ;从本条指令到EXCH指令之间重复执行32次

LDI*AR0,R0 ;装载一个存储器的元素到

R0

||LDI*AR1,R1 ;装载另一个存储器的元素到

R1

EXCH:STIR1,*AR0++(1) ;交换它们的位置

||STIR0,*AR1--(1)根据块重复结构方式的限制,循环计数器在循环末端按寄存器RS、RE和RC的内容修改,因此不能用其它方法在循环末端修改重复计数器或程序计数器。原则上块重复程序是可以嵌套的。然而,因为仅有一组控制寄存器RS、RE和RC,因而在进行内循环之前必须保存这些寄存器。也可以将寄存器作为一个计数器,并用延时跳转,而不用重复块嵌套。例5.25用块重复程序找147个数中的最大值。LDI146,RC ;初始化块重复计数器RC=146LDI@ADDR,AR0 ;AR0指向数组的开始地址LDF*AR0++(1),R0 ;初始化最大值为第一个数

RPTBLOOPCMPF*AR0++(1),R0 ;与最大值比较LOOP: LDFLT*+AR0(1),R0 ;如果大于前一最大值,则设置为新的最大值

2.单指令重复和块重复方式相同,单指令重复操作也用控制寄存器RS、RE和RC,块重复的优点是指令仅取一次,然后总线供搬移数据使用。单指令重复和块重复程序的不同之处是单指令重复不可中断,而块重复允许中断。例5.26用单指令重复方式循环。在本例中计算两个数组相应元素乘积的和。设数组为a[i]和b[i],长度都为N=512,计算结果放在寄存器R0中。d = a[1]·b[1] + a[2]·b[2] + … + a[N]·b[N]在指令中重复计数器RC的值定为511,则循环执行512次。LDI@ADDR1,AR0 ;AR0指向数组a(i)LDI@ADDR2,AR1 ;AR1指向数组b(i)LDF0.0,R0 ;初始化R0MPYF3*AR0++(1),*AR1++(1),R1 ;计算第一个值并放入R1RPTS511 ;重复512次MPYF3*AR0++(1),*AR1++(1),R1 ;计算下一个值||ADDF3R1,R0,R0 ;并与前一个值相加ADDFR1,R0 ;在R0中存放最后的结果5.5.5位操作

1.位管理

TMS320C3x的普通逻辑运算指令(如AND、OR、NOT、ANDN和XOR等)和位移指令结合起来可用于位管理。此外,还有用来测试位的特殊指令TSTB、TSTB和AND,但AND的结果不写入任何寄存器仅用来作为条件标志。例5.27和例5.28说明用于位管理和测试的几条指令。例5.27STB指令用于软件控制中断。

TSTB0100b,IF;查询IF的第2位是否为1

CALLNZINTR;如果是,调用INTR子程序例5.28将一个寄存器的某一位移至另一个寄存器的另一位。;R1中的第I位复制到R2中的第J位(见图5.18)

LDI1,R0

LSH*AR0,R0 ;将1移到第I位

TSTBR1,R0 ;查询R1中的第I位BZDCOUNT;如果第I位等于0,则执行延时跳转LDI1,R0LSH*+AR0(1),R0;将1移到第J位ANDNR0,R2;如果第J位为0,则复位R2中的第J位ORR0,R2;如果第J位为1,则置位R2中的第J位COUNT…图5-18位操作示意图

2.位反转寻址

TMS320C3x具有位反转寻址的能力,可有效地实现快速傅里叶变换(FFT)。若数据以正确的次序传送,FFT的最后结果的次序是打乱的(位反转的次序)。为使频域数据以正确次序排列,某些存储器位置应作相应的交换。位反转寻址方式提供了不必作交换的方法,即下一次所需存取的数据是以位反转方式存取而不是顺序存取。位反转寻址的基地址必须位于循环寻址空间的起始位置。比如,若IR0 = 2n-1,则基地址的最低有效位的零的个数n必须满足2n > R,R是循环寻址空间的大小。在位反转寻址方式中,如实部和虚部数据存在分开的数组中,则IR0的内容是FFT点数的一半。辅助寄存器寻址由IR0变址完成,但变址是反向进位的。例5.29说明了512点复数FFT数据移动的情况,计算结果从计算的位置(AR0指向的位置)移到AR1指向的位置。在本例中,数据的实部XR(i)和虚部XI(i)不是存放在两个独立的数组中,而是在一个数组中交替存储,由于这样的排列,数组长度是2N,而不是N,即IR0的内容为512而不是256。排列的顺序为:XR(0),XI(0),XR(1),XI(1),…,XR(N-1),XI(N-1)。例5.29位反转寻址。

LDI512,IR0

LDI2,IR1

LDI511,RC ;设置RC=511

LDF*+AR0(1),R1;装载第一个虚部

RPTBLOOP

LDF*AR0++(IR0)B,R0;装载实部(指向下一个位置)

|STFR1,*+AR1(1) ;存储虚部

LOOP: LDF*+AR0(1),R1;装载下一个虚部

||STFR0,*AR1++(IR1) ;并且保存前一个实部5.5.6数据块转移由于TMS320C3x可直接寻址大量存储器,因此数据块或程序块可存储在片外低速存储器中,然后装入片内高速RAM中快速执行,数据也可从片内移到片外以存储数据或作多处理器间的数据传输。使用DMA在不影响CPU工作的情况下可以进行数据的直接传输,也可以在重复方式下用装入和存储指令来代替DMA进行数据传输。例5.30是512个浮点数从外部存储器传送到片内RAM的情况。例5.30在程序控制下的块传送。

extern.word01000h

block1.word0809C00h…

LDI@extern,AR0;源地址

LDI@block1,AR1;目的地址

LDF*AR0++,R0;装载第一个数

RPTS510;下一条指令重复511次

LDF*AR0++,R0;装载下一个数

||STFR0,*AR1++;存储前一个数

STFR0,*AR1;存储后一个数5.6算术运算和数据转换程序设计5.6.1整数和浮点数除法在TMS320C3x中,除法虽不是用单条指令实现的,但单指令集可以实现除法程序。整数除法和浮点数除法使用的算法不同,整数除法利用减法指令SUBC重复进行来完成,而浮点数除法采用倒数的方法实现。在第3章中,浮点数除法已有叙述,在此只给出整数除法的算法。

TMS320C3x实现除法是用SUBC这条特殊减法指令重复进行来完成的,考虑i位有效位(32-i位符号位)的32位正整数,SUBC指令重复i-j+1次产生32位结果,这里低i-j+1位为商数,高31-i + j位为除法余数。

SUBC实现除法和长除法的方式是一样的。除数(假定小于被除数)左移i-j位和被除数对准,然后用SUBC指令移动除数从被除数中减去。若每一次减法的结果不为负,则被除数用减法差值代替后,左移1位,且其中最低位放1;若结果为负,则被除数简单地左移1位,整个操作重复i-j+1次。比如33被5除的情况,这时i = 6,j = 3,SUBC操作重复6-3+1 = 4次。当用SUBC命令时,除数和被除数均为正。例5.31整数除法。;R1输入除数;R0输入被除数;输出结果R0/R1

.globalDIVISIGN.setR2TEMPF.setR3TEMP.setIR0COUNT.setIR1XORR0,R1,SIGN;取符号ABSIR0ABSIR1CMPIR0,R1;比较:除数>被除数吗BGTDZERO;成立,则跳至ZERO标号执行FLOATR0,TEMPF;归一化被除数PUSHFTEMPF;以浮点格式压入堆栈POPCOUNT;以整型弹出堆栈LSH-24,COUNT;取被除数的指数FLOATR1,TEMPF;归一化除数PUSHFTEMPF;以浮点格式压入堆栈POPTEMP;以整型弹出堆栈LSH-24,TEMP;取除数的指数SUBITEMP,COUNT;被除数指数和除数指数相减LSHCOUNT,R1;除数移位,移动位数为指数差值RPTSCOUNTSUBCR1,R0SUBRI31,COUNT;移位(32-(COUNT+1))LSHCOUNT,R0;左移NEGICOUNTLSHCOUNT,R0;右移取结果NEGIR0,R1;结果取反ASH-31,SIGN;核对符号LDINZR1,R0;如果是1,用取反的结果CMPI0,R0;从结果设置状态寄存器中的标志位RETS;RETURNZERO:LDI0,R0RETS.end若被除数小于除数,则要进行分数除法,当确定商数精度为多少位之后,可以进行这种除法。若希望商数精度为K位,开始先将被除数移K位,然后用上面的方法即可,但i应为i+k代替,i+k小于32。5.6.2平方根

TMS320C3x计算平方根所用的迭代方法十分类似于计算倒数所用的方法,此方法计算数值v平方根的倒数,即1/,由此可以求出平方根()等于这个倒数(1/)与原数值(v)相乘。在第i次迭代中,1/的估算值X[i]由v和前一估算值X[i-1]通过下列公式计算:

X[i]=X[i-1]×(1.5-(v/2)×X[i-1]×X[i-1])开始运算时需要一个初始值X[0]。若v=a×2e,初始值可以近似为:X[0]=1.0×2-e/2。例5.32是在TMS320C3x上实现此方法的例子,这里迭代需要进行5次。同样地,迭代次数的选择取决于所要求的精度。例5.32浮点数的平方根计算。

LDFv,R0

CALLSQRT;R0存放v和最后的结果SQRT(v)

.globalSQRT

SQRT: LDFR0,R3;保存v

RETSLE ;如果是非正数,则返回

PUSHFR0POPR1ASH-24,R1 ;取v的指数放入R1中ADDI1,R1ASH–1,R1 ;R1=e/2NEGIR1ASH24,R1PUSHR1POPFR1 ;R1=x[0]=1.0*2**(-e/2)MPYF0.5,R0 ;R0=v/2MPYFR1,R1,R2 ;R2=x[0]*x[0]MPYFR0,R2 ;R2=(v/2)*x[0]*x[0]SUBRF1.5,R2 ;R2=1.5-(v/2)*x[0]*x[0]MPYFR2,R1 ;R1=x[1]=x[0]*(1.5-(v/2)*x[0]*x[0])RNDR1MPYFR1,R1,R2 ;R2=x[1]*x[1]MPYFR0,R2 ;R2=(v/2)*x[1]*x[1]SUBRF1.5,R2 ;R2=1.5-(v/2)*x[1]*x[1]MPYFR2,R1 ;R1=x[2]=x[1]*(1.5-(v/2)*x[1]*x[1])RNDR1MPYFR1,R1,R2 ;R2=x[2]*x[2]MPYFR0,R2 ;R2=(v/2)*x[2]*x[2]SUBRF1.5,R2 ;R2=1.5-(v/2)*x[2]*x[2]MPYFR2,R1 ;R1=x[3]=x[2]*(1.5-(v/2)*x[2]*x[2])RNDR1MPYFR1,R1,R2 ;R2=x[3]*x[3]MPYFR0,R2 ;R2=(v/2)*x[3]*x[3]SUBRF1.5,R2 ;R2=1.5-(v/2)*x[3]*x[3]MPYFR2,R1 ;R1=x[4]=x[3]*(1.5-(v/2)*x[3]*x[3])RNDR1MPYFR1,R1,R2 ;R2=x[4]*x[4]MPYFR0,R2 ;R2=(v/2)*x[4]*x[4]SUBRF1.5,R2 ;R2=1.5-(v/2)*x[4]*x[4]MPYFR2,R1 ;R1=x[5]=x[4]*(1.5-(v/2)*x[4]*x[4])RNDR1,R0 ;R1中扩展精度浮点数转换为单精度浮点数, ;并放入R0MPYFR3,R0 ;得出RETS.end5.6.3扩展精度算法

TMS320C3x提供了32位精度整数算法和24位尾数精度的浮点算法。为提高浮点运算的精度,8个扩展精度寄存器R0~R7包含8位附加精度位。对于定点运算,因为没有和上述浮点算法相类似的扩展方法,所以本节将讨论如何运用处理器来实现定点双精度算法。实现本算法的技术就像普通算法那样,指令组中有ADDC(带进位位加法)和SUBB(带借位位减法)指令,可用进位位来实现扩展精度算法,进位位受ALU运算指令和循环移位指令影响,它也可通过对状态寄存器的相应位直接置值来管理。为了操作更合理,溢出方式应该复位(OVM=0),使累加器的结果不装入饱和溢出值。例5.33和例5.34是64位加法和64位减法的例子,第一个操作数存在寄存器R0(低位字)和R1(高位字)中,第二个操作数分别在R2和R3中,结果存在R0和R1中。例5.3364位加法。;R0存放数X的低位字;R1存放数X的高位字;R2存放数Y的低位字;R3存放数Y的高位字;R1R0存放结果

ADDIR2,R0

ADDCR3,R1例5.3464位减法。;R0存放数X的低位字;R1存放数X的高位字;R2存放数Y的低位字;R3存放数Y的高位字;R1R0存放结果

SUBIR2,R0

SUBBR3,R1当两个32位数相乘时,得到64位乘积,乘法的方法是将被乘数X和乘数Y的32位分别分成两部分(X1,X0)和(X3,X2),每部分16位。运算是对无符号数进行的,乘积对符号位调准。例5.35是32位乘32位的例子。例5.3532位乘32位乘法。.globalEXTMPYEXTMPY:XOR3R0,R1,AR0 ;存储符号ABSIR0 ;取X的绝对值ABSIR1 ;取Y的绝对值LDI16,AR1LSH3AR1,R0,R2 ;R2=X1(X的高16位)AND0FFFFH,R0 ;R0=X0(X的低16位)LSH3AR1,R1,R3 ;R3=Y1(Y的高16位)AND0FFFFH,R1 ;R1=Y0(Y的低16位)MPYI3R0,R1,R4 ;X0*Y0=P1MPYIR3,R0 ;X0*Y1=P2MPYIR2,R1 ;X1*Y0=P3ADDIR0,R1 ;P2+P3MPYIR2,R3 ;X1*Y1=P4LDIR1,R2LSH16,R2 ;P2+P3的低16位CMPI0,AR0 ;核对乘积的符号BGEDDONE ;如果>0,乘法完成延时LSH–16,R1 ;P2+P3的高16位ADDI3R4,R2,R0 ;W0=R0(乘积的低字节)ADDC3R1,R3,R1 ;W1=R1(乘积的低字节)NOTR0ADDI1,R0NOTR1ADDC0,R1DONERETS.end5.7典型的信号处理算法程序设计

5.7.1压扩在远程通信领域中,主要关心的问题之一是在一定的通道带宽下保持高的语音质量,这可以通过对语音采样的对数量化来实现,一个8位的对数量化器产生的语音质量相当于13位均匀量化器产生的语音质量。对数量化用COMPAND(COMpress/exPANDing的缩写,合起来意为压扩)来实现,现在已经建立了压扩的两个国际标准:µ律(用于美国和日本)和A律(用于欧洲)。对数量化器是用符号的幅度形式表示的,在发送时沿通信通道传送。在做了必要的处理后,这些数据应扩展为14位(µ律)或13位(A律)的线性格式。当数据在数字信号处理器中接收后,这些操作开始执行。数据处理后,被压缩回8位格式并在通道中连续传送。例5.36和例5.37是µ律压缩和扩展程序(即线性到µ律和µ律到线性的转换),例5.38和例5.39是A律压缩和扩展程序。对于扩展可用查表法,查表法折中了存储空间和执行速度的矛盾。由于压缩后的数据是8位字长,因此256项的数据表足以包含扩展数据。比如压缩数据存储在AR0中,下面两条指令将扩展数据放在寄存器R0中:

ADDI@TABL,AR0;@TABL是表基地址

LDI*AR0,R0 ;扩展数据放在R0中例5.36µ律压缩。

R0 ;存放被转换的数据和最后结果

.globalMUCMPR

MUCMPR:LDIR0,R1;保存被压缩数据的符号

ABSIR0,R0

CMPI1FDEh,R0;判断R0>0x1FDE?

LDIGT1FDEh,R0;若上述判断成立,则保存这个结果

ADDI33,R0 ;加偏置量

FLOATR0 ;归一化

MPYF0.03125,R0;调整区段号2**(-5)LSH1,R0 ;左移一位PUSHFR0POPR0 ;R0以整型弹出LSH-20,R0 ;R0右移LDI0,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论