garfield

基于cw10的kinetis中断程序编写

0
阅读(3176)

中断是用以提高计算机工作效率、增强计算机功能的一项重要技术。当中断事件发生时,CPU停止当前程序的执行,保存现场,转向执行中断服务程序。中断服务程序执行完毕再恢复现场,回到断点处继续执行。

在这套机制中,最重要的是当中断事件发生时,是谁发出了中断信号?和它对应的中断服务程序的入口地址在哪里?

在每个CPU中,对不同的中断源都赋予了一个中断请求号,即IRQ号,每个IRQ都对应一个中断向量号。所谓中断

向量,即该中断的服务程序的入口地址。

对于Kinetis芯片而言,在其数据手册中,有详细说明。以kinetis10,144脚芯片为例,其数据手册K10P144M100SF2RM.pdf 67页即列出了所有中断的IRQ和中断向量。clip_image002

clip_image004

clip_image006

clip_image008

clip_image010

查到你要用的中断的IRQ号和中断向量号以后,接下来就可以对相关模块初始化并编写中断服务程序了。

1. 首先,需要设置相关模块,在指定事件发生后,发出中断请求信号,即中断使能。

每个模块都有相关的寄存器设置,比如DMA模块,希望在DMA传送主循环MAJORLOOP完成后发出中断请求,即可设置DMA_TCD0_CSR|=DMA_CSR_INTMAJOR_MASK;//使能DMA0中断

不同的模块设置的寄存器也不同,这点可详细查看数据手册。

2. 接下来就要设置NVIC模块。NVIC是kinetis芯片的中断控制模块,必须使能对应的NVIC模块对应的IRQ,NVIC模块才会响应对应的中断请求。

K10的中断由专门的嵌套向量中断控制器管理,称为NVIC。

clip_image012

各中断源中断向量号、地址、IRQ号参考K10P144M100SF2RM.pdf第67页。

注意:中断向量号和IRQ号不同,中断向量号=IRQ号+16,因为有16个ARM核心中断是不需要IRQ号的。

要设置IRQ,有以下几个寄存器会用到:

NVICISERx;中断使能寄存器

NVICICERx;中断清除使能寄存器

NVICISPRx;中断设置挂起寄存器

NVICICPRx;中断清除挂起寄存器

NVICIABRx;中断激活寄存器

NVICIPRx;中断优先级寄存器

每种寄存器都是一个寄存器组,要设置对应的IRQ,必须要搞清楚IRQ号对应相关寄存器组中的哪一个,以PIT0定时中断为例,查表得(K10P144M100SF2RM.pdf第70页)

clip_image014

PIT0中断入口地址0x0000_0150,中断向量号84,IRQ号68,非优先级寄存器号2,优先级寄存器号17。

IRQ号和对应寄存器号的关系为:

对于非优先级寄存器,主要是NVICISER, NVICICER, NVICISPR, NVICICPR, NVICIABR

寄存器号=IRQ号/32;

以PIT0为例,IRQ/32=2,即跟PIT0有关的非优先级寄存器主要是NVICISER2, NVICICER2, NVICISPR2, NVICICPR2, NVICIABR2。

对于优先级寄存器,即NVICIPR

寄存器号=IRQ号/4;

以PIT0为例,IRQ/4=17,跟PIT0有关的优先级寄存器为NVICIPR17。

对于非优先级寄存器,每个IRQ都有一个对应的bit,找到对应的寄存器号以后,该bit的位置可如下计算。

位置=IRQ%32

以PIT0为例,PIT0在NVICISER2, NVICICER2, NVICISPR2, NVICICPR2, NVICIABR2寄存器中对应bit位为4。

对于优先级寄存器IPR

设备对各中断有16级优先级可设置,可通过IPR寄存器设置,每个中断源在IPR寄存器中都有对应的4个bit的设置位用来表示优先级。IPR寄存器组从IPR0开始,每个IPR寄存器包含4个可设置的中断源的优先级。以IPR0为例,如图:

clip_image016

每个IRQ的对应优先级寄存器中有关的4个bit的起始位置如下计算:

起始位置= 8 * (IRQ% 4) + 4

以PIT0为例,如要设置优先级,则在NVICIPR17寄存器中的,bit4开始4位设置。

要使能对应的IRQ,主要需要将对应的NVICISERx(中断使能)寄存器中对应位置1,并将对应NVICICPRx(中断清除挂起)寄存器中对应位置1,可用如下代码实现:

void enable_irq (int irq)

{

int div;

if (irq > 91) irq=91; //确定irq号为有效的irq号

div = irq/32; //确定对应的寄存器号

switch (div)

{

case 0x0:

NVICICPR0 = 1 << (irq%32);

NVICISER0 = 1 << (irq%32);

break;

case 0x1:

NVICICPR1 = 1 << (irq%32);

NVICISER1 = 1 << (irq%32);

break;

case 0x2:

NVICICPR2 = 1 << (irq%32);

NVICISER2 = 1 << (irq%32);

break;

}

}

如使能pit0中断,即可调用该函数enable_irq (68);

3. 接下来就可以编写中断服务程序了,程序名自定,可放在main函数所在的文件,也可以单独放在一个文件中。

如PIT0为例

voidpit0_isr(void)

{

uint32 c;

PIT_TFLG0=PIT_TFLG_TIF_MASK;

GPIOA_PTOR=0X0003E000;

c=PIT_CVAL0;

}

4. 最后就是需要定义中断向量表,也就是让中断控制器知道,中断服务程序的入口地址在哪儿

以cw10为例,打开对应工程下的\Project_Settings\Startup_Code文件夹中的kinetis_sysinit.c文件

将中断服务程序再这里做一个定义。还是以pit0为例

extern pit0_isr(void);

然后找到,该文件最后找到中断向量84对应的位置,并加入自己的定义的中断服务函数。

(tIsrFunc)UNASSIGNED_ISR, /* 83 (0x0000014C) (prior: -) */

(tIsrFunc)pit0_isr, /* 84 (0x00000150) (prior: -) */

(tIsrFunc)UNASSIGNED_ISR, /* 85 (0x00000154) (prior: -) */

在这里需要注意,kinetis_sysinit.c文件的编码若是GBK则不让修该,可改为ISO-8859-1即可修改。

Baidu
map