打印
[Kinetis]

从零入手Kinetis系统开发之中断使用方法

[复制链接]
1614|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Vitality1|  楼主 | 2015-3-22 23:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
对于掌握一款单片机(Coretex-M系列定位就是高端单片机,呵呵,和Cortex-A系列的应用处理器定位是两个档次)来说,其中断机制是必须要掌握的,所以作为一个单片机开发者,编写相应的中断服务程序是最基本的要求之一了。前面提到过,本来在第八篇系列就该写写中断的使用方法了(其实这都算晚了,呵呵),不过那会儿玩TSI玩的正在热头上就趁热打铁的写了TSI模块,以致于拖到现在才开始写中断,哈哈,所以不多说废话了,直接进入正题。
    Kinetis的中断机制其实也即是Cortex-M4核的机制,ARM从Cortex-M3核系列(ARMv7-M架构)开始就引入了嵌套向量中断控制器(NVIC)来管理其中断功能,其主要的特点包括:
(1)可嵌套中断支持,这点不用细说了,几乎大多数内核都支持中断嵌套,不过可能嵌套的级数有些不同;
(2)向量中断支持,Cortex-M系列通过查询中断向量表找到相应的ISR(中断服务程序)入口,并跳转执行;
(3)动态优先级调整,即支持软件运行时改变中断优先级,其实飞思卡尔的HCS12也支持这个,嘿嘿;
(4)中断延迟大大缩短,引入了一些新特性,例如咬尾中断,晚到中断;
(5)中断可屏蔽,支持条件性屏蔽即只屏蔽优先级低于某个阈值的中断,当然也可以屏蔽全部中断了;

相关帖子

沙发
Vitality1|  楼主 | 2015-3-22 23:22 | 只看该作者
Cortex-M核的NVIC最多支持200多个中断(包括系统异常16个和外部中断240个),只不过各大半导体厂商根据自家芯片的资源做了定制。其中前16个中断为系统中断(即核自己的,咱管不着,不过一些场合用的到),咱们主要关心的是IRQ中断(即外部中断,含外设资源),本系列既然主打Kinetis,就以其为例,重点介绍其特点和使用流程,刚刚是补补常识,下面才进入到本篇主角,哈哈:
1.首先介绍飞思卡尔Kinetis系列中断特点:
(1)低中断延迟,从中断发生到进入中断服务程序最多12时钟周期;
(2)最多120个中断,包含16个核中断和剩余的外部IRQ中断;
(3)最多16个可编程优先级;
(4)动态改变优先级;
(5)可重定位向量表,通过写SCB_VTOR寄存器。

使用特权

评论回复
板凳
Vitality1|  楼主 | 2015-3-22 23:22 | 只看该作者
2.按部就班,老套路了,介绍完特点之后,下面细说说要写完整的中断服务程序的流程步骤,擦亮眼睛啦,呵呵,先上个图:

(1)使能外设的中断功能,也就是说打开外设的中断使能位(如果外设支持中断的话),使之与NVIC的中断输入连接;
(2)清除已经挂号发生的中断(避免刚打开即进入,可能造成一些不必要的影响),写NVICICPRx寄存器;
(3)使能相应IRQ中断号在NVIC的中断功能,写NVICISERx寄存器;
(4)配置中断优先级(可选,不设置的话默认,即按照在中断向量表的排序来决定),写NVICIPx;
(5)写相应的中断服务程序(ISR);
(6)使能全局中断EnableInterrupts,其实在启动代码部分已经开启,不过为了稳妥还是再使能一次。
哦了,按照上面6步即可完成相应资源中断功能的实现,so easy吧,呵呵,下面就根据实例来看下具体在程序里是如何实现的吧:

使用特权

评论回复
地板
Vitality1|  楼主 | 2015-3-22 23:22 | 只看该作者
3.该步通过拿出来我以前分享的IAR框架代码来分析下,具体如何实现中断服务机制的,以上篇系列的TSI中断为例,贴代码:
(1)使能相应外设的中断:
    ENABLE_EOR_INT; /* 使能TSI越界中断 */
(2)根据TSI的IRQ中断号,清除已经发生的TSI中断事件,并且使能TSI中断功能,首先在K60的datasheet或者直接到其头文件开始处即可找到中断向量表,查到TSI的IRQ中断号(但是要注意IRQ号=中断向量表号-16(即前16个核中断,它们不是IRQ中断)):

注意图中所示为中断向量表号,IRQ中断号为99-16=83。
然后利用ARM核自带的API函数使能TSI的IRQ中断,如下
    enable_irq(83);  /* 使能TSI的IRQ中断 */
该函数的具体内容如下,注意每个NVICCPRx和NVICISERx都是32字节对齐的,即管理32个IRQ中断,所以要根据TSI实际的中断号算出其具体在哪一个寄存器里设置。
void enable_irq (int irq)
{
    int div;
    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;
    }              
}


使用特权

评论回复
5
Vitality1|  楼主 | 2015-3-22 23:23 | 只看该作者
(3)配置优先级,这一步如果没特殊需要的话可以默认,不设置即可,如果设置的话也可以通过API函数执行,如下
    set_irq_priority (83,5); /* 设置TSI中断优先级为5,注意越小优先级越大 */
(4)编写相应的中断服务函数
/********************************************************************************
**Routine: TSI_isr
**Description: TSI模块,out of Range 中断服务程序,中断服务号为99,IRQ为83
**Notes:
********************************************************************************/
void TSI_isr(void);
然后在写完该中断服务函数之后,我们需要把该中断函数地址映射到中断向量表里面,所以找到isr.h文件打开,设置如下;
    #undef  VECTOR_099  /* 取消原来默认的宏定义 */
    #define VECTOR_099      TSI_isr  /* 重定义中断服务函数名为VECTOR_99*/
(5)使能全局中断
EnableInterrupts; /* 其宏定义为CPSIE i,即设置特殊功能寄存器 */
    完整的中断编写流程如上,喝口水。其中可能有些寄存器和有关NVIC概念和结构之类的建议看看官方文档或者直接到ARM官网下载Cortex-M核的介绍瞅一瞅,相信会让你受益匪浅。



使用特权

评论回复
6
FSL_TICS_ZJJ| | 2015-4-10 14:47 | 只看该作者
非常感谢你关于Kinetis的经验分享 !

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

81

主题

421

帖子

9

粉丝