实验目的:
了解DMA通信基本原理,掌握内存与SDRAM间一维DMA通信方式、二维DMA通信方式以及相关控制方法。学习数字滤波器设计方法,掌握其调试步骤,使学生加深对IIR的理解,进一步提高对数字信号处理理论的认识。
实验任务:
实验1:内存与SDRAM间的一维DMA通信实验
实验2:内存与SDRAM间的二维DMA通信实验
实验3:无限脉冲响应数字滤波器(IIR)的设计实验
实验内容:
实验1内存与SDRAM间的一维DMA通信实验
实验原理
DMA是一种不需要处理器内核干预的数据传输机制,作为一种后台任务执行,即进行DMA传输时,处理器可以处理其它任务。如果使能了DMA中断,那么当数据传输结束后会产生中断信号,表示DMA传输已经完成。
DMA传输方式包括:一维DMA、二维DMA、链式DMA、AutoDMA等,本次实验使用一维DMA方式,即传输存储器中一段连续的数据(地址是相邻接的)。
若要利用DMA传输数据,首先应配置DMA传输控制块(TCB)寄存器。DMA传输的数据具有方向性,即从发送端(源)到接受端(目的),若为外部存储器DMA传输,则需要设置两个TCB参数,一个源TCB,用于描述源数据的地址、大小和每次传输数据的长度等;还有一个目的TCB,用于描述数据传入的目标地址、数据大小及每次传输数据的长度等。若要使能DMA中断,也需要在TCB中设置相应位。若使用链路或AutoDMA通道则只需一个目的TCB。设置好TCB寄存器后,DMA传输自动开始。
TS201S一共14个DMA通道,4个通道(03)专用于外部存储器设备,8个通道(411)用于链路口,2个通道(12~13)用于自动DMA操作。本次实验使用DMA0通道实现内存与外部存储器SDRAM间的一维DMA通信。
相关的寄存器:
1〉 TCB寄存器
TCB寄存器是一个128位的四字组寄存器,由DI、DX、DY和DP寄存器组成:
a) DI是DMA索引寄存器,包括了将要发送或者接收的数据的源地址或者目的地址,既可以指向内部存储器又可以指向外部存储器,也可指向链路口
b) DX包含了一个16位(高)的计数值和一个16位的修改量,若使能了二维DMA则该寄存器保存的只是X方向的计数值和修改量
c) DY与DX结合一起使用,保存了Y方向上的16位计数值和16位修改量。如果只进行一维DMA传输,就不需要设置该寄存器。
d) DP寄存器包括了DMA所有控制信息,分为两个主要段
DP寄存器各位功能说明:
2〉中断屏蔽寄存器(IMASK)
IMASK是一个64位寄存器,由IMASKH和IMASKL组成,当IMASK中某位被设置成1的时,那么将响应这个位所对应的中断。
DMA0中断对应在IMASKL中的第14位,所以我们要取消对DMA0中断的屏蔽,使能DMA0中断,可以通过如下指令实现:
xr0=0x4000;; /*0x4000= B 0100 0000 0000 0000 */
IMASKL=xr0;;
xr0=0;;
IMASKH=0
也可以直接使用如下指令实现,原理是一样的,下面的方法更为直观一些。
xr0=INT_DMA0;; /* INT_DMA0在头文件中的定义的值为0x4000*/
IMASKL=xr0;;
实验步骤:
1)启动VisualDSP++,新建工程命名为”test2_1”,路径选择为”D:\DSP\”,并将源代码文件夹下默认生成的test2_1.c文件移除;
2)新建空白文件(选择菜单FileNewFile),输入参考源代码,保存为DMA_1.asm,并将其添加到工程中;
3)分析、理解源程序,并编译文件纠错;
4)建立链接文件(选择菜单ToolsExpert LinkerCreate LDF)
4)编译整个工程,若出现错误“The following symbols referenced in processor ‘p0’ could not be resolved: ‘main [_main]’ referenced from ‘ts_hdr_TS201.doj’”则说明声明的程序段/数据段(变量)所存放到了不能被执行的位置,导致该程序段/数据段(变量)没有被分配到相应的存储空间。处理方式:打开生成的LDF链接文件,在打开的Expert Linker窗口中将红叉项下的DMA1.obj添加(用鼠标拖拽)到MSSD0存储区(由于TS201S将外部存储器SDRAM地址映射到了0x4000 0000到0x7FFF FFFF之间的四个部分:MSSD0~3,所以我们将DMA1.obj添加至其中之一即可,由于开发板上SDRAM是映射在MSSD0,为方便以后实验,直接添加至MSSD0即可)。
5)重新编译工程,为方便观察存储器内相应地址其内容变化,在__Done处设置断点,同时打开两个存储器观察窗口(选择菜单Memory->TigerSHARC Memory)分别输入tx_data和rx_data。
6)运行(RUN)工程,程序自动运行至_Done后停止,观察tx_data内数据值,然后单步运行程序(按F11键),观察rx_data内数据变化。
实验结果:
要求:
1〉按照实验步骤完成实验;
2〉修改程序,DMA每次传输一个字(32位),验证结果;
#define MODIFY 4改为#define MODIFY 1
TCB_INTMEM|TCB_QUAD改为TCB_INTMEM|TCB_NORMAL;
TCB_EXTMEM|TCB_QUAD改为TCB_EXTMEM|TCB_NORMAL;
3〉修改程序,用软环境模拟外部中断来启动DMA传输,并观察传输结果。
通过下列步骤来建立一个外部中断:
a.打开对话框选Settings\Interrupts,会出现一个Interrupt Timing对话框;
b.设置中断属性;
c.设置断点并且运行程序.
用如下程序段:
_Set_IRQ_A: /设置外部中断/
j0=_IRQ0_ISR;;
IVIRQ0=j0;;
xr0=INT_IRQ0;;
IMASKH=xr0;; //外部中断IRQ0使能
SQCTLST=SQCTL_GIE;;
_Wait_For_Interrupt:
.align_code 4;
nop;nop;nop;idle;; //无限等待直到中断发生,然后跳至中断程序_IRQ0_ISR执行
jump _Wait_For_Interrupt;;
_IRQ0_ISR:
_Load_DMA0_TCBs: //将初始值倒入DMA0的传输和接收TCB
j0=DC0_Source_TCB;;
xr3:0=q[j0+j31];; //注意这种传递方式
j0=DC0_Destination_TCB;;
yr3:0=q[j0+j31];;
DCS0=xr3:0;;
DCD0=yr3:0;; //开始进行DMA传输
rti(np)(abs);;
代替以下原程序:
_Load_DMA0_TCBs: //将初始值倒入DMA0的传输和接收TCB
j0=DC0_Source_TCB;;
xr3:0=q[j0+j31];; //注意这种传递方式
j0=DC0_Destination_TCB;;
yr3:0=q[j0+j31];;
DCS0=xr3:0;;
DCD0=yr3:0;; //开始进行DMA传输
4〉分析两个程序的原理,简述软环境模拟外部硬件中断的程序流程。
参考源代码:
#include <defts201.h>
#define N 1024 /定义需要传输的32位字的个数=1024/
#define MODIFY 4 /每次传输的数据单元大小,4个字(128位)数据/
.section data1;/声明数据段1,存放对源TCB和目的TCB预先设置的参数/
.var DC0_Source_TCB[4]=
tx_data,
N<<16|MODIFY, /将N左移16位,即移至DX的高16位(计数位)/
0x0,
TCB_INTMEM|TCB_QUAD;/源选择为内部存储器/四字操作数/
.align 4;
.var DC0_Destination_TCB[4]=
rx_data,
N<<16|MODIFY, /将N左移16位,即移至DX的高16位(计数位)/
0x0,
TCB_EXTMEM|TCB_QUAD;/目标为外部存储器/四字操作数/
.section data2;
.var tx_data[N]; /定义内部存储器缓冲区,存储需要传输到外存的数据/
.section sdram0;
.var rx_data[N]; /在SDRAM中定义外部存储器缓冲区,存储从写入的数据/
.section program;
_Initialize_Bus_SDRAM: /初始化SYSCON和SDRCON/
xr0=SYSCON_MP_WID64|SYSCON_MEM_WID64|
SYSCON_MSH_PIPE2|SYSCON_MSH_WT0|SYSCON_MSH_IDLE|
SYSCON_MS1_PIPE1 |SYSCON_MS1_WT0|SYSCON_MS1_IDLE|
SYSCON_MS0_SLOW |SYSCON_MS0_WT3|SYSCON_MS0_IDLE;;
SYSCON=xr0;;
xr0=SDRCON_INIT |SDRCON_RAS2PC5 |SDRCON_PC2RAS2 |
SDRCON_REF3700|SDRCON_PG256 |SDRCON_CLAT2 |
SDRCON_ENBL;;
SDRCON=xr0;;
lc0=N;;
j0=tx_data;;
xr0=1;;
xr1=0;;
_Fill_Tx_Data:
xr1=r1+r0;;
[j0+=1]=xr1;;
if nlc0e,jump _Fill_Tx_Data;;
_Load_DMA0_TCBs: /将初始值倒入DMA0的传输和接收TCB寄存器/
j0=DC0_Source_TCB;;
xr3:0=q[j0+j31];; /注意这种传递方式/
j0=DC0_Destination_TCB;;
yr3:0=q[j0+j31];;
DCS0=xr3:0;;
DCD0=yr3:0;; /开始进行DMA传输/
_Done:
nop;nop;nop;nop;;
jump _Done;nop;nop;nop;;