文档库

最新最全的文档下载
当前位置:文档库 > Nios II中断机制

Nios II中断机制

目标:

1.需要解析NiosII中断功能的基本特性,中断响应的方式,中断向量(Interrupt Vector)的分配方式。2.如果,我们自行设计一个IP,需要NiosII能够响应这个IP所产生的中断请求,那么在IP的rtl设计中有哪些要求,同时NiosII的程序中该如何实现?

要求

1.必须实现一个样例工程,在SOPC中集成一个专门用以提中断并让NiosII执行一个响应程序的小IP(该IP 的基本结构图所示),并完成图右伪码所描述的过程。实现相应的程序,并能够在FPGA上跑通。

Nios II中断机制

// IP进行中断请求

If (counter == 某个时间点)

interruptstate = 1;

// Nios对中断进行清除

If (interruptClear == 1)

counter = 0; // 重新计数

interruptstate = 0; // 清中断

2.最终必须提交一份文档,详细描述NiosII中断相关功能和工程实现方法,一定要言简意赅,并且尽量做到面面俱到。

3.最迟8月1日前完成,越早越好。

其他

1.SOPC的相关使用方法,以及如何在SOPC中加入一个自己设计的IP,请去908室让一位师兄给你们集体培训一下,一个下午足矣。

2.NiosII的相关文档请至altera的网站上寻找,网址如下:

http://www.wendangku.net/doc/f27cf81d227916888486d7af.html/support/ip/processors/nios2/ips-nios2_support.html

3.一些相关的东西,908的郑勇师兄以前了解过,可咨询他。

4.FPGA板,用908里的180,用的时候从908拿,用完还回去。

Nios II中断处理机制之硬件实现

首先介绍下Nios II CPU处理中断的3个控制寄存器

Nios II中断机制

(1).status control Register:它的bit0位(PIE)是全局中断允许位,置1表示使能;

(2).ienable control Register:是中断允许寄存器,其中每一位控制着一个中断源,1代表允许,0代表禁止,共32位;

(3).ipending control Register:每一位对应着一个中断源的中断请求,1代表有中断,0代表没有……共32位。

下图显示了硬件中断的产生

Nios II中断机制

一、中断的产生

1 .timer中断

Nios II自带的timer模块,counter从高位计数减到0,在中断使能的情况下,产生中断请求信号。

Nios II中断机制

图1 timer寄存器

在SOPC Builder中例化32位Timer,技术周期500ms.

2.PIO中断

Nios II中断机制

Nios II自带的PIO模块,定义一位input only port PIO命名为KEY。输入为高电平时,在中断使能的情况下,产生中断请求信号。

assignirq = (data_in&irq_mask);

二、NiosII的中断处理过程

1.把status寄存器内容复制到estatus寄存器中,保存当前处理器状态;

2.清除status寄存器全局中断允许位PIE,禁止中断;

3.将下一条将执行的指令的地址存入R29,以便中断返回之用;

4.跳转到中断入口地址,进入系统ISR;

5.系统ISR保护现场;

6.系统ISR检测estatus寄存器的PIE位,如为0则进入软中断处理程序从

11继续,否则由7继续;

7.系统ISR检测ipending control Register,如果有中断申请,则转到硬中断

处理和序,否则进入软中断处理程序;

8.硬中断处理程序将检测中断申请号,并检索中断向量表,跳转到用户中断

处理程序;

9.用户中断处理程序做出具体的处理,最后返回系统ISR;

10.系统ISR恢复现场,并返回;

11.软中断处理程序进行陷井指令、模拟指令判断,并做相应处理,然后返回

系统ISR;

12.系统ISR恢复现场并返回;

注释:中断向量表存储在Exception memory下,而中断服务程序存储在program memory下。

Nios II中断处理机制之软件部分

Nios II 中所有的中断处理都从同一入口进入,然后由软件加以分配。负责分配工作的软件叫系统ISR,它是由开发系统提供的,自动的连接到可执行程序上。系统ISR维护着一个中断向量表,表中的每一项代表着一个专项处理程序的入口。处理程序由用户定义然后注册到中断向量表中的,叫做用户ISR。系统ISR的入口地址是在SOPC_Builder中定义的(Exception Address,可在sopc builder中cpu配置中修改)。

ISR(Interrupt Service Routine)中断服务凼数是为硬件中断服务的子程序。NIOS

II 处理器支持32 个硬件中断,每一个使能了的硬件中断都应该有一个ISR 与之对应。

中断产生时,硬件中断处理器会根据检测到的有效中断级别,调用相应的 ISR为其进行

中断服务。

第一、注册中断凼数 ISR

它的凼数原型如下所示:

Intalt_irq_register(alt_u32 id, void* context, void(*handler) (void*,alt_u32)); id:中断优先级,即所注册的 ISR是为哪个中断优先级的中断服务的。中断优先级

在 SOPC Builder 中分配的。

Context:为所注册癿的ISR传递参数,可以是NULL;

Handler,中断服务凼数ISR的指针,指向用户ISR入口。

如果注册成功,函数返回0,并允许全局中断及被服务中断;不成功返回非0值。

第二、编写ISR凼数,这个凼数有我们自己来写,而不是HAL系统提供的。

对 ISR的凼数原型有特定的要求:

voidISR_handler( void* context, alt_u32 id );

context: 传给ISR癿形参,可以是NULL;

id: 中断优先级。

Nios II中断处理过程从软件编程上分为3个步骤:

1.中断的注册;

2.中断处理程序;

3.中断的执行与清除。

下面从实验的C程序从软件编程上简要说明Nios II中断处理过程。

实验一:timer中断

功能:实现开发板上timer每隔500ms计数到零向cpu发中断,执行中断服务程序触发LED灯闪烁一次。

#include"key.h" //包含PIO口结构体指针的头文件,方便对IO口各寄存器赋值#include

#include "io.h"

#include"system.h" //系统配置文件,可以看到各模块以及中断优先级等信息

#include"altera_avalon_pio_regs.h" //pio模块寄存器偏移量

#include"altera_avalon_timer_regs.h" //timer模块寄存器偏移量

#include"alt_types.h"

#include"sys/alt_irq.h" //包含中断注册函数等,使用中断功能必须包含此文件

//////定时器初始化,包含中断的注册,这样timer发出的中断才能够被系统接收////// voidinit_timer(void)

{

//状态寄存器初始化

IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0x00);

//控制寄存器初始化

IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x07);

//中断的注册,此函数也可以放在main中

//alt_irq_register(中断优先级,中断模块基址指针,中断处理程序名)

alt_irq_register(TIMER_0_IRQ, (void *)TIMER_0_BASE, ISR_timer);

}

///////////中断处理程序,由alt_irq_register中中断程序名命名////////////// int flag = 0;

voidISR_timer(void *context,alt_u32 id)//unsigned long->alu_u32

{

flag = ~flag; //实现标志位flag每次中断翻转一次

IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0);//中断的清除

}

////////////////////主程序,实现LED灯的闪烁///////////////////////////// intmain()

{

while(1){

if(flag){

LED->DATA = 1;}

else{

LED->DATA = 0;}

}

return 0;

}

实验二:PIO中断

功能:在开发试验版上实现外部拨动开关sw0=1时每间隔一段时间向cpu请求中断,执行中断服务程序,触发LED灯不断闪烁。

用户编写的系统头文件sopc.h如下:

* sopc.h

*

* Created on: 2011-7-28

* Author: Huanglu

*/

#ifndef SOPC_H_

#define SOPC_H_ //新建头文件时自动生成

#include "system.h"//系统配置文件,可以看到各模块以及中断优先级等信息

#define _LED //增强代码的严谨性和可控制性

#define _KEY

typedefstruct

{

unsigned long int DATA;

unsigned long int DIRECTION;

unsigned long int INTERRUPT_MASK;

unsigned long int EDGE_CAPTURE;

}PIO_STR;

#ifdef _LED //定义PIO口结构体

#define LED ((PIO_STR *)PIO_LED_BASE)//定义了一个宏,命名为LED,它是指向 PIO_LED_BASE的结构体指针.

#endif

#ifdef _KEY

#define KEY ((PIO_STR *)KEY_BASE) //同LED

#endif

#endif /* SOPC_H_ *///新建头文件时自动生成

用户程序通过外部拨动开关来产生中断。当拨动开关sw0高电平时时,就会触发中断。在中断函数中,我们对key_flag迕行取反。而在主函数中,我们不断地进行查询,当key_flag为1时, LED->DATA置1,也就是让外部发光二级管亮;当key_flag为 0时,LED->DATA 置0,这时,发光二级管不亮。Sw0一直为高电平时,执行中断服务时关中断,处理完开中断,sw0又触发中断,如此往复,实现发光二级管不断闪烁。

用户源程序main.c如下:

/*

* main.c

*

* Created on: 2011-7-28

* Author: Huanglu

*/

#include

#include

#include

#include "system.h" //系统配置文件,可以看到各模块以及中断优先级等信息。软件开发时自动生成的。

#include "../inc/sopc.h" //用户系统的头文件.包含PIO口结构体指针.

#include "sys/alt_irq.h" //包含中断注册函数等,使用中断功能必须包含此文件volatile intkey_flag=0;//前加volatile防止变量key_flag被优化掉,默认零。uint *debug; //定义debug指针,用于追踪程序执行到哪了

////////// 中断处理程序,//////////////

voidISR_key(void * context,unsigned long id)

{

KEY->INTERRUPT_MASK=0; //关中断

key_flag=~key_flag; //实现标志位key_flag每次中断翻转一次

*(debug+20)=20;

}

//PIO初始化,包含中断的注册,这样PIO发出的中断才能够被系统接收//////

intinit_key(void)

{

*(debug+16) = 16;

KEY->INTERRUPT_MASK=1;//开中断,允许PIO产生中断。

*(debug+17) = 17;

return alt_irq_register(KEY_IRQ,NULL,ISR_key);//注册中断,注册成功返回0

}

////////////////////主程序,实现LED灯的闪烁/////////////////////////////

int main()

{

int i;

debug = (uint *)DEBUG_BASE;//指针debug指向DEBUG_BASE *debug = 1;

*(debug+22) = 22;

if(!init_key()){

*(debug+1) = 2; //注册成功

}

else{

*(debug+1) = 3; //注册失败

}

*(debug+2) = 4;

while (1){

if(key_flag){

LED->DATA=1;

*(debug+7)=7;

}

else{

LED->DATA=0;

*(debug+8)=8;

}

*(debug+3)=5;

for(i = 0;i<1000000;i++);

i = 0; //延时,便于观察LED灯的闪烁。

KEY->INTERRUPT_MASK=1;开中断,接受下一轮中断。

}

return 0;

}

总结:

若要在Nios II系统中实现中断操作,至少需要以下要求:

<一>.sopc builder搭建系统时:

1.分配系统ISR的入口地址,可手动设置也可使用默认值;

2.设置中断优先级,0-31优先级逐次降低,中断优先级可以在新建软件工程时生成的

system.h文件中查看,但不可以在system.h中直接修改。

<二>.编写软件部分时:

1.对模块进行正确初始化,确保中断能够被系统接收,如中断使能位置1;

2.注册中断(alt_irq_register);

3.由中断注册指向所需的中断程序;

4.正确声明所需的头文件;

5.cpu执行中断服务程序时没有对中断进行清除,清除中断必须在用户程序中实现。