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

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

3天内不再提示

控制IRQ和FIQ中断的编译器内部函数 基于Keil MDK

黄工的嵌入式技术圈 来源:黄工的嵌入式技术圈 作者:黄工的嵌入式技术 2020-02-29 16:45 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

本文是一篇偏向底层的内容。

1.写在前面

编译器内部函数__disable_irq、__enable_irq、__disable_fiq和__enable_fiq用于控制IRQ和FIQ中断。

只有当处理器处于特权模式才可以使用这些内部函数,因为这些函数要改变寄存器CPSR和SPSR(ARM7、ARM9等)或者PRIMASK和FAULTMASK寄存器(Cortex-M3、M4等),而这些寄存器只有在特权模式下才能被访问。

这些内部函数对所有架构的处理器都有效,无论是ARM状态还是Thumb状态,如下所述:

如果使用的是ARMv6(ARM11)或更新架构,编译器会将这些函数用CPS指令代替。

如果使用的是ARMv4或者ARMv5架构并且处于ARM状态,编译器会将这些函数用MRS和MSR指令代替。一般情况下ARM7属于ARMv4架构,ARM9属于ARMv5架构。

如果使用的是ARMv4或者ARMv5架构并且处于Thumb状态或编译器使能-compatible参数,则编译器会调用一个辅助函数比如__ARM_disable_irq来控制中断。

2.__enable_fiq使能FIQ中断

通常是通过清除寄存器CPSR中的F位来实现的。

注意FIQ中断一般只存在于ARMv4和ARMv5架构中(即ARM7和ARM9),ARMv6架构的处理器不支持此函数。

对于ARMv7架构的处理器(Cortex-M3),这个函数清除FAULTMASK寄存器的值。

语法:void __enable_fiq(void)

限制:只能在特权级别下使用,用户模式下无效。

3.__disable_fiq禁用FIQ中断

通常是通过置一CPSR的F位来实现的。

注意FIQ中断一般只存在于ARMv4和ARMv5架构中(即ARM7和ARM9),ARMv6架构的处理器不支持此函数。

对于ARMv7架构的处理器(Cortex-M3),这个函数置位FAULTMASK寄存器,这意味着此后只有NMI可以响应,所有其它的异常,包括中断和 Fault都不能响应。

语法:__disable_fiq有两个版本。

一个是返回值为空的void __disable_fiq(void)

另一个返回值为整形值的int __disable_fiq(void)

用法:int __disable_fiq(void),禁止FIQ中断(ARMv4和ARMv5)或禁用除NMI之外的所有中断(ARMv7)。

在禁用中断前,将中断使能状态返回。

void __disable_fiq(void),禁用FIQ中断(ARMv4和ARMv5)或禁用除NMI之外的所有中断(ARMv7)。

限制:只能在特权级别下使用,用户模式下无效。

如果编译器参数设置为-cpu=7,则不支持int __disable_fiq(void)函数,这是因为通用ARMv7架构和ARMv7 R及ARMv7 M-profiles架构的异常处理模式不同所导致的。

这意味着如果编译器参数设置为-cpu=7,编译器不能为int __disable_fiq(void)函数产生所有ARMv7架构通用的指令序列,此时只能使用void __disable_fiq(void)。

举例:

void func(void){ int was_masked = __disable_fiq(); /*其它处理*/ if(!was_masked) { __enable_fiq(); }}

为什么例子中要使用变量was_masked获取之前的中断使能信息,并且在使能中断时还要先判断这个变量?

直接使用__disable_fiq()和__enable_fiq()函数不是更简单吗?

这是因为如果之前系统的中断已经是关闭的,当你直接使用__enable_fiq()函数就会无条件打开中断,这样可能是很危险的。所以在打开中断前,要检查之前中断是不是已经是禁止状态,如果是的话就不要使能中断。

4.__enable_irq使能IRQ中断

对于ARMv4和ARMv5架构(ARM7和ARM9),编译器插入下列指令清除CPSR寄存器的I位。

MRS r0, CPSRAND r0, r0, #0x7FMSR CPSR_c, r0

对于ARMv6(ARM11)和ARMv7(Cortex-M3等)指令,编译器插入下列指令使能中断:

CPSIE I

比如Cortex-M3架构处理器,该指令清除PRIMASK寄存器,使能中断。

语法:void __enable_irq(void)

限制:只能在特权级别下使用,用户模式下无效。

5. __disable_irq禁止IRQ中断

对于ARMv4和ARMv5架构(ARM7和ARM9),编译器插入下列指令置位CPSR寄存器的I位。

MRS r0, CPSRORR r0, r0, #0x80MSR CPSR_c, r0

对于ARMv6(ARM11)和ARMv7(Cortex-M3等)指令,编译器插入下列指令禁用中断:

CPSID I

比如Cortex-M3架构处理器,该指令置位PRIMASK寄存器,表示禁止中断和可屏蔽的异常,只剩下NMI和硬Fault可以响应。

__disable_irq函数有两种形式,返回值为空的void __disable_irq(void)和返回值为整形数的int __disable_irq(void)。

前者直接禁用中断,后者在禁用中断前,将中断使能状态返回。

举例:

void func(void){ int was_masked = __disable_irq(); /*其它处理*/ if(!was_masked) { __enable_irq(); }}

为什么例子中要使用变量was_masked获取之前的中断使能信息,并且在使能中断时还要先判断这个变量?

直接使用__disable_irq()和__enable_irq()函数不是更简单吗?

这是因为如果之前系统的中断已经是关闭的,当你直接使用__enable_irq()函数就会无条件打开中断,这样可能是很危险的。

所以在打开中断前,要检查之前中断是不是已经是禁止状态,如果是的话就不要使能中断。

限制:只能在特权级别下使用,用户模式下无效。

如果编译器参数设置为-cpu=7,则不支持int __disable_irq(void)函数,这是因为通用ARMv7架构和ARMv7 R及ARMv7 M-profiles架构的异常处理模式不同所导致的。

这意味着如果编译器参数设置为-cpu=7,编译器不能为int __disable_irq(void)函数产生所有ARMv7架构通用的指令序列.

此时只能使用void __disable_irq(void)。

我们再从汇编层面上看一下返回整形数的__disable_irq:

int disable_irq(void){ return __disable_irq();}

在-cpu=Cortex-M3时,Keil MDK编译器产生的汇编代码为:

MRS r0, PRIMASKAND r0, r0, #1CPSID iBX lr

6.这些函数有什么用处?

保护共享资源

禁止中断嵌套

保护共享资源很好理解,但禁止中断嵌套可能很多人不理解。

中断嵌套可以提高系统响应时间,为什么要禁用掉?

虽然中断嵌套能提高响应时间,但绝大多数的应用并不需要如此高的响应时间;

更重要的是,中断嵌套增加了程序运行的不确定性。所以我建议在不需要极致的响应时间使,禁止中断嵌套。

方法也很简单,在进入中断服务函数后和退出中断服务函数前中调用本文讲的这些中断控制函数即可。

7.移植性

与编译器特性相关,不具备移植性,建议使用前先用宏进行封装。

来源:https://blog.csdn.net/zhzht19861011/article/details/52815488

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

    关注

    0

    文章

    17

    浏览量

    11599
  • 编译器
    +关注

    关注

    1

    文章

    1672

    浏览量

    51913
  • FIQ
    FIQ
    +关注

    关注

    0

    文章

    9

    浏览量

    2524
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    使用 Keil Studio for Visual Studio Code开发 STM32 设备

    与业界工具的无缝集成、版本控制支持,以及用于 CI 工作流的命令行接口(CLI)。 Keil Studio 作为 Arm Keil MDK 6的一部分,为基于 CortexM 的微
    的头像 发表于 03-05 17:41 4210次阅读
    使用 <b class='flag-5'>Keil</b> Studio for Visual Studio Code开发 STM32 设备

    C编译器错误与解决方法

    C语言keil编译器提示错误的解决方法,可以帮你解决程序编译中的烦恼!! C编译器错误与解决方法 1. Warning 280:’i’:unreferenced local var
    发表于 01-22 08:03

    在ADS编译器中,用标准的C库函数printf()需要哪些设置呢?

    在ADS编译器中,用标准的C库函数printf()需要哪些设置呢?又在哪儿可以看到printf()输出的信息呢?
    发表于 12-23 07:32

    开源鸿蒙技术大会2025丨编译器与编程语言分论坛:语言驱动系统创新,编译赋能生态繁荣

    在万物智联的时代背景下,操作系统底层能力的构建离不开编程语言与编译器的关键支撑。作为开源鸿蒙生态的核心技术,语言设计与编译器、虚拟机实现的进步直接关系到开发效率、运行性能与系统安全。本次分论坛聚焦
    的头像 发表于 11-20 17:24 1166次阅读
    开源鸿蒙技术大会2025丨<b class='flag-5'>编译器</b>与编程语言分论坛:语言驱动系统创新,<b class='flag-5'>编译</b>赋能生态繁荣

    请问Keil的优化等级到底该如何选择?

    Keil MDK(Microcontroller Development Kit)中,优化等级是编译器的核心设置之一,它直接影响生成代码的大小、执行速度和调试便利性。选择合适的优化等级是平衡性
    发表于 11-20 07:51

    RVMCU课堂「10」: 手把手教你玩转RVSTAR—处理内部中断

    /application/baremetal/demo_timer/main.c 其中,main函数调用的“ECLIC_Register_IRQ函数就是中断配置
    发表于 10-31 06:12

    GCC编译器,怎么才能实现c文件中未被调用的函数,不会被编译呢?

    GCC编译器,怎么才能实现c文件中未被调用的函数,不会被编译?有什么编译选项可以设置吗? 移植代码,有些函数没被调用的
    发表于 09-28 12:25

    scons --target=mdk5编译不成功如何解决?

    使用scons —target=mdk5编译不成功,报错如下: scons --target=mdk5 scons: Reading SConscript files ... UV4.exe
    发表于 09-26 07:20

    瑞萨RA系列MCU的中断过程介绍

    中断来临的时候会最先经过IRQ寄存IRQ寄存检测到中断的时候,会向中央处理嵌套向量
    的头像 发表于 09-23 09:45 1521次阅读
    瑞萨RA系列MCU的<b class='flag-5'>中断</b>过程介绍

    rt_list_for_each_entry编译失败怎么解决?

    最新版本的rtthread,做SDIO模式的SD卡,里面包含了blk.C文件,文件里有多个rt_list_for_each_entry,我用的是keil mdk AC6,编译报错 全局搜索了一下
    发表于 09-18 07:14

    请问如何在keil μVision 5上进行ARM编译器的代码优化?

    如何在keil μVision 5上进行ARM编译器的代码优化?
    发表于 08-20 07:37

    如何在Keil中将NuMicro BSP从Arm编译器5迁移到编译器6?

    Keil中将NuMicro BSP从Arm编译器5迁移到编译器6!
    发表于 08-20 06:29

    边缘设备AI部署:编译器如何实现轻量化与高性能?

    电子发烧友网综合报道 AI编译器是专门为人工智能(AI)和机器学习(ML)模型设计的编译器,其核心目标是将高级的AI模型描述(如计算图、神经网络结构)转换为特定硬件平台(如CPU、GPU、FPGA
    的头像 发表于 07-06 05:49 6937次阅读

    兆松科技ZCC编译器全面支持芯来科技NA系列处理

    近日,兆松科技(武汉)有限公司(以下简称“兆松科技”)宣布正式发布高性能RISC-V编译器ZCC 4.0.0版本。
    的头像 发表于 06-11 09:56 2009次阅读

    RVCT编译器是否比GNU的编译器的代码执行速度更快?

    使用FX3S遇到了RVCT编译器的问题。 1、在SDK的release note中有支持RVCT的描述, 但是在EZ USB Suite的设置中没有找到RVCT的选项, 请问支持的具体版本
    发表于 05-08 07:49