DSP中断实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

DSP实验大作业
班级:020851
姓名:徐宏立
学号:02085086
一.实验目的:
•了解和熟悉中断的原理
•能够保护中断程序下条指令的地址,能够转到中断请求所相应的处理程序,能够回到原来的程序。

•熟悉中断向量的访问。

•熟悉用户模式,仿真模式和监控模式的相互转换过程。

•熟悉FIR_DIR,FIR_FLAG_S,FIO_FLAG_C,FIO_EDGE,FIO_POLAR,FIO_MASKA_S,SIC_IMASK,IMASK的设置。

•熟悉计时器的配置
二.实验任务
•使用外部中断实现LED闪烁频率的改变
•实现嵌套中断
三.实验分析:
1.中断的基本认识
处理器的事件控制器处理所有的同步和异步事件,并管理5种类型的事件:仿真、复位、非屏蔽中断(NMI)、异常和中断(11种)。

中断:一种改变处理器正常指令流的异步事件。

处理器在正常执行程序过程中,由于内部/外部事件的触发或程序的预先
安排,引起处理器暂时中断当前正在运行的程序,而去执行内部/外部事
件或程序预先安排事件的服务子程序。

等中断服务子程序执行完毕后,处理器再返回到暂时中断程序处继续执行原来的程序。

事件系统有优先级而且可嵌套,优先级高的任务可以占用优先级低的任务的资源。

Blackfin DSP采用2级事件控制机制,一起控制所有系统中断并管理它们的优先级
1)系统中断控制器(SIC)
2)内核事件控制器(CEC)
SIC提供多个外设中断源和内核通用中断输入之间的映射。

某个中断可以在SIC中屏蔽掉
CEC支持9个通用中断(IVG7~IVG15)。

通常选用优先级最低的两个中断IVG14和IVG15作为软件中断
事件列表如下:
系统中断过程:
中断是由能够产生中断的外设产生的,系统中断过程简要概述为:
当一个中断产生时:
①SIC_IWR检查DSP内核是否从一个空闲状态中被中断唤醒
②SIC_ISR记录中断请求,并且跟踪被激活但未被服务的系统中断
③SIC_IMASK可以在系统级上屏蔽、使能外设的中断。

如果有一个中断A未被屏蔽,那么中断请求过程进入下一步
④SIC_IARx寄存器组用来将外设中断映射到通用的内核中断组(IVG7-IVGl5),并且决定中断A的优先级
⑤ILAT将中断A记录在内核中,但此时该中断还没有真正被响应
⑥IMASK屏蔽、使能不同优先级的内核中断。

如果中断A对应的IVG事件没有被屏蔽,中断过程就进入下一步
⑦访问事件向量表(EVT),查找中断A 的中断服务程序(ISR)的中断矢量。

⑧当中断A 的事件矢量进入内核的流水线时,相应的IPEND位被置位,该位将清除对应的ILAT位。

因此,IPEND可以记录所有的被系统挂起的中断和正在服务的中断
⑨在执行中断A 的中断服务程序时,RTI指令就会清除相应的IPEND位。

但是,相关的SIC_ISR位不会被清除,除非中断服务程序清除了产生中断A 的机制,或
者服务中断的进程清除了该位。

系统中断过程如下图:
对于上述中断过程:
仿真、复位、NMI、异常事件、硬件错误和内核定时器中断请求在ILAT 级上进入中断处理链,所以它们不受系统级的中断寄存器组(SIC_IWR, SIC_ISR,
SIC_IMASK, SIC_IARx)的影响
如果有很多个中断源共享一个内核中断,那么中断服务程序就必须能识别产生中断的外设。

中断控制寄存器:
1. 系统中断唤醒使能寄存器 (SIC_IWR)
系统中断唤醒使能寄存器 (SIC_IWR):1唤醒使能,0唤醒使能禁止
通过设置该寄存器的相应位,任一外设都可以唤醒内核从空闲状态进入中断过程
如果内核没有处于空闲状态,则该寄存器对内核没有影响
寄存器状态功能图如下:
2.系统中断状态寄存器 (SIC_ISR)
系统中断状态寄存器(SIC_ISR):1中断被激活,0中断未激活
寄存器每个有效位对应于一个外设中断源
SIC发现一个中断被激活时,相应位被置位;被撤销时,相应位被清除 3. 系统中断屏蔽寄存器 (SIC_IMASK)
系统中断屏蔽寄存器(SIC_IMASK):0中断屏蔽,1中断使能
该寄存器可以屏蔽SIC上的任何外设中断源,
复位时所有外设的中断被屏蔽
唤醒功能和中断屏蔽功能相互独立:如果在SIC_ISR使能一个中断源,在
SIC_IMASK中屏蔽该中断源,那么如果内核处于空闲状态,内核会被唤醒,但不会产生中断
4.系统中断设置寄存器(SIC_IARx)
通过将外设中断映射到内核中适当的通用中断级,可以设置外设中断的优先权
映射受三个寄存器控制:SIC_IRA0, SIC_IRA1, SIC_IRA2
设置外设到一个特定的IVG优先级时,写入SIC_IARx的值:
事件控制的寄存器:
事件控制器使用了3个寄存器来协调挂起事件的请求。

每一个寄存器都是16位的,并且寄存器中的每一位都对应事件向量表中的一个事件。

这些寄存器是:
1)ILAT-中断锁存寄存器
ILAT: 中断锁存寄存器中的每一位指示对应的中断是否被锁存
0-没有锁存;1-锁存
当一个事件被服务时,它在ILAT中的对应位就会被清除。

指令RAISE N 使ILAT寄存器中的第N位置位,并且只能被IVG15~IVG7、IVTMR、IVHW、NMI和RST等事件触发
位0的复位值取决于是否处于硬件仿真,只有JTAG的TRST脚才可清除ILAT[0] 2)IMASK-中断屏蔽寄存器
IMASK: 中断屏蔽寄存器中的每一位指示对应的中断是否被使能
0-中断屏蔽;1-中断使能
一个中断位在ILAT寄存器中设置后,只有在IMASK中也设置了这个位,内核才会接受这个位所控制的中断
3)IPEND-中断挂起寄存器
IPEND: 中断挂起寄存器记录当前所有的嵌套中断
位0:硬件仿真
位4:全局中断禁止
其他位:0-没有中断挂起,1-中断挂起或激活
IPEND中的每一位指示一个中断是否被激活,或是否在某一级上被嵌套
在进入或退出一个中断服务程序时,事件控制器使用IPEND[4]位暂时性地禁止中断
当正在处理一个事件时,IPEND中相对应的位就会被置位
SIC_IPEND寄存器:
中断全局禁止和使能:
1)中断全局禁止指令 CLI Dreg
设置IMASK寄存器为全零来禁止普通中断,并将IMASK寄存器以前的值保存在指定的数据寄存器Dreg中
2)中断全局使能指令 STI Dreg
恢复以前保存的IMASK寄存器的值来允许普通中断,以前的IMASK寄存器的值保存在指定的数据寄存器Dreg中
**复位,NMI、仿真和异常事件都不能使用全局使能和禁止的方法
事件向量表EVT:
EVT包含每一个可能事件的入口。

当一个事件发生时,在该事件的EVT入口所指的地址处开始读取指令。

每一个事件在寄存器ILAT、IMASK和IPEND中都有对应的位
内核事件向量表:
3.本实验知识分析:
程序利用SW4-SW7产生中断12,改变LED1-LED4的闪烁频率,执行相应的中断服务程序(ISR)
•利用外部计时器timer0产生计时中断,中断程序中断LED的闪烁,使LED变灭(或可以重新点亮)
可编程窗口:
1)Blackfin 的工作模式
三种模式:
a. 用户模式
不处于空闲状态、复位状态,不处理中断、NMI 、异常和仿真事件
处于用户模式的时候不能访问存储器映射寄存器(MMR )
b. 监控模式
对资源访问无限制
c. 仿真模式 中断15 中断12 中断
11 灯闪烁
灯灭
改变频率
对资源访问无限制
2)程序设计过程:
设置EVT(0~15),以设置EVT12为例
P0.H = HI (EVT12);
P0.L = LO (EVT12);
R0.H = _FRE_SWH;
R0.L = _FRE_SWH;
[ P0 ] = R0;
准备退出,保证顺利进入用户模式
R0 = 0x8000 (Z);
STI R0;
RAISE 15;
R0.L = wait_here;
R0.H = wait_here;
RETI = R0;
进入用户模式
RTI;
停留在用户模式
wait_here:
JUMP wait_here;
根据之前程序:
R0 = 0x8000 (Z);
STI R0;
RAISE 15;
被迫进入中断15
中断嵌套:
监控模式(15号中断)
灯闪烁
灯的闪烁频率有P5设置,代码实现如下:
P5.L = 0x0000;
P5.H = 0x0e00; // 初始设置LED的闪烁频率
R1.L = 0x000F;
BLINK:
W[ P2 ] = R1.L; // 设置PF0 - PF3为高电平输出CALL DELAY_LOOP;
CSYNC;//内核同步指令
W[ P1 ] = R1.L; // 设置PF0 - PF3为低电平输出CALL DELAY_LOOP;
CSYNC;//内核同步指令
JUMP BLINK;
允许新的中断,通过按键激活新的中断
允许中断嵌套,保护现场
[ --SP ] = RETI;
中断设置:
哪些灯闪烁?
设置FIO_DIR
P0.H = FIO_DIR >> 16;
P0.L = FIO_DIR & 0xFFFF;
R0.H = 0x000F;
W[ P0 ] = R0.H;
CSYNC;
初始时显示什么?
设置FIO_FLAG_S和FIO_FLAG_C
闪烁频率?
将频率参数保存在一个寄存器Px
要有按键输入,触发新的中断
设置FIO_EDGE和FIO_POLAR
定义并使能响应的中断:
FIO_MASKA_S
SIC_IMASK
IMASK
如何让灯闪烁?
改变FIO_FLAG_S和FIO_FLAG_C
每一个亮灯状态的保持时间:通过寄存器Px的值保持Delay周期
改变闪烁频率:设置寄存在Px中的闪烁频率
改变闪烁频率,先确保退路
[--SP] = RETI;
扫描每一个按钮,检测需要改到什么频率
R5 = W[ P1 ];
CC = BITTST (R5, 4);
IF CC JUMP RATE_i;
RATE_i中改变频率并原路返回
P5.H = 0x0200;
P5.L = 0x0000;
CSYNC;
RETI = [SP++];
RTI;
四.程序代码及注释:
#include "defBF535.h"
.section l2_bank0;
.global _MAIN;
_SETUP:
SP.H = 0xFFB0; // 设置监视模式下的堆栈起始地址,为了加快访问时间,
SP.L = 0x0F00; // SP应设置在scratch pad (0xFFB0 0000 - 0xFFB0 0FFF)中
//-----------------------------------------------------------------------------------//
P0.H = HI (EVT12);
P0.L = LO (EVT12);
R0.H = _SET_RATE;
R0.L = _SET_RATE;
[ P0 ] = R0; // 将中断事件_SET_RATE入口地址写入中断向量列表(IVT)EVT12中
//-----------------------------------------------------------------------------------//
P0.H = HI (EVT11);
P0.L = LO (EVT11);
R0.H = _IDLE;
R0.L = _IDLE;
[ P0 ] = R0; // 将中断事件_SET_RATE入口地址写入中断向量列表(IVT)EVT11中
//-------------------------------------------------------------------
----------------//
// 由于系统在重启(reset)后进入事件setup event, 其优先级高于IVG7 - IVG15,故其
// 在监视模式下无法对IVG7 - IVG15做出响应,但是我们可以在用户模式下使系统响应
// IVG15,然后使其转入监视模式,从而系统可以响应优先级高于IVG15的中断(中断嵌套)
// ,从而完成本程序的功能。

//-----------------------------------------------------------------------------------//
P0.H = HI (EVT15);
P0.L = LO (EVT15);
R0.L = ISR15;
R0.H = ISR15;
[ P0 ] = R0; // 将中断事件ISR15的入口地址写入中断向量列表(IVT)EVT15中
//-----------------------------------------------------------------------------------//
R0 = 0x8000 (Z);
STI R0; // 使能EVT15中断服务程序,中断允许指令
RAISE 15; // 产生EVT15中断
P0.L = WAIT_HERE;
P0.H = WAIT_HERE;
RETI = P0; // 将中断返回地址放入RETI中
RTI; // 中断返回,转入用户模式
WAIT_HERE:
JUMP WAIT_HERE; // 等待中断服务程序ISR15运行
ISR15:
[ --SP ] = RETI; // 中断服务程序ISR15运行后,系统转入监视模式,压栈保护RETI
JUMP _MAIN; // 使ISR15支持中断嵌套调用
_MAIN:
P0.H = HI (FIO_DIR); //FIO_DIR标志方向寄存器:15~0 PF管脚,逻辑1配置为输出,逻辑0配置为输入
P0.L = LO (FIO_DIR);
R0.L = 0x000F;
W[ P0 ] = R0.L; // 设置PF0 - PF3为输出管脚,LED显示;PF4 -
PF7为输入管脚,改变频率
CSYNC;//内核同步指令
//--------------------------------------------------------------------------------------------//
P1.H = HI (FIO_FLAG_C); //标志清除寄存器
P1.L = LO (FIO_FLAG_C);
P2.H = HI (FIO_FLAG_S); //标志置位寄存器
P2.L = LO (FIO_FLAG_S);
//用来检测设置为输入的PF管脚的电平和设置为输出管脚的状态,并可以用来清除由PF管脚引起的中断
//此处用来设置BLINK的时候灯亮灭的变化
//--------------------------------------------------------------------------------------------//
P0.H = HI (FIO_EDGE); //标志中断触发方式寄存器,用来配置每一个管脚的触发方式为电平触发或者边沿触发
P0.L = LO (FIO_EDGE); //默认为0,电平触发;1为边沿触发
R0.L = 0x0000;
W[ P0 ] = R0.L; // 设置PF4 - PF7为边沿触发
CSYNC;//内核同步指令
P0.H = HI (FIO_POLAR);//标志极性寄存器,用来标志输入源的极性;如果选择高电平或者上升沿激活,
P0.L = LO (FIO_POLAR);//在寄存器对应位写入0;如果选择低电平或者下降沿激活,在寄存器对应位写入1
R2.L = 0x0000;
W[ P0 ] = R0.L; // 设置PF4 - PF7为上升边沿触发
CSYNC;//内核同步指令
P0.H = HI (FIO_MASKA_S);//标志中断屏蔽寄存器,1为使能对应位
P0.L = LO (FIO_MASKA_S);
R0.H = 0x00f0;
W[ P0 ] = R0.H; // 使能PF4 - PF7中断,产生的中断事件为A类CSYNC;//内核同步指令
P0.H = HI (SIC_IMASK); //系统中断屏蔽寄存器,1为使能,0为屏蔽(V1.0以后版本取反)
P0.L = LO (SIC_IMASK);
R0 = [ P0 ];
BITCLR(R0, 17); // 使能内核能够接受PF产生的A类中断
BITCLR(R0, 14); // 使能内核能够接受Timer0中断
[ P0 ] = R0;
CSYNC;//内核同步指令
P0.L = LO (SIC_IWR); // enable PLL Wakeup Interrupt
P0.H = HI (SIC_IWR); //系统中断唤醒使能寄存器
R0.H = 0x0002; //唤醒PF中断A,对应上一步中改变第十七位
R0.L = 0x0000;
[ P0 ] = R0;
CSYNC;//内核同步指令
P0.H = HI (IMASK); //内核中断屏蔽寄存器
P0.L = LO (IMASK);
R0 = [ P0 ]; // 使能中断处理模块查找中断向量列表,执行Programmable
BITSET (R0, 12); //使能中断12
BITSET (R0, 11); //使能中断11
[ P0 ] = R0;
CSYNC;//内核同步指令
//==============================Timer0设置
===================================//
P0.H = HI(TIMER0_CONFIG); //定时器设置寄存器,中断请求有效(第五位),设置为周期结束计数(第四位)
P0.L = LO(TIMER0_CONFIG);
R0.L = 0x0019;
W[P0] = R0.L; //设置为PWM_OUT模式(第一位和第二位),此时Timer0为输出管脚
R1.H = 0xa000;
R1.L = 0x0000;
P0.L = LO(TIMER0_PERIOD_HI);
W[P0] = R1.H;
P0.L = LO(TIMER0_PERIOD_LO); //定时器周期寄存器
W[P0] = R1.L;
P0.L = LO(TIMER0_WIDTH_HI); //定时器宽度寄存器
W[P0] = R2.H;
P0.L = LO(TIMER0_WIDTH_LO);
W[P0] = R2.L;
P0.L = LO(TIMER0_STATUS); //定时器状态寄存器
R0.L = 0x0100;
W[P0] = R0.L;
SSYNC; //系统同步指令
//=============================================================== =========================//
P5.L = 0x0000;
P5.H = 0x0e00; // 初始设置LED的闪烁频率
R1.L = 0x000F;
BLINK:
W[ P2 ] = R1.L; // 设置PF0 - PF3为高电平输出
CALL DELAY_LOOP;
CSYNC;//内核同步指令
W[ P1 ] = R1.L; // 设置PF0 - PF3为低电平输出
CALL DELAY_LOOP;
CSYNC;//内核同步指令
JUMP BLINK;
_MAIN.END:
//-------------------------------闪烁时延子程序
---------------------------------------//
DELAY_LOOP: // 闪烁时延函数
LSETUP (L_BEGIN, L_END) LC0 = P5;
L_BEGIN:
L_END: NOP;
RTS;
//-----------------------------------IVG12 HANDLER,
----------------------------------//
_SET_RATE: // 响应_SET_RATE,扫描每一个PF是否按下,进行中断嵌套和响应并返回
[ --SP ] = RETI;
R5 = W[ P1 ];
CC = BITTST (R5, 4);//检查PF4是否按下,产生中断,跳转到相应频率设置
IF CC JUMP SET_RATE_1;
CC = BITTST (R5, 5);//检查PF5是否按下,产生中断,跳转到相应频率设置
IF CC JUMP SET_RATE_2;
CC = BITTST (R5, 6);//检查PF6是否按下,产生中断,跳转到相应频率设置
IF CC JUMP SET_RATE_3;
CC = BITTST (R5, 7);//检查PF7是否按下,产生中断,跳转到相应频率设置
IF CC JUMP SET_RATE_4;
SET_RATE_1:
P5.H = 0x0900;
P5.L = 0x0000;
CSYNC;//内核同步指令
RETI=[SP++];// 中断嵌套,返回地址
RTI;
SET_RATE_2:
P5.H = 0x0500;
P5.L = 0x0000;
CSYNC;//内核同步指令
RETI=[SP++];// 中断嵌套,返回地址
RTI;
SET_RATE_3:
P5.H = 0x0100;
P5.L = 0x0000;
CSYNC;//内核同步指令
RETI=[SP++];// 中断嵌套,返回地址
RTI;
SET_RATE_4:
P5.H = 0x0060;
P5.L = 0x0000;
CSYNC;//内核同步指令
RETI=[SP++];// 中断嵌套,返回地址
RTI;
//-------------------------------------------IVG11
HANDLER--------------------------------//
_IDLE:
W[ P1 ] = R1.L;
R0.L = 0x0019;
W[P0] = R0.L;
IDLE;
SSYNC;//系统同步指令
//----------------------------------------------------------------------------------------//
五.问题分析:
在本次试验中遇到的最困惑的问题是:
在程序段:Timer0中:
P0.H = HI(TIMER0_CONFIG); //定时器设置寄存器,中断请求有效(第五位),设置为周期结束计数(第四位)
P0.L = LO(TIMER0_CONFIG);
R0.L = 0x0019;
W[P0] = R0.L; //设置为PWM_OUT模式(第一位和第二位),此时Timer0为输出管脚
R1.H = 0xa000;
R1.L = 0x0000;
P0.L = LO(TIMER0_PERIOD_HI);
W[P0] = R1.H;
P0.L = LO(TIMER0_PERIOD_LO); //定时器周期寄存器
W[P0] = R1.L;
P0.L = LO(TIMER0_WIDTH_HI); //定时器宽度寄存器
W[P0] = R2.H;
P0.L = LO(TIMER0_WIDTH_LO);
W[P0] = R2.L;
P0.L = LO(TIMER0_STATUS); //定时器状态寄存器
R0.L = 0x0100;
W[P0] = R0.L;
SSYNC; //系统同步指令
并未设置R2的宽度,按理来说程序应该无法执行,因为电平不会改变,但实际上程序可以正常运行,经过单步调试发现R2的宽度值并不为0,而为Ox7000。

又再次想到也许是与R0的宽度有关,于是将R0改变,发现R2并不发生变化,于是认为R2的值也许是系统默认值,但是当R0的值变化超过R2宽度2倍的时候程序将无法正常运行。

相关文档
最新文档