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

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 includedbuffered 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.hqwc.cn/news/418797.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 的delete、truncate、drop 有什么区别

目录 一、从执行速度上来说 二、从使用场景和原理上讲 1、DELETE 2、truncate 3、drop 希望能够帮助到大家&#xff01;&#xff01;&#xff01; 一、从执行速度上来说 drop > truncate >delete 二、从使用场景和原理上讲 1、DELETE DELETE from TABLE_NAME wh…

uniapp的IOS证书(.p12)和描述文件(.mobileprovision)申请 2024年最新教程

文章目录 准备环境登录 iOS Dev Center 下面我们从头开始学习一下如何申请开发证书、发布证书及相对应的描述文件。首先需要申请苹果 App ID &#xff08;App的唯一标识&#xff09;生成证书请求文件申请开发(Development)证书和描述文件申请开发(Development)证书添加调试设备…

蓝桥杯备战 每日一题 (4)

题目地址 首先我们要有一个知识储备 1 加法&#xff1a;(ab)%m(a%mb%m)%m 2 减法&#xff1a;(a-b)%m(a%m-b%m)%m 3 乘法&#xff1a;a*b%m(a%m)*(b%m)%m 我们可以每次计算就可以取余一次&#xff0c;这样就保证了最后取余的结果和一起相加再取余的结果一样 然后这个题目要怎…

Pyro —— Velocity Voxel Scale

Velocity Voxel Scale是H19.5引入的新参数&#xff0c;该参数可单独定义volume和速度体素&#xff1b;根据参数设置&#xff0c;可观察到模拟时间的显著变化&#xff1b; Velocity Voxel Scale对DOP和SOP均可用&#xff1b;对DOP设置&#xff0c;该参数在Smoke Object&#xf…

postgresql(Windows)初始化数据库教程

省流&#xff1a;本文章内容讲的是如何初始化postgresql数据库环境&#xff0c;前提是已经安装好postgresql数据库&#xff0c;安装步骤参考postgresql&#xff08;Windows&#xff09;安装教程 # 开始&#xff1a;安装postgresql-12.14-2-windows-x64.exe完成后进行初始化数据…

frida https抓包

web端导入证书、https代理即可解决大部分需求&#xff0c;但是&#xff0c;有些app需要处理ssl pinning验证。 废话不多说。frida处理ssl pin的步骤大体如下。 安装python3.x,并在python环境中安装frida&#xff1a; pip install frida pip install frida-tools下载frida-se…

tomcat原理模拟和tomcat优化

1、tomcat实现原理 servlet 没有主方法main&#xff0c;依赖tomcat才能运行&#xff0c;因为tomcat 有主方法main&#xff0c;由java编写 servlet中doGet和doPost方法属于非静态方法&#xff0c;只能依托new对象存在&#xff0c;tomcat无法new出来对象&#xff0c;因此tomcat…

fiddler捕获HTTPS

打开软件查看请求会出现&#xff1a;HTTPS decryption is disabled. Click to configure&#xff0c;表示已经禁用https捕获&#xff0c;点击黄色警告可以进行https配置&#xff0c;也可以选择菜单栏tools>options进行配置 勾选Decrypt HTTPS traffic → 点开 Actions → 重…

【接上篇】二、Flask学习之CSS(下篇)

上篇&#xff1a;二、Flask学习之CSS 3.8hover hover是用来美化鼠标悬停的效果的&#xff0c;当鼠标停放在某个区域&#xff0c;就会执行对应的hover操作。可以操作本标签的内容&#xff0c;也可以操作本标签下某一个标签的内容 3.9after <!DOCTYPE html> <html l…

【极问系列】springBoot集成elasticsearch出现Unable to parse response body for Response

【极问系列】 springBoot集成elasticsearch出现Unable to parse response body for Response 如何解决&#xff1f; 一.问题 #springboot集成elasticsearch组件,进行增删改操作的时候报异常Unable to parse response body for Response{requestLineDELETE /aurora-20240120/…

【精选】中间件 tomcat漏洞复现

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

一个简单的ETCD GUI工具

使用ETCD没有好用的GUI工具&#xff0c;随手用c#写了一个&#xff0c; 做得好玩的一个ETCD GUI工具&#xff0c;后面加上CLI 工具&#xff0c;类似于 redis Cli工具一样&#xff0c;简化在 Linux下面的操作&#xff0c;不知道有没有必要&#xff0c; git 地址如下&#xff0c;…