0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ARM Cortex-M内核MCU的三重中断控制设计

Dp1040 来源: 痞子衡嵌入式 2023-10-31 11:04 次阅读

我们知道在 MCU 裸机中程序代码之所以能完成多任务并行实时处理功能,其实主要是靠中断来调度的,没有中断,CPU 就只能按顺序"呆板"地执行代码。很多人都说是中断能力赋予了 MCU 真正的灵魂,能正确认识和熟练使用 MCU 中断,基本上就算玩熟了这颗 MCU。

之前写过一篇《中断处理函数(IRQHandler)的标准流程》,里面详细讲了中断处理函数里的标准代码流程与写法,这篇文章可让大家对 MCU 里的中断用法有个初步认识。今天以 ARM Cortex-M 内核 MCU 为例再来介绍下业界标准的三重中断控制设计:

一、外设事件中断控制

MCU 中最底层的中断控制针对的是外设里某个具体的事件,这个控制来自于外设模块本身,以恩智浦 i.MXRT 系列 MCU 的 GPT 定时器模块为例。如下是 GPT 模块寄存器列表,你可以发现其中有经典的 IR 和 SR 寄存器,SR 是事件状态寄存器,IR 是中断事件控制寄存器:

a5214dae-7799-11ee-939d-92fbcf53809c.png


GPT 定时器一旦被使能,其运行状态(一共支持 6 个事件:超时、输入捕获 x 2ch、比较输出 x 3ch)都会实时记录在 SR 寄存器中,如果不在 IR 寄存器中将事件中断开启(默认是关闭的),那么就需要用户在代码里手动去查询 SR 寄存器置起的事件标志位以处理对应事件。

Note:SR 寄存器中置起的事件标志位需要在事件处理前手动清除掉。如果标志位不及时清除,可能会遗漏下一次事件的处理(比如先处理当前事件,后清除事件标志位,那么处理事件期间再次发生的事件就会被漏掉)。如果标志位忘了清除,同一次事件就会被处理两次及以上。

当然在实际应用中,为了节省 CPU 带宽,我们都是要开启外设事件中断的,MCU 厂商 SDK 包里一般都会提供相应接口函数(取自 fsl_gpt.h):

typedefenum_gpt_interrupt_enable
{
kGPT_OutputCompare1InterruptEnable=GPT_IR_OF1IE_MASK,
kGPT_OutputCompare2InterruptEnable=GPT_IR_OF2IE_MASK,
kGPT_OutputCompare3InterruptEnable=GPT_IR_OF3IE_MASK,
kGPT_InputCapture1InterruptEnable=GPT_IR_IF1IE_MASK,
kGPT_InputCapture2InterruptEnable=GPT_IR_IF2IE_MASK,
kGPT_RollOverFlagInterruptEnable=GPT_IR_ROVIE_MASK,
}gpt_interrupt_enable_t;

//开启GPTx的xx事件中断
staticinlinevoidGPT_EnableInterrupts(GPT_Type*base,uint32_tmask)
{
base->IR|=mask;
}

//关闭GPTx的xx事件中断
staticinlinevoidGPT_DisableInterrupts(GPT_Type*base,uint32_tmask)
{
base->IR&=~mask;
}

使能 GPT1 的超时事件中断代码示例如下:

voidperiph_int_config(void)
{
//初始化GPT1...
GPT_Init(GPT1,&gptConfig);
//...

//开启GPT1的超时事件中断
GPT_EnableInterrupts(GPT1,kGPT_RollOverFlagInterruptEnable);
}

二、外设全局中断控制

MCU 中第二层的中断控制针对的是整个外设,这个控制来自于 Cortex-M 内核的 NVIC 模块。如下是 NVIC 模块寄存器列表(取自 ARMv8-M 手册,除了 IABRn 和 ITNSn 寄存器组外,其余寄存器适用全部的 Cortex-M 家族),其中跟中断开关相关的是 ISER 和 ICER 寄存器:

a52dcef8-7799-11ee-939d-92fbcf53809c.png

当 MCU 中某外设(比如上一节里的 GPT)被使能后,即使其内部事件中断已被开启,也不意味着系统中断一定会被触发,因为 NVIC 里对于这个外设的全局中断开关(同一外设中所有事件共享一个系统中断资源,即一个中断号)还没有开启。ARM CMSIS 包里提供了外设全局中断控制函数(取自 core_cm7.h 文件):

#defineNVIC_EnableIRQ__NVIC_EnableIRQ
#defineNVIC_DisableIRQ__NVIC_DisableIRQ

//开启xx外设的全局中断
__STATIC_INLINEvoid__NVIC_EnableIRQ(IRQn_Type IRQn)
{
if((int32_t)(IRQn)>=0)
{
__COMPILER_BARRIER();
NVIC->ISER[(((uint32_t)IRQn)>>5UL)]=(uint32_t)(1UL<< (((uint32_t)IRQn)&0x1FUL));
__COMPILER_BARRIER();
}
}

//关闭xx外设的全局中断
__STATIC_INLINEvoid__NVIC_DisableIRQ(IRQn_Type IRQn)
{
if((int32_t)(IRQn)>=0)
{
NVIC->ICER[(((uint32_t)IRQn)>>5UL)]=(uint32_t)(1UL<< (((uint32_t)IRQn)&0x1FUL));
__DSB();
__ISB();
}
}

增加了使能 GPT1 的全局中断代码示例如下,其中 GPT1_IRQn 和 GPT1_IRQHandler 是固定名字,在 MCU 厂商提供的头文件(MIMXRT1176_cm7.h)和启动文件(startup_MIMXRT1176_cm7.s)里有定义。

voidperiph_int_config(void)
{
//初始化GPT1...
GPT_Init(GPT1,&gptConfig);
//...

//开启GPT1的超时事件中断
GPT_EnableInterrupts(GPT1,kGPT_RollOverFlagInterruptEnable);

//开启GPT1的全局中断
NVIC_EnableIRQ(GPT1_IRQn);
}

//GPT1的中断响应函数
voidGPT1_IRQHandler(void)
{
GPT_ClearStatusFlags(GPT1,kGPT_RollOverFlagInterruptEnable);

//中断业务处理代码
}

三、系统全局中断控制

MCU 中最顶层的中断控制针对的是整个芯片系统,这个控制来自于 Cortex-M 内核的 CPS 指令。如下是 CPS 指令用法(取自 ARMv7-M 手册):

a542a7e2-7799-11ee-939d-92fbcf53809c.png

当你想对 MCU 整个芯片的所有中断进行统一开关控制时,就必须借助 CPS 指令。一般情况下开启芯片系统全局中断动作在 MCU 启动文件里已经做好了,所以在用户代码环境里常常不需要使能系统全局中断的动作。如下是 IAR 环境下 i.MXRT1170 启动文件中系统全局中断操作,基于汇编指令实现:

a54d51a6-7799-11ee-939d-92fbcf53809c.png

为了便于用户在 C 代码中操作系统全局中断,各 IDE 下均按同样的接口函数( __disable_irq / __enable_irq )做了封装实现。IAR 环境见 IAR SystemsEmbedded Workbench 8.50.6armincciccarm_builtin.h 文件,但是封装进其 Lib 了,没有暴露源码:

#include"iccarm_builtin.h"

#define__disable_irq__iar_builtin_disable_interrupt
#define__enable_irq__iar_builtin_enable_interrupt

Keil 环境见 Keil_v5ARMARMCLANGincludearm_compat.h 文件,我们可以看到源码:

static__inline__unsignedint__attribute__((__always_inline__,__nodebug__))
__disable_irq(void){
unsignedintcpsr;
#if__ARM_ARCH>=6
#ifdefined(__ARM_ARCH_PROFILE)&&__ARM_ARCH_PROFILE=='M'
__asm__ __volatile__("mrs%[cpsr],primask
"
"cpsid i
"
:[cpsr]"=r"(cpsr));
returncpsr&0x1;
#endif
#endif
}

static__inline__void__attribute__((__always_inline__,__nodebug__))
__enable_irq(void){
#if__ARM_ARCH>=6
__asm__ __volatile__("cpsie i");
#endif
}

最终 GPT 例程里完整的三重中断使能代码应如下:

voidperiph_int_config(void)
{
//初始化GPT1...
GPT_Init(GPT1,&gptConfig);
//...

//开启GPT1的超时事件中断
GPT_EnableInterrupts(GPT1,kGPT_RollOverFlagInterruptEnable);

//开启GPT1的全局中断
NVIC_EnableIRQ(GPT1_IRQn);

//开启芯片系统全局中断
__enable_irq();
}
本文转载自痞子衡嵌入式

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    17123

    浏览量

    350983
  • 嵌入式
    +关注

    关注

    5082

    文章

    19104

    浏览量

    304804
  • 寄存器
    +关注

    关注

    31

    文章

    5336

    浏览量

    120230
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10854

    浏览量

    211578
  • 中断
    +关注

    关注

    5

    文章

    898

    浏览量

    41470

原文标题:嵌入式MCU中标准的三重中断控制设计

文章出处:【微信号:玩点嵌入式,微信公众号:玩点嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    怎么实现嵌入式MCU中标准的三重中断控制设计?

    怎么实现嵌入式MCU中标准的三重中断控制设计?
    发表于 11-29 06:02

    ARM Cortex-M内核的相关资料推荐

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是ARM Cortex-M功能模块,不过侧重点是款安全特性处理器。  ARM C
    发表于 12-27 07:21

    Arm 10款 Cortex-M系列MCU内核对比

    MCU出现的历史并不长,但其发展非常迅速。就目前来说,第方的MCU内核中,占主导地位的是Arm Cor
    发表于 07-29 11:30

    方的MCU内核中,Arm Cortex M系列为什么占主导地位

    MCU出现的历史并不长,但其发展非常迅速。就目前来说,第方的MCU内核中,占主导地位的是Arm Cor
    发表于 07-29 11:33

    干货:对比看看Arm推出的10款Cortex-M系列MCU内核IP

    。公司产品被广泛应用于电动车、无人机、智能家居、GPS模块、打印控制、运动控制和人工智能等领域。核心团队拥有超过20年的MCU产品研发经验。公司核心产品是基于ARM
    发表于 07-29 11:35

    国内MCU厂商90%都采用的ArmCortex-M系列内核,优点在哪?

    MCU出现的历史并不长,但其发展非常迅速。就目前来说,第方的MCU内核中,占主导地位的是Arm Cor
    发表于 07-29 11:37

    ARM Cortex-M 系列微控制器(ST)

    ARM Cortex-M 系列微控制器(ST) 意法半导体(ST)宣布在基于ARM Cortex-M系列处理器
    发表于 11-02 09:29 951次阅读

    传统的单片机和ARM较量 助推MCU踏上高端Cortex-M市场

    据有关市场调研机构称,基于ARM Cortex-M内核MCU在2010年创纪录地实现了100%的出货量增长。而整个MCU市场才增长了37%
    发表于 04-28 10:00 1611次阅读

    mcookie与单片机的关系_使用ARM Cortex-M MCU拓展单片机教学

    mcookie与单片机的关系_使用ARM Cortex-M MCU拓展单片机教学
    发表于 11-30 19:36 9次下载
    mcookie与单片机的关系_使用<b class='flag-5'>ARM</b> <b class='flag-5'>Cortex-M</b> <b class='flag-5'>MCU</b>拓展单片机教学

    一点理解之 CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库

    一点理解之 CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库
    发表于 11-30 19:51 10次下载
    一点理解之 CmBacktrace: <b class='flag-5'>ARM</b> <b class='flag-5'>Cortex-M</b> 系列 <b class='flag-5'>MCU</b> 错误追踪库

    Cortex-M中断及FreeRTOS中断优先级配置原理

    下面就来说说关于Cortex-M中断,及FreeRTOS中断优先级配置原理。
    发表于 02-08 15:30 3次下载
    <b class='flag-5'>Cortex-M</b><b class='flag-5'>中断</b>及FreeRTOS<b class='flag-5'>中断</b>优先级配置原理

    分析ARM Cortex-M内核复位启动过程

    ARM Cortex-M内核的复位启动过程也被称为复位序列(Reset sequence),下面就来简要总结分析下这一过程。
    的头像 发表于 03-20 09:58 2360次阅读

    基于32位Arm Cortex-M内核N32系列MCU应用

    国民技术N32系列MCU产品基于32位Arm Cortex-M内核,内置嵌入式高速闪存、低功耗电源管理,集成数模混合电路,并内置硬件密码算法加速引擎以及安全单元。
    发表于 03-28 11:35 890次阅读

    Cortex-M 内核中断/异常系统、中断优先级/嵌套 详解

    Cortex-M 内核中断/异常系统、中断优先级/嵌套 详解
    的头像 发表于 09-27 15:29 2177次阅读
    <b class='flag-5'>Cortex-M</b> <b class='flag-5'>内核</b><b class='flag-5'>中断</b>/异常系统、<b class='flag-5'>中断</b>优先级/嵌套 详解

    瑞萨Cortex-M内核RA MCU的RT-Thread BSP制作教程发布

    瑞萨Cortex-M内核RA MCU的RT-Thread BSP制作教程发布
    的头像 发表于 09-18 10:58 708次阅读
    瑞萨<b class='flag-5'>Cortex-M</b><b class='flag-5'>内核</b>RA <b class='flag-5'>MCU</b>的RT-Thread BSP制作教程发布