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

news2024/11/27 0:21:27

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
相关寄存器如下:
在这里插入图片描述

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获取优先级分组设置的值。
相关寄存器如下:
在这里插入图片描述

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使能中断。
相关寄存器如下:
在这里插入图片描述

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);
  }
}

该函数通过中断请求编号得到在其在中断使能寄存器中的对应位,然后读取对应位的值并返回。
相关寄存器如下:
在这里插入图片描述

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失能中断。
相关寄存器如下:
在这里插入图片描述
这里还有__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);
  }
}

该函数通过中断请求编号得到在其在中断挂起寄存器中的对应位,然后返回对应位的值。
相关寄存器如下:
在这里插入图片描述

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。
相关寄存器如下:
在这里插入图片描述

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。
相关寄存器如下:
在这里插入图片描述

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);
  }
}

该函数通过中断请求编号得到在其在中断激活寄存器中的对应位,然后读取并返回对应位的值。
相关寄存器如下:
在这里插入图片描述

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)
通过中断请求编号找到对应的中断优先级寄存器,然后设置中断优先级寄存器即可。
相关寄存器如下:
在这里插入图片描述
注:stm32f407仅使用高4bit设置中断优先级
(2)系统异常(中断请求序号<0)
通过系统异常请求编号找到对应的异常优先级寄存器,然后设置系统异常优先级寄存器即可。
相关寄存器如下:
在这里插入图片描述
注: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)
通过中断请求编号找到对应的中断优先级寄存器,然后读取中断优先级寄存器即可。
相关寄存器如下:
在这里插入图片描述
注:stm32f407的高4bit为中断优先级
(2)系统异常(中断请求序号<0)
通过系统异常请求编号找到对应的异常优先级寄存器,然后读取系统异常优先级寄存器即可。
相关寄存器如下:
在这里插入图片描述
注: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复位。
相关寄存器如下:
在这里插入图片描述

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;
}

这个函数实际上就是设置外部中断向量偏移量,用得很少。
相关寄存器如下:
在这里插入图片描述

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];
}

这个函数实际上就是获取外部中断向量偏移量寄存器的值,用得很少。
相关寄存器如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399754.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么使用物理、数学等工具不能实现对人类智能的模拟

物理和数学是研究自然界和抽象概念的工具&#xff0c;它们为我们提供了理论和方法来解决问题。在实现类人的智能方面&#xff0c;物理和数学可以应用于以下几个方面&#xff1a; 1、计算机科学和算法 数学中的逻辑、统计学和优化理论等可以用于开发智能算法和机器学习模型。这些…

【趣味题-03】20240120猴子吃桃( 从大到小insert ,列表元素互减)

背景需求&#xff1a; 猴子摘桃的题目 解决&#xff1a; 猴子吃桃 倍数问题 作者&#xff1a;阿夏 时间&#xff1a;2024年1月20日猴子吃桃问题-1 猴子第一天摘了许多桃子&#xff0c;第一天吃了一半&#xff0c;&#xff1b;第二天又吃了一半&#xff0c; 后面每天都是这样吃…

NLP论文阅读记录 - 2022 | WOS 04.基于 XAI 的强化学习方法,用于社交物联网内容的文本摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作三.本文方法3.1 总结为两阶段学习3.1.1 基础系统 3.2 重构文本摘要 四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 XAI-Base…

vue3 项目中 arguments 对象获取失败问题

问题 在 vue3 项目中 获取到的 arguments 对象与传入实参不符&#xff0c;打印出函数中的 arguments 对象显示如下&#xff1a; 原因 作者仔细回看代码才发现&#xff0c;自己一直用的是 vue3 的组合式写法&#xff0c;函数都是箭头函数&#xff0c;而箭头函数不存在 argumen…

GoZero微服务个人探究之路(七)添加中间件、自定义中间件

说在前面 官方已经自己实现了很多中间件&#xff0c;我们可以方便的直接使用&#xff0c;不用重复造轮子了 开启方式可以看官方文档 中间件 | go-zero Documentation 实现自定义的中间件 在业务逻辑中&#xff0c;我们需要实现自定义功能的中间件 ------这里我们以实现跨源…

【jQuery入门】链式编程、修改css、类操作和className的区别

文章目录 前言一、链式编程二、修改css2.1 获取css的值2.2 设置单个css属性2.3 设置类样式添加类移除类切换类 三、类操作与className的区别总结 前言 jQuery是一个流行的JavaScript库&#xff0c;广泛用于简化DOM操作和处理事件。在jQuery中&#xff0c;链式编程是一种强大的…

VisualSVN Server实战

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;下载VisualSVN Server&#xff08;二&#xff09;安装VisualSVN Server&#xff08;三&#xff09;使用VisualSVN Server1、新建仓库&#xff08;1&#xff09;新建Repository&#xff08;2&#xff09;选择仓库类…

CentOS 7安装Java并配置环境

一、安装Java环境 1、检查系统是否安装Java [rootlocalhost ~]# java -version 2、更新系统软件包 [rootlocalhost ~]# yum update #遇到[y/n],选择y并回车&#xff0c;耐心等待下载完毕&#xff0c;之后系统会自动检验更新的软件包遇到 /var/run/yum.pid 已被锁定 /var/…

Microchip Studio修改工程名

打开工程后&#xff0c;右键选择重命名 右键工程重命名 关闭后回到工程下的文件夹 再次打开工程软件会显示加载失败&#xff0c;此时是找不到路径了 菜单栏打开工程 选择修改文件夹名字的路径下的cproj文件 然后点击关闭&#xff0c;会显示保存新的atsln文件&#xff0c;此时将…

web渗透安全学习笔记:2、HTML基础知识

目录 前言 HTML的标题 段落链接与插入图片 HTML元素 HTML属性 HTML头部 HTML与CSS HTML与JavaScript 表格与列表 HTML区块 布局 HTML表单 HTML与数据库 音频与视频 HTML事件 前言 HTML的标题 <!DOCTYPE html> <html> <head> <meta chars…

VMware workstation安装FreeBSD14.0虚拟机并配置网络

VMware workstation安装FreeBSD14.0虚拟机并配置网络 FreeBSD是类UNIX操作系统&#xff0c;FreeBSD带有多个软件包&#xff0c;并覆盖了广阔的应用领域&#xff0c;且都是免费和易于安装的。该文档适用于在VMware workstation平台安装FreeBSD14.0虚拟机。 1.安装准备 1.1安装…

事件驱动架构

请求驱动 服务注册&#xff0c;服务发现&#xff0c;虽然调用地址隐藏了&#xff0c;但是调用stub必须相同。 rpc通信&#xff0c;远程调用。 生产者和消费者要有相同的stub存根。 消费者和生产者的调用接口是耦合的。 事件驱动 核心&#xff1a;上下游不进行通信 中间通过M…

【Go】rune和byte类型的认识与使用

【Go】rune和byte类型的认识与使用 大家好 我是寸铁&#x1f44a; 总结了一篇rune和byte类型的认识与使用的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; byte和rune类型定义 byte,占用1个字节&#xff0c;共8个比特位&#xff0c;所以它实际上和uint8没什么本质区别,它表示…

qt学习:应用程序设置菜单栏+实战 打开文件菜单栏

目录 步骤如下 第一步&#xff0c;ui界面&#xff0c;双击菜单栏可以改菜单栏的内容 第二步&#xff0c;修改菜单栏 第三步&#xff0c;设置好的action拖到菜单栏 第四步&#xff0c;triggered槽函数实现 在qt中&#xff0c;如果想要使用菜单栏功能&#xff0c;那么界面的基…

【C++笔记】C++11一些重要的新特性

一、列表初始化 C11第一个比较好用的特性就是”列表初始化"&#xff0c;它可以大大的节省我们初始化对象的时间(特别是对象数组)&#xff0c;虽然有些地方用起来有点儿奇怪&#xff0c;但是总的来说利大于弊。 1、列表初始化的使用方法 我们在使用C语言或者在C11之前&a…

动态规划Day14(子序列第二天)

目录 1143.最长公共子序列 看到题目的第一想法 看到代码随想录之后的想法 自己实现过程中遇到的困难 1035.不相交的线 看到题目的第一想法 看到代码随想录之后的想法 自己实现过程中遇到的困难 53. 最大子序和 看到题目的第一想法 …

Unity3D学习之Unity基础

文章目录 1. 第一部分&#xff1a;MONO中的重要内容2. 延时函数2.1 什么是延时函数2.2 延时函数的使用2.2.1 延时重复函数2.2.2 取消延迟函数2.2.3 判断是否有延迟函数开启2.2.4 延迟函数和依附对象的关系 3 协同程序3.1 Unity中的多线程3.2 协同程序3.3 协程的使用3.3.1 关闭协…

ChatGLM vs ChatGPT

所有的NLP大模型 都是transformer结构 1.Mask attention 的策略不同 2.训练任务目标不同 国内大模型nb公司&#xff1a;百度、清华智谱 一、主流大模型 粉色&#xff1a;Encoder-only。 绿色&#xff1a;Encoder-Decoder&#xff0c;尽头智谱ChatGLM。 蓝色&#xff1a;…

开源项目_大模型应用_Chat2DB

1 基本信息 项目地址&#xff1a;https://github.com/chat2db/Chat2DBStar&#xff1a;10.7K 2 功能 Chat2DB 是一个智能且多功能的 SQL 客户端和报表工具&#xff0c;适用于各种数据库。 对于那些平时会用到数据库&#xff0c;但又不是数据库专家的程序员来说&#xff0c;…

对#多种编程语言 性能的研究和思考 go/c++/rust java js ruby python

对#多种编程语言 性能的研究和思考 打算学习一下rust 借着这个契机 简单的写了计算圆周率代码的各种语言的版本 比较了一下性能 只比拼单线程简单计算能力 计算十亿次循环 不考虑多线程 go/c/rust java js ruby python 耗时秒数 1:1:1:22:3:250:450 注&#xff1a;能启用则启…