1. 中断概述

1.1 中断响应机制和分类

CPU在进程正常的程序处理的时候,有时候会被要求处理更高需求级别的任务,因此不得不中断当前任务进程,进入中断服务程序。而在处理完这些额外的任务之后,还需要回到之前的任务,因此就需要在进入中断程序之前必须保存现场,以确保在主要任务被打断并完成中断程序之后,能够准确地回到之前的任务节点。

中断请求可以分为:

  • 可屏蔽中断:可通过判断优先级选择是否处理
  • 不可屏蔽中断:强制停止CPU进程,进入中断程序,比如复位和NMI。

中断源也可以分成两类:

  • 片内部中断源:PWM,CAP,QEP,定时器等
  • 片外部中断源:外部中断输入引脚XINT1、XINT2引入的信号

1.2 中断结构

F28335有很多的外设资源,这些外设资源有可能会同时发布额外任务给CPU,换句话说就是F28335的中断源有很多,这些中断源想要得到CPU的响应就必须要中断线传递信号给CPU。可是F28335的中断线数是有限的,这个时候PIE模块来分配中断资源了。

                   

DSPBIOS硬件中断_外部中断

从图中可以看出,

  • 外部中断源均通过PIE模块进行判断处理
  • 内部中断源中定时器1和定时器2单独通过INT13和INT14处理,其他也通过PIE模块处理
  • PIE模块处理INT~INT12
  • 总共16路中断线

2. 中断管理模块PIE

PIE模块作用是在有限中断线的情况下用来管理多个中断源触发。

2.1 PIE模块结构

DSPBIOS硬件中断_中断向量表_02

PIE的结构如上图所示,PIE模块是由多个中断组和每个中断组的多路选择器构成的。从INT1~INT12均为PIE模块管理的可屏蔽中断,而这12个中断每个都由8个外设计中断组成,比如途中INT1.X对应的就是由INT1.1~INT1.8组成,这8个外设级中断就是我们对应的外部中断源引脚。

PIE模块通过一个8选1的多路选择器将这8个外设中断组成一组。我们在程序中配置的时候也是以这个结构为基础来配置的。

补充PIE响应的优先级

  • INT1>INT2>...>INT12
  • INT1.1>INT1.2>...>INT1.8

2.2 PIE模块的响应机制

PIE模块有这么多的外设需要管理,就必定有相应的响应顺序和寄存器需要配置。

在PIE模块内每组中断都有相应的中断标志位(PIEIFRx)和使能位(PIEIERx.y),除此之外,每组PIE中断(INT1~INT12)有一个响应标志位(PIEACK)。下图给出了PIEIFR和PIEIER不同设置时的PIE硬件的操作流程。

DSPBIOS硬件中断_可屏蔽中断_03

一旦PIE控制器有中断产生,相应的中断标志位(PIEIFRx.y)将置1。如果相应的PIE中断使能位也置1,则PIE将检查相应的PIEACKx以确定CPU是否准备响应该中断。如果相应的PIEACKx位清零,PIE向CPU申请中断;如果PIEACKx置1,PIE将等待到相应的PIEACKx清零才向CPU申请中断。PIE通过对PIEACKx的位控制来控制每1组中只有1个中断能被响应,一旦响应后,就需要将PIEACKx响应为清零,以让它能够响应该组中后边过来的中断。

举个例子,如果要使CPU反应INT1.1的中断。

就需要

  • PIEIFR1.1标志位置1
  • PIEIFR1.1使能位置1
  • PIEIFR1.1响应标志位1
  • IFR全局标志位置1(只对INT1~INT12)
  • IER全局中断使能置1(只对INT1~INT12)

2.3 中断向量表

由于F28335各个中断源对应的地址是事先就设定好的,我们无法更改,所以中断向量表必须要备一张。

DSPBIOS硬件中断_外部中断_04

从图中可以看出

  • INT1~INT12每个都对应8个外部中断
  • 总共有96个可响应的资源,有很多富裕的资源

2.4 中断配置的简单实例

中断的配置是与PIE模块的响应机制完全对应的。

对外部中断XINT1进行配置。

第一步:

基础的初始化之后,对PIE模块进行指定,一般在InitPieVectTable();PIE模块初始化之后进行指定。

void main(void)
{
 InitSysCtrl();
 DINT;
 InitPieCtrl();
 IER = 0x0000;
 IFR = 0x0000;
 InitPieVectTable();
 EALLOW;
 PieVectTable.XINT1 = &xint1_isr;
 EDIS;
}

第二步:

打开PIE模块的时钟,经过查询中断向量表知道,外部中断XINT1在使能在INT1.4,打开这个中断使能。

void main(void)
{
 InitSysCtrl();
 DINT;
 InitPieCtrl();
 IER = 0x0000;
 IFR = 0x0000;
 InitPieVectTable();

EALLOW;
PieVectTable.XINT1 = &xint1_isr;   //赋予中断地址
EDIS;
 
IER |= M_INT1;                                   //全局使能INT1
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;     //使能INT1.4
EINT;
ERTM;
 
}

当时我疑惑这个PIEIFR标志位置1去哪里了,其实中断响应的时候它是自动置1的。我们只要开使能使他能够顺利通过就好。
第三步:
就是在我们的中断里面写函数,并在中断里面清楚中断响应标志位PIEACK。

interrupt void xint1_isr(void)
  {
 Xint1Count++;
 GpioDataRegs.GPACLEAR.all = 0x4; 
 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
  }