外部中断控制DMA传输
DMA的原理就不多说了,之前的文章里有写。
- 电路中的Interrupt Pin
ADSP-TS201 EZ-KIT Lite评估板上每片DSP含有4个外部中断(IRQ3–0 ),其中IRQ0接到了一个按键上(SW4和SW5)。
当按键按下时,表现为低电平(可采用高低电平触发中断的模式)。
- Interrupt Pin的寄存器
涉及到中断的主要有以下这几个寄存器:ILAT,IMASK,PMASK,以及SQCTL下的GIE位控制全局中断,和INTCTL控制IRQ3-0的触发方式、TIME1-0的启动。ILAT,IMASK,PMASK这三者“相与”指明了正在执行的中断为哪一个。
ILAT:中断锁存寄存器,只要发生中断相应位置1;
IMASK:中断屏蔽寄存器,只有置1才允许响应相应的中断;
PMASK:锁存正在执行的中断,如果允许中断嵌套,只有在高于目前PMASK位的中断才可以响应。
ILAT IMASK PMASK (H)寄存器
这里要讲的IRQ0就在(H)寄存器中。
ILAT IMASK PMASK (L)寄存器
INTCTL寄存器
INTCTL控制IRQ3-0的触发方式、TIME1-0的启动。
SQCTL寄存器
SQCTL下的SQCTL_GIE位控制全局中断。SQCTL还有两个别名SQCTLST和SQCTLCL。
和一般的单片机如MCS-51,MSP430,以及ARM处理器相比,DSP的中断很独特。它的中断向量表是有专门的寄存器组来存储,而非像ARM处理、单片机那样放在存储器中,更不需要ARM那样复杂的地址映射之类操作。
调试步骤:
1)打开VisualDSP++,并新建一个工程文件,命名为”test3_2”,保存路径选择”D:\DSP\”;
2)新建C语言源程序文件,命名为” DMA_INT.asm”,并将文件添加至工程,并理解程序源代码;
3)新建或选择一个相应的调试会话Session (评估测试模式下的调试会话);
4)检查EZ-KIT板各SW设置是否正确;
5)用USB将PC与EZ-KIT板连接;
6)连接EZ-KIT板电源线,LED1(POWER)点亮、LED8(RESET)点亮,EZ-KIT板开始自动复位,复位完成后LED8熄灭,LED3点亮(USB MONITOR,注意此LED实际位置在USB上方),则表示EZ-KIT板与PC已经正常连接;
7)编译工程,在弹出的处理器选择窗口中,选择处理器A作为本次试验的处理器;手动分配自定义缓存区的存储空间以消除编译中出现的错误;
8)在代码中的SQCTLST=SQCTL_GIE;; 和rti(np)(abs);;两行分别设置断点;
9)打开两个TigerSharc Memory 窗口,观察地址分别设为tx_data和rx_data;
10)运行程序,观察TigerSharc Memory 窗口变化,继续运行程序,按下IRQ_A按键,再次观察TigerSharc Memory 窗口变化,理解程序的执行过程。
调试结果:
按照调试步骤,完成参考代码的运行,并记录现象,进一步认识模拟中断在实验二中控制DMA传输的过程。理解程序的执行过程。
参考源代码:
#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;;
_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);;
_Done:
nop;nop;nop;nop;;
jump _Done;nop;nop;nop;;