第五节,ZYNQ中断

ZYNQ中断

1 中断类型

ARM处理器支持7种异常情况:复位、未定义指令、指令预取终止、数据终止、中断请求(IRQ)和快速中断请求(FIQ)。

复位(RESET):但处理器的复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行。复位异常中断通常用在下面两种情况,一是系统加电时和系统复位时;二是跳转到复位中断向量处执行;

数据访问中止(data abort):如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问中止异常中断;

快速中断请求(FIQ):当处理器的外部快速中断请求引脚有效,而且CPSR寄存器的F控制位被清除时,处理器产生外部中断请求(FIQ)异常中断;

外部中断请求(IRQ):当处理器的外部中断请求引脚有效,而且CPSR寄存器的I控制位被清除时,处理器产生外部中断请求(IRQ)异常中断。系统中各外设通常通过该异常中断请求处理器服务;

预取指令中止(prefech abort):如果处理器预取指令的地址不存在,或者该地址不允许当前指令访问,当该被预取的指令执行时,处理器产生指令预取中止异常中断;

软件中断(software interrupt SWI):这是一个用户定义的中断指令,可用于用户模式下的程序调用特权操作指令。在实时操作系统(RTOS)中可以通过该机制实现系统功能调用;

未定义的指令(undefined instructin):当ARM处理器或者是系统中的协处理器认为当前指令未定义时,产生未定义的指令异常中断,可以通过该异常中断机制仿真浮点向量运算。

2 中断体系结构

Zynq中有两个cortex-a9处理器和GIC pl390中断控制器,中断结构体系如图1所示。中断类型主要包括私有中断、软件中断和共享中断,其体系结构中管理中断的是通用中断控制器。

每个CPU都有一组私有外设中断(PPI),PPI包括全局定时器、私有看门狗定时器、私有定时器和来自PL的FIQ/IRQ。

软件中断(SGI)连接到其中一个CPU或者所有的CPU,通过写ICDSGIR寄存器产生SGI。

共享中断(SPI)是通过PS和PL内各种I/O和存储器控制器产生。图2给出了中断源,它们连接到其中一个CPU或者所有的CPU。

通用中断控制器(GIC)是核心资源,用于管理来自PS或者PL的中断,这些中断发送到CPU。

 

第五节,ZYNQ中断

图1 中断体系结构

GIC用于对系统上百个中断源进行分类、总裁等工作,是系统中断处理的核心部件,其整个系统中的位置如图1所示。GIC处于中断源与CPU之间,负责对中断触发信号进行时能控制、分类、编码、优先级等设置等操作,最后将中断信号送入CPU。送入CPU的每路中断信号都具有唯一的ID编码,CPU通过查询ID编码可判断中断源位置,内部结构如图2所示。

第五节,ZYNQ中断

图2 中断控制器框架

中断ID表:

软件中断SGI的中断ID分布如表1所示。

表1 SGI中断ID

第五节,ZYNQ中断

CPU私有外设中断PPI的中断ID分布如表2所示。

表2 PPI中断ID

第五节,ZYNQ中断

共享外设中断SPI的中断ID分布如表3所示

第五节,ZYNQ中断

第五节,ZYNQ中断

3 定时器中断使用实例

Zynq上私有定时器的如下特性:

1,32位计数器,当到达零时,产生一个中断;

2,8位预分频器,能够更好的控制中断周期;

3,可配置的一次性或者自动重加载模式;

4,2次时间间隔可通过下进行计算:时间间隔=[(预分频器的值+1)(加载值+1)]/该定时器频率。所有私有定时器和看门狗定时器总是工作在CPU频率的1/2(CPU_3x2x)。

配置私有定时器的步骤如下:

第一,GIC中断控制器的初始化

  1. 连接到硬件,把对应中断映射到GIC中断请求上;
  2. 找到GIC中断,填充GIC中断寄存器基地址和一些相关信息;
  3. 找到定时器中断源,填充定时器中断寄存器基地址和一些相关信息;
  4. 将定时器中断映射到定时器中断的中断服务函数上;
  5. 时能GIC中断;
  6. 时能中断向量表和中断向量表的映射;

第二,定时器外设的初始化:

  1. 找到定时器外设,填充定时器外设寄存器基地址和一些相关信息;
  2. 定时器外设自检;
  3. 加载定时器定时时间;
  4. 使能自动重加载功能;
  5. 时能定时器外设中断;
  6. 开始定时器;
  7. 编写定时器中断服务函数;

初始化GIC源码:

void Init_GIC_Timer(void)

{

      XScuGic_Config *IntcConfig;

      //1,GIC的初始化

      //connect to hardware

      Xil_ExceptionInit();

      Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,

                                      (Xil_ExceptionHandler)XScuGic_InterruptHandler,

                                      (void *)&Intc);

      //find device

      IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);

      //config XScuGic data

      XScuGic_CfgInitialize(&Intc, IntcConfig,IntcConfig->CpuBaseAddress);

      //GIC connect to handler

      XScuGic_Connect(&Intc, TIMER_IRPT_INTR,(Xil_ExceptionHandler)TimerIntrHandler,(void*)&Timer);

      //enable xscugic

      XScuGic_Enable(&Intc,TIMER_IRPT_INTR);

 

      //enable exception

      Xil_ExceptionEnable();

      Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

}

定时器外设初始化源码:

void Init_Timer(void)

{

      XScuTimer_Config *TMRConfigPtr;

    //2,私有定时器初始化

      //find device

      TMRConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);

      //config XScuTimer data

     XScuTimer_CfgInitialize(&Timer,TMRConfigPtr,TMRConfigPtr->BaseAddr);

      //self test

      XScuTimer_SelfTest(&Timer);

      //loader value

      XScuTimer_LoadTimer(&Timer,TIMER_LOAD_VALUE);

      //enable auto reload

      XScuTimer_EnableAutoReload(&Timer);

      //enable interrupt

      XScuTimer_EnableInterrupt(&Timer);

      //start timer

      XScuTimer_Start(&Timer);

}

定时器中断服务函数源码:

void TimerIntrHandler(void *CallBackRef)

{

      static int sec = 0;

      XScuTimer* TimerInstancePtr = (XScuTimer*)CallBackRef;

      XScuTimer_ClearInterruptStatus(TimerInstancePtr);

      sec++;

      printf("%d Second\n\r",sec);

}