FreeRTOS学习笔记-基于stm32(3)中断管理

一、什么是中断

        通俗点讲就是让CPU停止当前在做的事,转而去做更紧急的事。

二、中断优先级分组

        这个紧急的事也有一个等级之分,优先级越高越先执行。stm32使用中断优先配置寄存器的高4位,共16级的中断优先等级。

        stm32的中断优先等级可以分为抢占优先级和子优先级。抢占优先级高的中断可以打断正在执行的抢占优先级低的中断;当抢占优先级相同时,子优先级高的优先执行。

eg:抢占优先级2,子优先级1的中断可以打断抢占优先级3,子优先级0的中断;但抢占优先级2,子优先级1的中断不能打断抢占优先级2,子优先级2的中断;虽然前者子优先级高于后者,但子优先级不能打断其他中断

三、特征

        1、低于configMAX_SYSCALL_INTERRUPT_PRIORITY(一般默认设置为5)优先级的中断才允许调用FreeRTOS的API函数(带有“FromISR后缀的函数”);

        2、将所有优先级位指定为抢占优先级位,方便管理;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 

        3、中断优先级越小越优先,任务优先级越大越优先;

四、FreeRTOS中断相关寄存器

        FreeRTOS 中,通过 SHPR3 寄存器,将 PendSV 和 Systick 中断优先级被设置为最低,因为要保证系统任务的切换不会阻塞系统其他中断的响应

1、FreeRTOS关闭中断:

        FreeRTOS 中,通过 BASEPRI 寄存器,屏蔽优先级低于某一阈值的中断。

eg:BASEPRI 寄存器设置为0x50,表示中断优先级在5~15内的均被屏蔽,0~4的正常执行。(因为中断寄存器使用的是8位寄存器的高4位)也就是关闭FreeRTOS的中断  。

portDISABLE_INTERRUPTS();       //关闭中断

         经过此函数的一层层回调,会发现最终此函数还是对寄存器 basepri 写入0x50来关闭中断;

#define portDISABLE_INTERRUPTS()				vPortRaiseBASEPRI()

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			15                      //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5                       //系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) 
//此处对5进行左移4位,正是因为控制中断的寄存器高4位有效

static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

	__asm
	{
		/* Set BASEPRI to the max syscall priority to effect a critical
		section. */
		msr basepri, ulNewBASEPRI //将0x50写入寄存器basepri
		dsb
		isb
	}
}

2、FreeRTOS开启中断:

        将 BASEPRI 寄存器值设置为0时,则不关闭任何中断。

portENABLE_INTERRUPTS();        //开启中断

        此处就比较简单了,与关闭中断函数类似,直接对中断寄存器 basepri 写0。

#define portENABLE_INTERRUPTS()					vPortSetBASEPRI( 0 )

static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
	__asm
	{
		/* Barrier instructions are not used as this function is only used to
		lower the BASEPRI value. */
		msr basepri, ulBASEPRI
	}
}

 五、中断管理例程

        创建函数与上一章说的类似,此处只展示 task1 代码:

注意:此处延时函数使用的是 delay_xms(); 而不是delay_ms(); 或 vTaskDelay(); 因为FreeRTOS提供的 vTaskDelay() 内部会调用到 vPortSetBASEPRI( 0 ) ,就是上面开启中断所调用的内部函数。也就是说 vTaskDelay() 会调用到开中断函数,而 delay_ms() 内部则是调用的 vTaskDelay() 函数所以如果调用 vTaskDelay() 函数会提前开启中断,从而得不到正确的实验现象。

void task1( void * pvParameters )
{
    uint8_t task1_num=0;
    while(1)
    {
        if(++task1_num==5)
        {
            printf("关中断!!!\r\n");
            portDISABLE_INTERRUPTS();       //关闭中断
            delay_xms(5000);
            printf("开中断!!!!!!\r\n");
            portENABLE_INTERRUPTS();        //开启中断
        }
        vTaskDelay(1000);
    }
}

        定时器部分,为了验证FreeRTOS的中断管理函数仅对5~15的优先级有效,所以 TIM3 的优先级为4,TIM5 的优先级为6;

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;  //先占优先级4级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
}

//通用定时器5中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器5!
void TIM5_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; 					//设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 					//设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 	//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); 			//根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE ); 					//使能指定的TIM5中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  			//TIM5中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;  	//先占优先级6级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  		//从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 			//IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  							//初始化NVIC寄存器

	TIM_Cmd(TIM5, ENABLE);  									//使能TIM5					 
}

        中断服务函数

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
	{
		printf("TIM3输出!!!\r\n");
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}

//定时器5中断服务函数
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //溢出中断
	{
		printf("TIM5输出!!!!!!\r\n");
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清除中断标志位
}

        由于FreeRTOS的中断管理函数仅对5~15的优先级有效,所以关闭中断后,TIM3会正常工作。

        实验现象:

        至于关中断时候输出的乱码,我个人觉得可能是抢占同一个串口导致的。

                                 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

链表|142.环形链表

ListNode *detectCycle(ListNode *head) {ListNode *fast head, *slow head;while (fast && fast->next) {// 这里判断两个指针是否相等&#xff0c;所以移位操作放在前面slow slow->next;fast fast->next->next;if (slow fast) { // 相交&#xff0c…

【Godot4自学手册】第二十二节完成主人公的闪现功能

这一节我们主要自学主人公的闪现功能&#xff0c;当按下鼠标右键&#xff0c;我们的主人公根据不同的方向进行瞬间移动&#xff0c;并在身后留下一串残影&#xff0c;具体效果如下&#xff1a; 一、新建ghost场景 新建Node2D场景&#xff0c;命名为Ghost&#xff0c;存储到S…

《vtk9 book》 官方web版 第3章 - 计算机图形基础 (3 / 6)

3.8 演员几何 我们已经看到了光照属性如何控制演员的外观&#xff0c;以及相机如何结合变换矩阵将演员投影到图像平面上。剩下的是定义演员的几何形状&#xff0c;以及如何将其定位在世界坐标系中。 建模 计算机图形学研究中的一个重要主题是建模或表示物体的几何形状。…

第五十四回 高太尉大兴三路兵 呼延灼摆布连环马-AI通过构建并训练CNN网络来进行飞机识别

呼延灼举荐了百胜将韩滔和天目将彭玘做先锋。 两军对战&#xff0c;韩滔和秦明斗二十回合&#xff0c;呼延灼与林冲斗在一起&#xff0c;花荣与彭玘斗在一处&#xff0c;后彭玘与一丈青扈三娘斗在一起&#xff0c;被扈三娘抓住。 尽管梁山占优&#xff0c;宋江也没有乘胜追击&…

❤ Vue3项目搭建系统篇(二)

❤ Vue3项目搭建系统篇&#xff08;二&#xff09; 1、安装和配置 Element Plus&#xff08;完整导入&#xff09; yarn add element-plus --savemain.ts中引入&#xff1a; // 引入组件 import ElementPlus from element-plus import element-plus/dist/index.css const ap…

B端系统升级,登录页必在升级之列,不容置疑。

进行B端界面升级时&#xff0c;首先升级登录页有以下几个原因&#xff1a; 用户体验&#xff1a;登录页是用户进入系统的第一个页面&#xff0c;用户首先接触到的界面。通过升级登录页&#xff0c;可以提升用户的第一印象&#xff0c;增强用户对系统的信任感和好感度&#xff…

基于Unity3D引擎RPG游戏设计与开发

目 录 摘 要 I Abstract II 引 言 1 1.相关技术 3 1.1 Unity基础界面 3 1.2 C#脚本编写 3 1.3 Unity脚本 3 1.4 Unity物理引擎 3 1.5 UGUI 3 1.6 Unity动画系统 4 1.7 本章小结 4 2. 系统分析 5 2.1游戏内容需求分析 5 2.2游戏流程需求分析 5 2.3游戏场景需求分析 5 2.4怪物系…

GPT-4-turbo还是大家心中第一!Claude 3竞技场人类投票成绩出炉:仅居第三

Claude 3的竞技场排名终于揭晓了&#xff1a; 在仅仅3天的时间里&#xff0c;20000张投票使得排名的流量达到了前所未有的高度。 最后&#xff0c;Claude 3的"大杯"模型Opus以1233的分数赢得了胜利&#xff0c;成为了第一个能和GPT-4-Turbo匹敌的选手。 "中杯…

基于范围的for循环(C++11)和auto

auto C11中&#xff0c;标准委员会赋予了auto全新的含义即&#xff1a; auto不再是一个存储类型指示符&#xff0c;而是作为一个新的类型 指示符来指示编译器&#xff0c;auto声明的变量必须由编译器在编译时期推导而得。 int a 10;auto b a;auto c a;auto d TestAuto(…

Vue:自动按需导入element-plus图标

自动导入使用 unplugin-icons 和 unplugin-auto-import 从 iconify 中自动导入任何图标集。 完整vite.config.js参考模板 https://download.csdn.net/download/ruancexiaoming/88928539 导入element-plus图标 命令行安装unplugin-icons pnpm i -D unplugin-icons//没有安装自…

银河麒麟V10 安装部署大数据管理软件 DataSophon

一、概览 1、愿景 致力于快速实现部署、管理、监控以及自动化运维大数据云原生平台&#xff0c;帮助您快速构建起稳定、高效、可弹性伸缩的大数据云原生平台。 2、DataSophon是什么 《三体》&#xff0c;这部获世界科幻文学最高奖项雨果奖的作品以惊艳的"硬科幻"…

Joe主题网站

一款博客网站源码 发现源码为大家内置了主题 清爽又强大真正的永久可用的一条源码&#xff0c;该版本为整合版本&#xff0c;内置了Joe主题&#xff0c;搭建后直接启用即可~ 安装环境要求&#xff1a; PHP 7.2 以上 MySQL, PostgreSQL, SQLite 任意一种数据库支持&#xff0c;…

一个爬虫自动化数据采集的故事~

目录 一、原文二、故事前半段背景内容三、正经的讲点DrissionPage知识四、故事的收尾 一、原文 原文来自一个爬虫自动化数据采集的故事~ , 建议点击链接看文章末尾的视频笔者不擅长自动化&#xff0c;一个小小故事分享给大家&#xff0c;仅个人观点 二、故事前半段背景内容 …

C#中对象的相等性与同一性的判断方法总结

C#对象的相等性与同一性 1. 概述与准备1.1 概述1.2 准备 2. Equals(Object)2.1 功能&#xff1a;2.2 实例&#xff1a;2.3 扩展&#xff1a;2.4 重写此方法 3. Equals(Object, Object)3.1 功能3.2 实例 4. ReferenceEquals(Object, Object)4.1 功能4.2 使用场景&#xff1a;4.3…

突破编程_前端_JS编程实例(自适应表格列宽)

1 开发目标 针对如下的表格组件&#xff1a; 根据表格的各个列字符串宽度动态调整表格列宽&#xff1a; 2 详细需求 本组件目标是提供一个自动调整 HTML 表格列宽的解决方案&#xff0c;通过 JS 实现动态计算并调整表格每列的宽度&#xff0c;以使得表格能够自适应容器宽度&a…

Matlab|配电网智能软开关(sop)规划模型

目录 1 主要内容 目标函数 2 部分程序 3 程序结果 3.1 sop选址定容优化模型 3.2 对比算例&#xff08;不含sop&#xff09; 4 下载链接 1 主要内容 该程序参考文献《基于改进灵敏度分析的有源配电网智能软开关优化配置》&#xff0c;采用二阶锥算法&#xff0c;以改进的…

vscode 格式化prettier失败出现一大堆错误

如题&#xff0c;使用vscode开发项目时候&#xff0c;会自动进行格式化【安装prettier插件】 但是有时候会出现格式化失败的情况&#xff0c;如果插件安装正确&#xff0c;则可能是代码出现了格式问题。

使用腾讯云快速搭建WordPress网站流程详解

专栏系列文章&#xff1a; WordPress建站主题美化系列教程https://blog.csdn.net/seeker1994/category_12184577.html 一文搞懂WordPress是什么&#xff1f;为什么用它建站&#xff1f;怎么安装与部署&#xff1f; 初次安装WordPress后如何进行网站设置&#xff08;主题安装、…

揭秘接口测试:完整流程指南!

在讲接口测试之前&#xff0c;首先需要给大家申明下&#xff1a;接口测试对于测试人员而言&#xff0c;非常非常重要&#xff0c;懂功能测试接口测试&#xff0c;就能在企业中拿到一份非常不错的薪资。 这么重要的接口测试&#xff0c;一般也是面试笔试必问。为方便大家更好的…

Python快速入门系列-2(Python基础语法)

第三章&#xff1a;Python基础语法 3.1 变量与数据类型3.1.1 变量的定义与赋值3.1.2 数据类型3.1.3 类型转换 3.2 注释与缩进3.2.1 注释3.2.2 缩进 3.3 条件语句与循环结构3.3.1 条件语句3.3.2 循环结构 3.4 函数与模块3.4.1 函数3.4.2 参数和返回值3.4.3 模块3.4.4 标准库中的…