59
1 程程程程 (一) 1. 程程程程程size .set 100 ; 程程程程 size=100 stack: .usect“STK”, size ; 程 stac k 程程 100 程程程 STM #stack+size,SP ;SP 程程程程 程程程程程 0000H FFFFH stac k 程程程程程 SP 程程程程 程程程程 . . . . . . STK 程程程程 : 程程程程 程 SP 程 1 程程程程 :SP 程程 1 程程程 程程

程序设计 (一) 1. 堆栈初始化: size .set 100 ; 定义符号 size=100

  • Upload
    nonnie

  • View
    74

  • Download
    0

Embed Size (px)

DESCRIPTION

程序设计 (一) 1. 堆栈初始化: size .set 100 ; 定义符号 size=100 stack: .usect “ STK ” , size ; 为 stack 保留 100 个单元 STM #stack+size,SP ;SP 指向栈底. 数据存储器. 0000H. 压入 操作 : SP 先减 1 再压入数据. stack. 可用栈区. 最后用单元. SP. STK. 以用栈区. 弹出 操作 : 数据弹出 再 SP 加 1. FFFFH. - PowerPoint PPT Presentation

Citation preview

Page 1: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

1

程序设计 (一)1. 堆栈初始化:size .set 100 ; 定义符号 size=100stack: .usect“STK”, size ; 为 stack 保留 100 个单元

STM #stack+size,SP ;SP 指向栈底

数据存储器0000H

FFFFH

stack

最后用单元SP

可用栈区

以用栈区

......

STK

弹出操作 : 数据弹出 再 SP 加 1

压入操作 :SP 先减 1

再压入数据

Page 2: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

2

传送速度比加载和存储指令要快;传送数据不需要通过累加器;可以寻址程序存储器;与 RPT 指令相结合(重复时,这些指令都变成单周期指令),可以实现数据块传送。

2 . 数据块传送

特点

Page 3: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

3

( 1 )数据存储器←→数据存储器 这类指令有:MVDK Smem,dmad 指令的字数 / 执行周期 2/2MVKD dmad,Smem   ; Smem=dmad        2/2MVDD Xmem,Ymem   ; Ymem=Xmem 1/1( 2 )程序存储器←→数据存储器 这类指令有:MVPD pmad,Smem ; Smem=pmad 2/3MVDP Smem,pmad ; pmad=Smem 2/4

pmad 为 16 位立即数程序存储器地址;dmad 为 16 位立即数数据存储器地址;Smem 为数据存储器地址;Xmem 、 Ymem 为双操作数数据存储器地址, Xmem 从 DB 数据总线上读出。 Ymem 从 CB 数据总线上读出。

Page 4: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

4

( 3 )数据存储器←→ MMR 这类指令有:

MVDM dmad,MMR ;指令的字数 / 执行周期 2/2

MVMD MMR,dmad ; dmad=MMR 2/2

MVMM mmrx,mmry ; mmry=mmrx 1/1

( 4 )程序存储器( Acc )←→数据存储器 包括:

READA Smem ; Smem=prog(A) 1/5

WRITA Smem ; prog(A)= Smem 1/5

mmrx,mmry 为 AR0 ~ AR7 或 SP ; MMR 为任何一个存储器映象寄存器;

Page 5: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

5

例 将数组 x[5] 初始化为 {1,2,3,4,5} 。    .data ;定义初始化数据段起始地址TBL: .word 1,2,3,4,5 ;为标号地址 TBL         ;开始的 5 个单元赋初值 .sect “.vectors” ;定义自定义段,并获           ;得该段起始地址 B START ;无条件转移到标号为 START 的地址 .bss x,5 ;为数组 x 分配 5 个存储单元 .text ;定义代码段起始地址START:STM #x,AR5 ;将 x 的首地址存入 AR5 RPT #4 ;设置重复执行 5 次下条指令 MVPD TBL,*AR5+ ;将 TBL 开始的 5 个值传给 x

( 1 )程序存储器→数据存储器

Page 6: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

6

数据存储器

X:

……

.bss x,5

程序存储器

TBL: 12345

……

Page 7: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

7

例 将数据存储器中的数组 x[10] 复制到数组 y[10] 。 .title “cjy1.asm” ;为汇编源程序取名 .mmregs ;定义存储器映象寄存器STACK .usect “STACK”,30H ;设置堆栈 .bss x,10 ;为数组 x 分配 10 个存储单元 .bss y,10 ;为数组 y 分配 10 个存储单元 .datatable:.word 1,2,3,4,5,6,7,8,9,10 .def start ;定义标号 start .text

( 2 )数据存储器→数据存储器

Page 8: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

8

start:STM #0,SWWSR ;复位 SWWSR STM #STACK+30H,SP ;初始化堆指针 STM #x,AR1 ;将目的地首地址赋给 AR1 RPT #9 ;设定重复传送的次数为 10 次 MVPD table,*AR1+ ;程序存储器传送到数 ;据存储器 STM #x,AR2 ;将 x 的首地址存入 AR2 STM #y,AR3 ;将 y 的首地址存入 AR3 RPT #9 ;设置重复执行 10 次下条指令 MVDD *AR2+,*AR3+ ;将地址 x 开始的 10 个值 ;复制到地址 y 开始的 10 个单元end: B end .end

Page 9: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

9

用间接寻址方式获得操作数,且辅助寄存器只用 AR2~ AR5;占用程序空间小;运行速度快。

3 .双操作数乘法

特点

例 编制求解 的程序。利用双操作数指令可以节省机器周期。迭代次数越多,节

省的机器周期数也越多。本例中,在每次循环中,双操作数指令都比单操作数指令少用一个周期,节省的总机器周期数=1T*N (迭代次数) =NT 。

20

1iii xay

Page 10: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

10

单操作数指令方案 双操作数指令方案 LD #0,B LD #0,B STM #a,AR2 STM #a,AR2 STM #x,AR3 STM #x,AR3  STM #19,BRC    STM #19,BRC RPTB done-1 RPTB done-1 LD   *AR2+,TT;1T MPY *AR2+,*AR3+,A ;1T MPY   *AR3+,AA;1T   ADD A,B ; 1T ADD A,B   ;1T done: STH B,@y done: STH B,@y STL B,@y+1 STL B,@y+1     

Page 11: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

11

(1)并行运算指同时利用 D总线和 E总线。其中,D总线用来执行加载或算术运算, E总线用来存放先前的结果。

(2) 并行指令都是单字单周期指令。(3) 并行运算时所存储的是前面的运算结果,存储

之后再进行加载或算术运算。(4) 并行指令都工作在累加器的高位。(5) 大多数并行运算指令都受累加器移位方式 AS

M 位影响。

4 .并行运算

特点

Page 12: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

12

表 1 并行指令举例指 令 指 令 举 例 操作说明

并行加载和乘法指令 LD‖MAC[R]LD‖MAS[R]

LD Xmem,dst‖MAC[R] Ymem[,dst]

dst=Xmem<<16dst2=dst2+T*Ymem

并行加载和存储指令 ST‖LDST src, Yme‖LD Xmem, dst

Ymem=src>> ( 16-ASM )dst=Xmem<<16

并行存储和乘法指令ST‖MAYST‖MAC[R]ST‖MAS[R]

ST src, Ymem‖MAC[R] Xmem, dst

Ymem=src>> ( 16-ASM )dst=dst+T*Xmem

并行存储和加 / 减法指令 ST‖ADDST‖SUB

ST src, Ymem‖ADD Xmem, dst

Ymem=src>> ( 16-ASM )dst=dst+Xmem

Page 13: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

13

例 编写计算 z=x+y 和 f=d+e 的程序段。在此程序段中用到了并行存储 / 加载指令 ; 即在同一机器周期内利用 E 总线存储和 D 总线加载。 数据存储器分配如图所示。 .title “cjy3.asm” .mmregsSTACK .usect “STACK”,10H .bss x,3 ;为第一组变量 ;分配 3 个存储单元 .bss d,3 ;为第二组变量 ;分配 3 个存储单元 .def start .datatable: .word 0123H,1027H,0,1020H,0345H,0

Page 14: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

14

.text start:STM #0,SWWSR STM #STACK+10H,SP STM #x,AR1 RPT #5 MVPD table,*AR1+ STM #x,AR5 ;将第一组变量的首地址传给 AR5 STM #d,AR2 ;将第二组变量的首地址传给 AR2 LD #0,ASM ;设置 ASM=0 LD *AR5+,16,A ;将 x 的值左移 16 位放入 A 的高端字 ADD *AR5+,16,A ;将 y 值左移 16 位与 A 的高端字 x 相加 ST A,*AR5 ;将 A 中的和值右移 16 位存入 z中 ‖LD *AR2+,B ;将 d 的值左移 16 位放入 B 的高端字 ADD *AR2+,16,B ;将 e 值左移 16 位与 B 的高端字 d 相加 STH B,*AR2 ;将 B 的高端字中的和值存入 f 中end: B end .end

Page 15: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

15

9. 将数据存储器中的数组 x[20] 复制到数组 y[20]

.bss x,20

.bss y,20

STM #x,AR2

STM #y,AR3

RPT #19 ; 复制 20 个数

MVDD *AR2+,*AR3+

数据存储器

X:

……

x,20

y,20

Page 16: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

16

练习:将数据存储器中的数组 x[20] 和数组 y[20] 的内容对调 .

Page 17: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

17

5. 将数据存储器中的数组 x[20] 和数组 y[20] 的内容对调 .

.bss x,20

.bss y,20

.bss z,20

STM #x,AR2

STM #z,AR3

RPT #19 ; 下一条指令重复 19+1 次 , x z

MVDD *AR2+,*AR3+

Page 18: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

18

STM #y,AR2

STM #x,AR3

RPT #19

MVDD   *AR2+,*AR3+

STM #z,AR2

STM #y,AR3

RPT #19

MVDD   *AR2+,*AR3+

X:

Y:

Z:

1

2

3

数据存储器

x

y

z

Page 19: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

19

又解:  .bss x,20  .bss y,20  .bss z,20 …   STM #x, AR2  STM #z, AR3  RPT #19  MVDD *AR2+,*AR3+  STM #x, AR3  RPT #19 MVDD *AR2+,*AR3+ RPT #19 MVDD *AR2+,*AR3+ …

;AR2 已指向 y

;AR2 已指向 z , AR3 已指向 y

Page 20: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

20

6. 在4项乘积 aixi(i=1,2,3,4) 中找出最大值 并存放在累加器 A 中

STM #a,AR1

STM #x,AR2

STM #2,AR3

LD * AR1+,T

MPY * AR2+,A ; A=(AR2)*TLoop:LD * AR1+,T

MPY * AR2+,B ; B=(AR2)*T

MAX   A ; 累加器 A 和 B 比较 , 大的存在 A中

BANZ loop, * AR3- ;如果 AR3 非0则跳转

MAX dst ;if (A>B)

;Then (A) dst

; 0 C

;Else (B) dst

; 1 C

Page 21: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

21

12. 乘法累加运算 *******************************************************

* example.asm y=a1*x1+a2*x2+a3*x3+a4*x4

*******************************************************

.title “example.asm”   ; 定义源程序名称 .mmregs      ; 定义存储器映像寄存器STACK .usect “STACK”,10h    ; 设置堆栈空间

.bss a,4      ; 为变量 ai 保留 4 个单元 .bss x,4      ; 为变量 xi 保留 4 个单元 .bss y,1      ; 为变量 y 保留 1 个单元 .def start   ; 定义外部可引用的符号 start

Page 22: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

22

.data    ; 其后为已初始化数据段Table: .word 1,2,3,4    ; 4 个字常数 a1,a2,a3,a4

.word 8,6,4,2    ;x1,x2,x3,x4

  .text    ; 其后为代码段start: STM #0,SWWSR   ; 设置等待状态寄存器

STM #STACK+10h,SP ; 堆栈指针指向栈底

STM #a,AR1 ;AR1 指向 a1

RPT #7 ; 移动 8 个数据 MVPD table,*AR1+ ; 从程序存储器到数据存储器 CALL SUM ; 调用 SUM 子程序

end: B end ; 循环等待

Page 23: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

23

SUM: STM #a,AR3 ; 计算乘累加 .AR3 指向 a1

STM #x,AR4 ; AR4 指向 x1

RPTZ A,#3 ; 作 4 次乘累加运算 MAC *AR3+,*AR4+,A ;A=(AR3)*(AR4)+ A

;AR3=AR3+1

;AR4=AR4+1

STL A,*AR4 ;y=A(bit15~bit0)

RET ;子程序结束 .end ; 汇编源程序结束

Page 24: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

24

1 . FIR 滤波器基本概念

1. FIR滤波器没有反馈回路,因此它是无条件稳 定系统,其单位冲激响应h(n) 是一个有限长序列。

2. FIR滤波算法实际上是一种乘法累加运算。对采样值 (输入样本 )x(n)经延时 Z-1, 再作乘累加;采用 N 次的采样值计算称为 N阶的滤波器。

要点

程序设计(二)用 DSP 实现 FIR滤波器

Page 25: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

25tntn-1 tn+1

tn+2

t

取得样本x(n)

计算y(n)

取得样本x(n+1)

计算 y(n+1)

计算y(n-1)

取得样本 x(n-1)

Page 26: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

26

C54x片内没有 I/O 资源, CPU通过外部译码可以寻址 64K 的 I/O单元。

有两条实现输入和输出的指令:PORTR PA,Smem ;将为 PA 的端口内容送 ;数据存储器 SmemPORTW Smem,PA ;将地址为 Smem 的数据 ;存储器内容送端口 PA

数据的输入 /输出

Page 27: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

27

2. FIR 滤波器中 z-1 的实现

对于 N级的 FIR滤波器,在数据存储器中开辟一个称之为滑窗的 N 个单元的缓冲区,存放最新的 N 个输入样本;计算从最老的样本开始,每读一个样本后,将此样本向下移位,读完最后一个样本后,输入最新样本至缓冲区的顶部。 用线性缓冲区实现 z-1 的优点是,新老数据在存储器中存放的位置直接明了。

特点

(1)用线性缓冲区法实现 z-1

Page 28: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

28N=6 的线性缓冲区存储器图

5

0ii )in(xa)n(y

从底部开始计算

最新样本

Page 29: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

29

使用存储器延时指令 DELAY ,可以将数据存储单元中的内容向较高地址的下一单元传送。

实现 z-1 的运算指令为: DELAY Smem ;(Smem)→Seme+1 ,即数据存储 ; 器单元的内容送下一高地址单元如 DELAY *AR2 ;AR2 指向源地址 , 即将 AR2 所指单元内容 ; 复制到下一高地址单元中

存储器的延时操作

延时指令与其它指令的结合LT+DELAY → LTD Smem ; 单数据存储器的值装入 ;T 寄存器并送下一单元延时MAC+DELAY→ MACD Smem,pmad,src ; 操作数与程序存储器值相乘 ,

; 后累加并送下一单元延时

Page 30: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

30

在数据存储器中开辟一个称之为滑窗的 N 个单元的缓冲区,滑窗中存放最新的 N 个输入样本;每次输入新样本时,以新样本改写滑窗中的最老的数据,而滑窗中的其它数据不作移动;利用片内 BK (循环缓冲区长度)寄存器对滑窗进行间接寻址,循环缓冲区地址首尾相邻。利用循环缓冲区实现 Z-1的优点是不需要移动数据,不存在一个机器周期中要求能一次读和一次写的数据存储器,因而可以将循环缓冲区定位在数据存储器的任何位置(线性缓冲区要求定位在 DARAM)。

特点

( 2)用循环缓冲区法实现 z-1

Page 31: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

31N=6 的循环缓冲区存储器图

5

0ii )in(xa)n(y

从顶部开始计算

最新样本

Page 32: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

32

3 . FIR 滤波器的实现方法

例 编写 N=5 , y(n)=a0*x(n)+a1*x(n-1)+a2*x(n-2)+a3*x(n-3)+a4*x(n-4) 的计算程序。先将系数 a0 ~ a4 存放到数据存储器中,然后设置线性缓冲区,用以存放输入和输出数据。

(1)用线性缓冲区和直接寻址方法实现 FIR

线性缓冲区安排

Page 33: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

33

.title “FIR1.ASM” ;定义源程序名 .mmregs ;定义存储器映象寄存器 .def start ;定义语句标号 start .bss y,1 ;为结果 y预留 1 个单元的空间XN .usect “XN”,1 ;在自定义的未初始化段“ XN”XNM1 .usect “XN”,1 ;中保留 5 个单元的空间XNM2 .usect “XN”,1XNM3 .usect “XN”,1 XNM4 .usect “XN”,1A0 .usect “A0”,1 ;在自定义的未初始化段“ A0”A1 .usect “A0”,1 ;中保留 5 个单元的空间A2 .usect “A0”,1A3 .usect “A0”,1A4 .usect “A0”,1PA0 .set 0 ;定义 PA0 为输出端口PA1 .set 1 ;定义 PA1 为输入端口

Page 34: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

34

.datatable: .word 1*32768/10 ;假定程序空间有五个参数 a0=0.1=0ccch .word -3*32768/10 ;a1=-0.3 (16 位 2 的补码 ) .word 5*32768/10 ;a2=0.5 .word -3*32768/10 ;a3=-0.3 .word 1*32768/10 ;a4=0.1 .textstart: .SSBX FRCT ;设置进行小数相乘 STM #A0,AR1 ;将数据空间用于放参数的首地址送 AR1

RPT #4 ;重复下条指令 5 次传送 MVPD table,*AR1+ ;传送程序空间的参数到数据空间 LD #XN,DP ;设置数据存储器页指针的起始位置 PORTR PA1,@XN ;从数据输入端口 I/O输入最新数据 x ( n )FIR1: LD @XNM4,T ; x(n-4)→T

Page 35: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

35

MPY @A4,A ; a4*x(n-4)→A

LTD @XNM3 ; x(n-3)→T,x(n-3)→x(n-4)MAC @A3,A ; A+a3*x(n-3)→A

LTD @XNM2 ; x(n-2)→T,x(n-2)→x(n-3)MAC @A2,A ; A+a2*x(n-2)→A

LTD @XNM1 ; x(n-1)→T,x(n-1)→x(n-2)MAC @A1,A ; A+a1*x(n-1)→A

LTD @XN ; x(n)→T,x(n)→x(n-1)MAC @A0,A ; A+a0*x(n)→A

STH A,@y ;保存 y(n) 的高字节PORTW @y,PA0 ;输出 y(n)BD FIR1 ;执行完下条指令后循环PORTR PA1,@XN ;输入 x(n).end

Page 36: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

36

vectors.objfir1.obj-o fir1.out-m fir1.map-e startMEMORY { PAGE 0 : EPROM: org=01OOOH len=01000H VECS: org=03F80H len=00080H PAGE 1 : SPRAM: org=00060H len=00020H DARAM: org=00080H len=01380H }SECTIONS { .vectors:> VECS PAGE 0 .text:> EPROM PAGE 0 .data:> EPROM PAGE 0 .bss:> SPRAM PAGE 1 .XN:> DARAM align(8){ } PAGE 1 .A0:> DARAM align(8){ } PAGE 1 }

Page 37: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

37

(2)用线性缓冲区和间接寻址方法实现 FIR例 编写 y(n)=a0*x(n)+ a1*x(n-1)+ a2*x(n-2)+ a3*x(n-3)+ a4

*x(n-4) 的计算程序,其中 N=5 。

将系数 a0 ~ a4 存放在数据存储器中,并设置线性缓冲区存放输入数据。利用 AR1 和 AR2 分别作为间接寻址线性缓冲区和系数区的辅助寄存器。

Page 38: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

38

.title “FIR2.ASM” ;定义源程序名 .mmregs ;定义存储器映象寄存器 .def start ;定义语句标号 start .bss y,1 ;为结果 y预留 1 个单元的空间x .usect “x”,5 ;在自定义的未初始化段“ x” 中保留 5 个单元的空间a .usect “a”,5 ;在自定义的未初始化段“ a” 中保留 5 个单元的空间PA0 .set 0 ;定义 PA0 为输出端口PA1 .set 1 ;定义 PA1 为输入端口 .datatable: .word 2*32768/10 ;假定程序空间有五个参数 .word -3*32768/10 .word 4*32768/10 .word -3*32768/10 .word 2*32768/10

Page 39: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

39

.textstart: STM #a,AR2 ;将数据空间用于放参数 ;的首地址送 AR2 RPT #4 ;重复下条指令 5 次传送 MVPD table,*AR2+ ;传送程序空间的参数到数据空间 STM #x+4,AR1 ; AR1 指向 x(n-4) STM #a+4,AR2 ; AR2 指向 a4

STM #4,AR0 ;指针复位值 4→AR0 SSBX FRCT ;小数相乘 LD #x,DP ;设置数据存储器页指针 ;的起始位置 PORTR PA1,@x ;从端口 PA1输入最新值 x(n)

Page 40: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

40

FIR2: LD *AR1-,T ; x(n-4)→T MPY *AR2-,A ; a4*x(n-4)→A

LTD *AR1- ; x(n-3)→T,x(n-3)→x(n-4) MAC *AR2-,A ; A+a3*x(n-3)→A

LTD *AR1- ; x(n-2)→T,x(n-2)→x(n-3) MAC *AR2-,A ; A+a2*x(n-2)→A

LTD *AR1- ; x(n-1)→T,x(n-1)→x(n-2) MAC *AR2-,A ; A+a1*x(n-1)→A

LTD *AR1 ; x(n)→T, x(n)→x(n-1) MAC *AR2+0,A ; A+a0*x(n)→A ,AR2 复原,指向 a4

STH A,@y ;保存运算结果的高位字到 y ( n ) PORTW @y ,PA0 ;将结果 y(n)输出到端口 PA0 BD FIR2 ;执行完下条指令后,从 FIR2 开始循环 PORTR PA1,*AR1+0 ;输入新值 x(n+1),AR1 复原指向 x+4 .end

Page 41: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

41

(3) 用线性缓冲区和带移位双操 作数寻址方法实现 FIR

例 5-27 编写 y ( n ) =a0*x ( n ) + a1*x ( n-1 ) + a2*x ( n-2 )+ a3*x ( n-3 ) + a4*x ( n-4 )的计算程序,其中 N=5 。

与前面的编程不同,本例中,系数 a0~ a4存放在程序存储器中,输入数据存放在数据存储器的线性缓冲区中。乘法累加利用MACD指令,该指令完成数据存储器单元与程序存储器单元相乘,并累加、移位的功能。

Page 42: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

42

.title “FIR3.ASM” ;定义源程序名 .mmregs ;定义存储器映象寄存器 .def start ;定义语句标号 start .bss y,1 ;为结果 y预留 1 个单元的空间x .usect “x”,6 ;在自定义的未初始化 ;段“ x” 中保留 6 个单元 PA0 .set 0 ;定义 PA0 为输出端口PA1 .set 1 ;定义 PA1 为输入端口 .dataCOEF: .word 1*32768/10 ;假定程序空间有五个参数 ,a4 .word -4*32768/10 ; a3 .word 3*32768/10 ; a2 .word -4*32768/10 ; a1 .word 1*32768/10 ; a0

Page 43: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

43

.textstart : SSBX FRCT ;小数乘法 STM #x+5,AR1 ; AR1 指向 x(n-4) STM #4,AR0 ;设置 AR1 复位值 LD #x+1,DP ;设置数据存储器页指针的起始位置 PORTR PA1,@x+1 ;输入最新值 x ( n )FIR3 : RPTZ A,#4 ;累加器 A清 0, 设置重复下条指令5 次 MACD *AR1-,COEF,A ;第一次执行: x(n-4)→T,

; A= x(n-4)*a4 +A

; (PAR)+1→PAR, x(n-4)→x(n-5) STH A,*AR1 ;暂存结果到 y(n) PORTW *AR1+,PA0 ;输出 y(n) 到 PA0 , AR1 指向 x(n) BD FIR3 ;执行下条指令后循环 PORTR PA1,*AR1+0 ;输入新数据到 x(n),AR1 指向 x(n-4)

Page 44: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

44

(4) 用循环缓冲区和双操作 数寻址方法实现 FIR

例 5-28 编写 y ( n ) =a0*x ( n ) + a1*x ( n-1 ) + a2*x ( n-2 )+ a3*x ( n-3 ) + a4*x ( n-4 )的计算程序,其中 N=5 。

本例中,存放 a0~ a4的系数表以及存放数据的循环缓冲区均设在 DARAM 中。

Page 45: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

45

.title “FIR4.ASM” ;给汇编程序取名 .mmregs ;定义存储器映象寄存器 .def start ;定义标号 start 的起始位置 .bss y,1 ;为未初始化变量 y保留空间xn .usect “xn”,5 ;自定义 5 个单元空间的数据段 xna0 .usect “a0”,5 ;自定义 5 个单元空间的数据段 a0PA0 .set 0 ;设置数据输出端口 I/O , PA0=0PA1 .set 1 ;设置数据输入端口 I/O , PA1=1 .datatable: .word 1*32768/10 ; a0=0.1=0x0CCC

.word 2*32768/10 ; a1=0.2=0x1999

.word 3*32768/10 ; a2=0.3=0x2666

.word 4*32768/10 ; a3=0.4=0x3333

.word 5*32768/10 ; a4=0.5=0x4000 .text

Page 46: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

46

start: SSBX FRCT ;小数乘法 STM #a0,AR1 ; AR1 指向 a0 RPT #4 ; 从程序存储器 table 开始的地址传送 MVPD table,*AR1+ ; 5 个系数至数据空间 a0 开始的数据段 STM #xn+4,AR3 ; AR3 指向 x(n-4) STM #a0+4,AR4 ; AR4 指向 a4 STM #5,BK ;设循环缓冲区长度 BK=5 STM #-1,AR0 ; AR0=-1, 双操作数减量 LD #xn,DP ;设置数据存储器页指针的起始位置 PORTR PA1,@xn ;输入新数据到 x(n)FIR4: RPTZ A,#4 ; A清 0, 重复执行下条指令 5 次 MAC *AR3+0%,*AR4+0%,A ;系数与输入数据双 ;操作数相乘并累加 STH A,@y ;保存结果的高字节到 y(n) PORTW @y,PA0 ;输出 y(n) 到端口 PA0 BD FIR4 ;执行完下条指令后循环 PORTR PA1,*AR3+0% ;从端口 PA1输入新数据到 xn +4 .end

Page 47: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

47

DSP 引导方式选择 在硬件产品和系统设计时,用户程序通常保存在片外非遗失的存储器中,程序运行一般在片内程序存储器。上电时将片外中的程序引导到片内程序存储器中,此过程为 BOOTLOADER 。

C54XX 系列 DSP 的片上 ROM 放有引导程序,

上电复位时,将用户程序从外部设备装入到 DSP

片内程序存储器,再启动用户程序运行。

1. 引导过程:

用片上引导程序,要将 MP/MC 引脚在上电复位时接为低电平。 VC5402 从片内 ROM 的 FF80H 处开始执行。

Page 48: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

48

FF80H 处是矢量表的起始,是一条跳转指令,跳转到片上 ROM 引导程序。引导程序在选择引导方式之前,先初始化 CPU 状态寄存器,包括全局禁止中断( INTM=1 ),内部 DARAM 和 SARAM 均映射到程序 / 数据存储器空间( OVLY=1 )

VC5402 的引导方式有多种: HPI 口、串行口、并行 I/O 口、外部并行存储器、串行 EEPROM 引导等。

Page 49: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

49

DSP 复位MP/MC=0

INT2=0 有效入口

跳到入口地址

INT3=0EEPROM串行引导 加载代码

Y

N

Y

N N

Y

Y

NHPI 引导

串行 EEPROM 引导

主机通过 HPI装入程序

通过 McBSP1 读入 EEPROM 程序

Page 50: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

50

从 I/O 空间 FFFFH读入源地址

从数据空间 FFFFH读入源地址

加载代码并行引导?

并行引导?

并行引导

Y

N

Y

N

引导表地址:

4000H~0FFFFH 放在 I/O 空间或数据空间的 0FFFFH 中,

DSP 通过外部总线读入引导表

Page 51: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

51

初始化串口 ,XF=0

McBSP1?

Y

McBSP0?

Y

BIO=0 ? Y

有效入口? Y

有效关键字? Y

有效关键字? Y

有效关键字? Y

跳到入口

加载代码

加载代码

加载代码

RESTART

RESTART

标准串口引导

IO 引导

HPI 引导 ( 二次监测 )

主机通过串口加载

主机通过 I/O 口加载

Page 52: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

52

2. 采用 EPROM 并口引导的引导表设计

扩展 8 位字宽的 EPROM, 占用 DSP 外部数据空间

8000H~0FFFFH (引导程序放在数据存储空间)。

引导方式: 8 位并行引导。

上电复位时 ,MP/MC=0, 启动片内 ROM 引导程序。

从数据空间 FFFFH 读出引导表地址,读引导表

引导程序将 EPROM 用户程序代码调入片内存储器后分支转移到目的地址,并执行用户程序代码。

Page 53: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

53

引导程序

FF80H

FFFFH

数据空间EPROM

目的地址

程序代码

EPROM 起始地址8000

8000H 8 位 BOOT 标识08AA

设置 SWWSR

1000H

1000

DSP

Page 54: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

54

引导表的内容EPROM 数据区地址 内容( Hex) 含义

8000 088 位 BOOT 标识( H )

8001 AA8 位 BOOT 标识( L )

8002 7F SWWSR ( H )8003 FF SWWSR ( L )8004 F8 BSCR(H)

8005 00 BSCR(L)

8006 00 程序入口地址 XPC(H)8007 00 程序入口地址 XPC(L)8008 10 程序入口地址 PC(H)8009 00 程序入口地址 PC(L)800A 20 程序长度 (H)800B 00 程序长度 (L)

Page 55: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

55

800C CODE0 程序代码 0(H)800D CODE1 程序代码 0(L)

… …

C00E CODEN-2 程序代码 N-1(H)C00F CODEN-1 程序代码 N-1(L)C010 00 结束标记C011 00 结束标记

… …

FFFE 80 EPROM 起始地址( H)FFFF 00 EPROM 起始地址 (L)

Page 56: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

56

OVLY=0 片内 RAM 只安排在数据存储空间DROM=0 片内 ROM 不安排到数据空间MP/MC=0 片内 ROM 安排到程序空间 数据存储器

存储映射寄存器0000H

005FH0060H007FH

暂时存储器 (RAM)

0080H

3FFFH

DARAM16K*16 位

4000H

EFFFHF000H

FEFFH

FF80HFFFFH

外部

外部

外部

外部

外部

外部

片内 ROM4K 字 *16 位

中断矢量 ( 片内 )

005FH0060H007FH0080H

3FFFH4000H

EFFFHF000H

FF7FH

FF80H

FFFFH

0000H

FF00HFF7FH 保留

第 0 页程序存储器

C5402 存储器配置图

Page 57: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

57

OVLY=0 片内 RAM 只安排在数据存储空间DROM=0 片内 ROM 不安排到数据空间MP/MC=1 片内 ROM 不安排到程序空间

0000H

005FH0060H007FH0080H

3FFFH4000H

EFFFHF000H

FEFFH

FF80HFFFFH

外部

外部

外部

中断矢量 ( 外部 )

FF00HFF7FH 外部

第 0 页程序存储器

外部

Page 58: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

58

OVLY=1 片内 RAM 安排到程序 / 数据空间DROM=0 片内 ROM 不安排到数据空间MP/MC=0 片内 ROM 安排到程序空间 数据存储器

存储映射寄存器0000H

005FH0060H007FH

暂时存储器 (RAM)

0080H

3FFFH

DARAM16K*16 位

4000H

EFFFHF000H

FEFFH

FF80HFFFFH

外部

外部

外部

外部

外部

片内 ROM4K 字 *16 位

中断矢量 ( 片内 )

005FH0060H007FH0080H

3FFFH4000H

EFFFHF000H

FF7FH

FF80H

FFFFH

0000H

FF00HFF7FH 保留

第 0 页程序存储器

DARAM16K*16 位

Page 59: 程序设计  (一) 1. 堆栈初始化: size  .set   100                ; 定义符号 size=100

59

OVLY=1 片内 RAM 安排到程序 / 数据空间DROM=1 部分片内 ROM 安排到数据空间MP/MC=0 片内 ROM 安排到程序空间 数据存储器

存储映射寄存器0000H

005FH0060H007FH

暂时存储器 (RAM)

0080H

3FFFH

DARAM16K*16 位

4000H

EFFFHF000H

FEFFH

FF80HFFFFH

外部

片内 ROM4K 字 *16 位

外部

外部

外部

片内 ROM4K 字 *16 位

中断矢量 ( 片内 )

005FH0060H007FH0080H

3FFFH4000H

EFFFHF000H

FEFFH

FF00H

FFFFH

0000H

FF00HFF7FH 保留

第 0 页程序存储器

DARAM16K*16 位