1. 概述

NIOS2 支持32个内部硬件中断,且有32级别的中断请求(irq0-irq31)。

软件通过ienable控制寄存器使能和取消中断源,还可以通过status控制寄存器的PIE位全局的开使能和取消所有中断。

硬件中断产生的条件:

  • status寄存器的PIE位为1

  • 一个中断请求输入申请irq<n>

  • 在ienable寄存器中对应的位置1


2. HAL接口API

<sys/alt_irq.h>
int alt_ic_isr_register (alt_u32 ic_id, alt_u32 irq, alt_isr_func isr, void* isr_context, void* flags)
int alt_ic_irq_enable (alt_u32 ic_id, alt_u32 irq)
int alt_ic_irq_disable (alt_u32 ic_id, alt_u32 irq)
void alt_irq_init (void* base) 
//定义ISR中断处理函数:
typedef void (*alt_isr_func) (void* isr_context);


3. 按键中断

1) 在QSYS中添加PIO组件

设置PIO位宽为1,输入模式,勾选同步边沿capture,上升沿方式,使能IRQ生成,EDGE方式。

wKiom1hbPb7wYeQhAACyyFtUEVA288.jpg

2)编写代码

#include <stdio.h>
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"

alt_u8 key_flag =0;

void ISR_handle_button(void* context ){
	key_flag =~key_flag;
	printf("button interrupt!\n");
	IOWR_ALTERA_AVALON_PIO_EDGE_CAP( PIO_0_BASE,0x0);// clear the interrupt
}

void init_button_pio(void){
	IOWR_ALTERA_AVALON_PIO_IRQ_MASK( PIO_0_BASE,0x1);// 使能按钮中断
	IOWR_ALTERA_AVALON_PIO_EDGE_CAP( PIO_0_BASE,0x0);// 清边沿捕获寄存器
	alt_ic_isr_register(PIO_0_IRQ_INTERRUPT_CONTROLLER_ID, PIO_0_IRQ, ISR_handle_button,NULL,0x0);
}

int main(){
	init_button_pio();
	while(1);
	return 0;
}


4. 自定义组件中断

在定义自己的Qsys组件时,可以添加自己的中断。

wKiom1hbQWnhpxytAADEKk-dtPo546.jpg

软件编写:

#include <stdio.h>
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"

void ISR_handle_FUNC(void* context){
	...
	//清除中断
}

int main(){
	volatile int i=0;
	
	alt_irq_init(ALT_IRQ_BASE);
	if(!alt_ic_isr_register(ALT_IRQ_INTERRUPT_CONTROLLER_ID, ALT_IRQ, ISR_handle_FUNC,NULL,0x0))
		printf("The IRQ is set\n");
		
	while(1);
	return 0;
}


5. 总结

  • NIOS2中断系统中,中断号越小中断优先级越高。

  • 尽量不要在中断处理函数中使用不可重入的函数,否则可能死锁,比如printf函数。

  • 使用全局变量时,使用volatile,确保每次都能从内存中获得变量值。