Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现

这篇具有很好参考价值的文章主要介绍了Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

0 工具准备

Keil uVision5
Cortex M3权威指南(中文)
Cortex M3与M4权威指南
stm32f407的HAL库工程
STM32F4xx中文参考手册

1 HAL库中断底层函数实现

打开stm32f407的HAL库工程,可以在CMSIS->Include->core_cm4.h内找到有关NVIC寄存器设置的相关函数:

  #define NVIC_SetPriorityGrouping    __NVIC_SetPriorityGrouping
  #define NVIC_GetPriorityGrouping    __NVIC_GetPriorityGrouping
  #define NVIC_EnableIRQ              __NVIC_EnableIRQ
  #define NVIC_GetEnableIRQ           __NVIC_GetEnableIRQ
  #define NVIC_DisableIRQ             __NVIC_DisableIRQ
  #define NVIC_GetPendingIRQ          __NVIC_GetPendingIRQ
  #define NVIC_SetPendingIRQ          __NVIC_SetPendingIRQ
  #define NVIC_ClearPendingIRQ        __NVIC_ClearPendingIRQ
  #define NVIC_GetActive              __NVIC_GetActive
  #define NVIC_SetPriority            __NVIC_SetPriority
  #define NVIC_GetPriority            __NVIC_GetPriority
  #define NVIC_SystemReset            __NVIC_SystemReset
  #define NVIC_SetVector              __NVIC_SetVector
  #define NVIC_GetVector              __NVIC_GetVector

1.1 __NVIC_SetPriorityGrouping(设置优先级分组)函数

__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
  uint32_t reg_value;
  uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL);             /* only values 0..7 are used          */

  reg_value  =  SCB->AIRCR;                                                   /* read old register configuration    */
  reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change               */
  reg_value  =  (reg_value                                   |
                ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
                (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos)  );              /* Insert write key and priority group */
  SCB->AIRCR =  reg_value;
}

该函数操作步骤如下:
(1)读取SCB->AIRCR旧值,保存到reg_value
(2)将reg_value的bit31-16(访问钥匙)、bit10-8(优先级分组)设置为0
(3)将reg_value的bit31-16(访问钥匙)设置为0x05FA,同时将优先级分组值写到bit10-8(优先级分组)
(4)将SCB->AIRCR的值设置为reg_value
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.2 __NVIC_GetPriorityGrouping(获取优先级分组)函数

__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
{
  return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
}

这个函数读取SCB->AIRCR的bit10-bit8获取优先级分组设置的值。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.3 __NVIC_EnableIRQ(使能中断请求)函数

__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
  }
}

该函数通过中断请求编号得到在其在中断使能寄存器中的对应位,然后将该位置1使能中断。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.4 __NVIC_GetEnableIRQ(获取中断请求使能状态)函数

__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
  }
  else
  {
    return(0U);
  }
}

该函数通过中断请求编号得到在其在中断使能寄存器中的对应位,然后读取对应位的值并返回。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.5 __NVIC_DisableIRQ(失能中断请求)函数

__STATIC_INLINE void __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();
  }
}

该函数通过中断请求编号得到在其在中断失能寄存器中的对应位,然后将该位置1失能中断。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库
这里还有__DSB()、__ISB()这2个函数,分别是数据同步屏障、指令同步屏障,目的是保证前面对寄存器的操作被执行完成。

1.6 __NVIC_GetPendingIRQ(获取中断请求挂起状态)函数

__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
  }
  else
  {
    return(0U);
  }
}

该函数通过中断请求编号得到在其在中断挂起寄存器中的对应位,然后返回对应位的值。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.7 __NVIC_SetPendingIRQ(设置中断请求挂起状态)函数

__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
  }
}

该函数通过中断请求编号得到在其在中断挂起寄存器中的对应位,然后设置对应位为1。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.8 __NVIC_ClearPendingIRQ(清除中断请求挂起)函数

__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
  }
}

该函数通过中断请求编号得到在其在中断解挂寄存器中的对应位,然后设置对应位为1。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.9 __NVIC_GetActive(获取中断激活状态)函数

__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
  }
  else
  {
    return(0U);
  }
}

该函数通过中断请求编号得到在其在中断激活寄存器中的对应位,然后读取并返回对应位的值。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.20 __NVIC_SetPriority(设置中断优先级)函数

__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if ((int32_t)(IRQn) >= 0)
  {
    NVIC->IP[((uint32_t)IRQn)]               = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
  else
  {
    SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
}

该函数可以分为外部中断和系统异常2个部分:
(1)外部中断(中断请求序号≥0)
通过中断请求编号找到对应的中断优先级寄存器,然后设置中断优先级寄存器即可。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库
注:stm32f407仅使用高4bit设置中断优先级
(2)系统异常(中断请求序号<0)
通过系统异常请求编号找到对应的异常优先级寄存器,然后设置系统异常优先级寄存器即可。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库
注:stm32f407仅使用高4bit设置中断优先级

1.21 __NVIC_GetPriority(获取中断优先级)函数

__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{

  if ((int32_t)(IRQn) >= 0)
  {
    return(((uint32_t)NVIC->IP[((uint32_t)IRQn)]               >> (8U - __NVIC_PRIO_BITS)));
  }
  else
  {
    return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
  }
}

该函数可以分为外部中断和系统异常2个部分:
(1)外部中断(中断请求序号≥0)
通过中断请求编号找到对应的中断优先级寄存器,然后读取中断优先级寄存器即可。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库
注:stm32f407的高4bit为中断优先级
(2)系统异常(中断请求序号<0)
通过系统异常请求编号找到对应的异常优先级寄存器,然后读取系统异常优先级寄存器即可。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库
注:stm32f407的高4bit为中断优先级

1.22 __NVIC_SystemReset(系统复位)函数

__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
  __DSB();                                                          /* Ensure all outstanding memory accesses included
                                                                       buffered write are completed before reset */
  SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
                           (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
                            SCB_AIRCR_SYSRESETREQ_Msk    );         /* Keep priority group unchanged */
  __DSB();                                                          /* Ensure completion of memory access */

  for(;;)                                                           /* wait until reset */
  {
    __NOP();
  }
}

系统复位函数实际上就是写AIRCR(应用程序中断及复位控制寄存器)的bit2为1使MCU复位。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.23 __NVIC_SetVector(设置中断向量偏移量)函数

__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
{
  uint32_t *vectors = (uint32_t *)SCB->VTOR;
  vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
}

这个函数实际上就是设置外部中断向量偏移量,用得很少。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库

1.24 __NVIC_GetVector(获取中断向量偏移量)函数

__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
{
  uint32_t *vectors = (uint32_t *)SCB->VTOR;
  return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
}

这个函数实际上就是获取外部中断向量偏移量寄存器的值,用得很少。
相关寄存器如下:
Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现,单片机开发,ARM内核,stm32,ARM,中断,HAL库文章来源地址https://www.toymoban.com/news/detail-809754.html

到了这里,关于Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 中断相关操作函数HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()

    HAL_NVIC_SetPriority() 函数是一个用于 设置中断优先级的函数 ,其定义如下: 其中,参数含义如下: IRQn :指定要设置优先级的中断号,类型为IRQn_Type,定义在stm32f4xx.h头文件中; PreemptPriority :指定抢占优先级,取值范围为0~15,其中0表示最高优先级,15表示最低优先级; SubP

    2024年02月07日
    浏览(34)
  • 【ARM Cortex-M 系列 1.1 -- Cortex-M33 与 M4 差异 详细介绍】

    请阅读 【嵌入式开发学习必备专栏 之 Cortex-Mx 专栏】 在移植 RT-Thread 到 瑞萨RA4M2(Cortex-M33)上时,遇到了hardfault 问题,最后使用了Cortex-M4中的调度相关的函数后,OS 可以正常调度了。所以这里做下 M33与 M4的关系梳理。 ARM Cortex-M33 和 Cortex-M4 都是 ARM 公司设计的32位RISC微处理

    2024年01月21日
    浏览(47)
  • 【ARM Cortex-M 系列 1 -- Cortex-M0, M3, M4, M7, M33 差异】

    请阅读 【ARM Coresight | AMBA BUS| Armv8/v9 | GCC 专栏导读】 下篇文章:ARM Cortex-M 系列 2 – CPU 之 Cortex-M7 介绍 Cortex-M0/M0+ 介绍 Cortex-M0 是 ARM 公司推出的一款微控制器(MCU)核心。这个核心是基于 ARMv6-M 架构设计的, 只支持 56 条指 令的小指令集,大部分指令是 16 位指令, 是 ARM Cor

    2024年02月17日
    浏览(47)
  • 【ARM Cortex-M 系列 1 -- Cortex-M0, M3, M4, M7, M33, M35P 差异】

    请阅读 【ARM Coresight | AMBA BUS| Armv8/v9 | GCC 专栏导读】 下篇文章:ARM Cortex-M 系列 2 – CPU 之 Cortex-M7 介绍 Cortex-M0/M0+ 介绍 Cortex-M0 是 ARM 公司推出的一款微控制器(MCU)核心。这个核心是基于 ARMv6-M 架构设计的, 只支持 56 条指 令的小指令集,大部分指令是 16 位指令, 是 ARM Cor

    2024年02月05日
    浏览(45)
  • ARM Cortex-M3内核

    目录 ARM Cortex-M3内核 存储器系统 外设接口 时钟和电源管理 中断控制器 DMA控制器 STM32F1系列微控制器是一款基于ARM Cortex-M3内核的嵌入式芯片,其架构组成主要包括以下几个方面:  ARM Cortex-M3内核:STM32F1系列微控制器采用了ARM Cortex-M3内核,该内核是一种高性能、低功耗的32位

    2024年02月07日
    浏览(44)
  • ARM Cortex-M 内核调试相关

    推荐博文1: SWD协议通信的简单总结 根据《ARM Technical Reference Manual cortex_m3_r1p1_trm》和《Arm® Debug Interface Architecture Specification ADI v6.0.pdf》进行梳理。 Cortex-M3 处理器实现了ARM v7-M架构。这包括整个 16 位的Thumb指令集和基本的 Thumb-2 32位指令集架构。处理器无法执行ARM指令。 Thumb

    2024年02月03日
    浏览(48)
  • ARM Cortex-M3内核理解

    做一个对社会有用的人!不抱怨,不气馁! 目录 前言 1 ARM处理器家族 2 什么是ARM Cortex-M处理器 2.1 Cortex-M3 2.2 M3处理器到微控制器 2.3 ARM处理器的发展 2.4 Thumb ISA的架构版本 2.4.1 指令集的概念 2.5 软件开发流程  2.5.1 轮询 3、技术综述 3.1、Cortex-M3简介 3.1.1 处理器类型 3.1.2 指令

    2024年02月08日
    浏览(38)
  • 第七章嵌套矢量中断控制器(Cortex-M7 Processor)

    目录   第七章嵌套矢量中断控制器  7.1关于NVIC 7.2NVIC功能描述 7.2.1低功耗模式 7.2.2电平与脉冲中断 7.3NVIC程序员模型  7.3.1中断控制器类型寄存器 本章描述了嵌套矢量中断控制器(NVIC)。它包含以下部分: 关于NVIC在7-2页。 NVIC功能描述见第7-3页。 NVIC程序员模型在第7-4页。 NVIC为

    2024年02月16日
    浏览(40)
  • STM32 HAL库的串口中断服务函数详解

    最近在实现利用上位机通过串口发送指令给下位机执行操作的实验,在之前学习串口的过程中我就一直有一个疑惑,那就是为什么在串口中断回调函数内除了要加上自己的操作以外还要在末尾再执行一次 接收中断 ,在查阅了一些资料后我才发现原来和 中断服务函数 有关 我

    2024年02月10日
    浏览(43)
  • 【ARMv8M Cortex-M33 系列 7.4 -- 如何使能 usagefault | memmange fault | bus fault 中断】

    请阅读 【嵌入式开发学习必备专栏 之 ARM Cortex-Mx专栏】 由于文章【ARMv8M Cortex-M33 系列 7.2 – HardFault 问题定位 1】 中提到了HardFault 的发生是由于其它异常所升级导致的,所以就需要调查下如何是能其它异常中断。 在 ARM Cortex-M33 核心上启用 UsageFault 、 MemManageFault 和 BusFault 异

    2024年01月20日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包