05_FreeRTOS中断管理

news2024/10/6 2:27:42

目录

什么是中断

中断相关寄存器

源码实验


什么是中断

简介:让CPU打断正常运行的程序,转而去处理紧急的事件(程序) ,就叫中断

举例:上课可以比做CPU正常运行的程序,上厕所可以比做中断程序。

 中断执行机制,可简单概括为三步:

中断请求:外设产生中断请求(GPIO外部中断、定时器中断等)

响应中断:CPU停止执行当前程序,转而去执行中断处理程序(ISR)

退出中断:执行完毕,返回被打断的程序处,继续往下执行

中断优先级分组设置

ARM Cortex-M使用了8位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器,但STM32,只用了中断优先级配置寄存器的高4位[7:4],所以STM32提供了最大16级的中断优先等级

 

STM32 的中断优先级可以分为抢占优先级和子优先级

抢占优先级:抢占优先级高的中断可以打断正在执行但抢占优先级低的中断

子优先级:当同时发生具有相同抢占优先级的两个中断时,子优先级数值小的优先执行

注意:中断优先级数值越小越优先

一共有5种分配方式,对应着中断优先级分组的5个组

 通过调用函数HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)即可完成设置

特点:

1.低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS 的API函数

2.建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理

3.中断优先级数值越小越优先,任务优先级数值越大越优先

 

中断相关寄存器

三个系统中断优先级配置寄存器,分别为SHPR1、SHPR2、SHPR3

SHPR1寄存器地址:0xE000ED18

SHPR2寄存器地址:0xE000ED1C

SHPR3寄存器地址:0xE000ED20

 FreeRTOS如何配置PendSV和Systick中断优先级

 

 

 所以: PendSV和SysTick设置最低优先级

设置最低:保证系统任务切换不会阻塞系统其他中断的响应

三个中断屏蔽寄存器,分别为PRIMASK、 FAULTMASK和BASEPRI

 FreeRTOS所使用的中断管理就是利用的BASEPRI这个寄存器

BASEPRI:屏蔽优先级低于某一个阈值的中断

比如:BASEPRI设置为0x50,代表中断优先级在5~15内的均被屏蔽,0~4的中断优先级正常执行

BASEPRI:屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断

关中断程序示例:

 中断优先级在5~15的全部被关闭

当BASEPRI设置为0x50时:

 在中断服务函数中调度FreeRTOS的API函数需注意:

1.中断服务函数的优先级需在FreeRTOS所管理的范围内

2.在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数

BASEPRI:屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断

开中断程序示例:

 FreeRTOS中断管理就是利用BASEPRI寄存器实现的

源码实验

/**
  ******************************************************************************
  * @file           : user_timer.c
  * @brief          : V1.00
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Include 包含---------------------------------------------------------------*/
#include "user_timer.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*/

/*!
	\brief		定时器初始化
	\param[in]	装载值
	\param[in]	分频系数
	\retval 	none
*/
void Tim3_Init(uint16_t arr, uint16_t psc)
{	
	/*定时器结构体*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeDefstruct;
	/*NVIC结构体*/
	NVIC_InitTypeDef NVIC_InitTypeDefstruct;
	
	TIM_TimeBaseInitTypeDefstruct.TIM_Period = arr; //自动装载值
	TIM_TimeBaseInitTypeDefstruct.TIM_Prescaler = psc; //分频系数
	TIM_TimeBaseInitTypeDefstruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInitTypeDefstruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频
	/*写入定时器3*/
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypeDefstruct);

	/*使能定时器更新中断配置*/
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
	
	/*定时器中断优先级配置*/	
	NVIC_InitTypeDefstruct.NVIC_IRQChannel=  TIM3_IRQn; //USART1中断通道
	NVIC_InitTypeDefstruct.NVIC_IRQChannelCmd = ENABLE;  //使能USART1中断
	NVIC_InitTypeDefstruct.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级
	NVIC_InitTypeDefstruct.NVIC_IRQChannelSubPriority = 0;//子优先级
	
	/*写入NVIC中*/
	NVIC_Init(&NVIC_InitTypeDefstruct);
	
	/*使能定时器*/
	TIM_Cmd(TIM3,ENABLE);
	
	
}

/*!
	\brief		TIM3_IRQHandler
	\param[in]	none
	\param[in]	none
	\retval 	none
*/

void TIM3_IRQHandler(void)
{
	/*判断是不是更新中断*/
	if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET)
	{
		printf("定时器3时间到任务优先级2********\r\n");
	}		
	/*清除更新中断*/
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	
}


/*!
	\brief		定时器初始化
	\param[in]	装载值
	\param[in]	分频系数
	\retval 	none
*/
void Tim4_Init(uint16_t arr, uint16_t psc)
{	
	/*定时器结构体*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeDefstruct;
	/*NVIC结构体*/
	NVIC_InitTypeDef NVIC_InitTypeDefstruct;
	
	TIM_TimeBaseInitTypeDefstruct.TIM_Period = arr; //自动装载值
	TIM_TimeBaseInitTypeDefstruct.TIM_Prescaler = psc; //分频系数
	TIM_TimeBaseInitTypeDefstruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInitTypeDefstruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频
	/*写入定时器4*/
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitTypeDefstruct);

	/*使能定时器更新中断配置*/
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
	
	/*定时器中断优先级配置*/	
	NVIC_InitTypeDefstruct.NVIC_IRQChannel=  TIM4_IRQn; //USART1中断通道
	NVIC_InitTypeDefstruct.NVIC_IRQChannelCmd = ENABLE;  //使能USART1中断
	NVIC_InitTypeDefstruct.NVIC_IRQChannelPreemptionPriority = 6; //抢占优先级
	NVIC_InitTypeDefstruct.NVIC_IRQChannelSubPriority = 0;//子优先级
	
	/*写入NVIC中*/
	NVIC_Init(&NVIC_InitTypeDefstruct);
	
	/*使能定时器*/
	TIM_Cmd(TIM4,ENABLE);
	
	
}

/*!
	\brief		TIM4_IRQHandler
	\param[in]	none
	\param[in]	none
	\retval 	none
*/

void TIM4_IRQHandler(void)
{
	/*判断是不是更新中断*/
	if(TIM_GetITStatus(TIM4,TIM_IT_Update) == SET)
	{
		printf("定时器4时间到任务优先级6!!!!\r\n");
	}		
	/*清除更新中断*/
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
	
}

/************************************************************** END OF FILE ****/
 
/**
  ******************************************************************************
  * @file           : user_mian.h
  * @brief          : V1.00
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "user_timer.h"
#include "FreeRTOS.h"
#include "task.h"

/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*/

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);


//任务优先级
#define Interruption_TASK_PRIO		2
//任务堆栈大小	
#define Interruption_STK_SIZE 		50  
//任务句柄
TaskHandle_t InterruptionTask_Handler;
//任务函数
void Interruption_task(void *pvParameters);





 int main(void)
 {	

	/*配置系统中断分组为4位抢占*/
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	 /*延时函数初始化*/
	 delay_init();
	/*RCC配置*/
	 Rcc_config();
	/*GPIO初始化*/ 
	 Gpio_Init();
	/*USART1初始化*/
	 Uart1_Init(9600);
	 /*初始化定时器3,1s中断*/ 
	 Tim3_Init(10000-1,7200-1);
	 /*初始化定时器4,1s中断*/ 
	 Tim4_Init(10000-1,7200-1);
	/*创建开始任务*/
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
		

}
 

/*!
	\brief		开始任务函数
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )Interruption_task,     	
                (const char*    )"Interruption_task",   	
                (uint16_t       )Interruption_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )Interruption_TASK_PRIO,	
                (TaskHandle_t*  )&InterruptionTask_Handler);   
         
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}


/*!
	\brief		led0_task任务函数
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void Interruption_task(void *pvParameters)
{
	uint8_t i =0;
    while(1)
    {
		if(++i == 5)
		{
			i=0;
			printf("关闭中断*****\r\n");
			/*关闭中断*/
			portDISABLE_INTERRUPTS();
			/*延时5秒*/
			delay_us(5000000);
			printf("开启中断*****\r\n");
			/*开启中断*/
			portENABLE_INTERRUPTS();			
		}

		vTaskDelay(1000);
    }
} 

 /************************************************************** END OF FILE ****/

 

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

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

相关文章

【精品】k8s(Kubernetes)cka由基础到实战学法指南

轻松快速学会k8s四招 图1 k8s四招 学完本篇,您会获得什么惊喜? 从初学k8s,到帮助别人学会的过程中,发现朋友们和我,并非不努力,而是没有掌握更好的方法。有方法可让我们学的更快更轻松,这篇文章,以一个networkpolicy的题目,来逐步讲解,帮助大家建立一种,自己可以根…

Java基础语法

文章目录Java 基础语法一、注释1. 注释介绍2. 注释分类3. 注释颜色二、关键字1. 关键字介绍2. 所有关键词三、字面量四、变量1. 变量2. Debug 工具1&#xff09;如何加断点&#xff1f;2&#xff09;如何开启 Debug 运行&#xff1f;3&#xff09;点哪里 ?4&#xff09;看哪里…

ElasticSearch架构之整合ELK

前言本篇文章主要是说ElasticSearch对Logstash、FileBeat、Kibana整合形成ELK的架构&#xff0c;为什么需要整合这个架构呢&#xff1f;一个很重要的原因就是我们开发过程中有相当多的日志需要进行查看&#xff0c;如果我们要查找一个问题需要到多台服务器进行查看那是相当麻烦…

【Java基础知识 4】Java数据类型之间的转换、运算符

本文已收录专栏 &#x1f332;《Java进阶之路》&#x1f332; 目录 &#x1f334;基本数据类型 &#x1f343;01、布尔 &#x1f343;02、byte &#x1f343;03、short &#x1f343;04、int &#x1f343;05、long &#x1f343;06、float &#x1f343;07、double …

C生万物 | 详解程序环境和预处理【展示程序编译+链接全过程】

&#x1f451;作者主页&#xff1a;Fire_Cloud_1 &#x1f3e0;学习社区&#xff1a;烈火神盾 &#x1f517;专栏链接&#xff1a;万物之源——C 文章目录一、程序的翻译环境和执行环境二、详解编译链接1、前言小知识&#x1f50d;2、翻译环境【important】2.1 编译① 预编译【…

【LeetCode每日一题】【2023/1/15】2293. 极大极小游戏

文章目录2293. 极大极小游戏方法1&#xff1a;双指针2293. 极大极小游戏 LeetCode: 2293. 极大极小游戏 简单\color{#00AF9B}{简单}简单 给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 nums 执行下述算法&#xff1a; 设 n 等于 nums 的长度&#x…

Windows 10的子系统不是非Ubuntu不可

Ubuntu 的制造商 Canonical 早已和微软进行合作&#xff0c;让我们体验了极具争议的 Bash on Windows。外界对此也是褒贬不一&#xff0c;许多 Linux 重度用户则是质疑其是否有用&#xff0c;以及更进一步认为 Bash on Windows 是一个安全隐患。 Unix 的 Bash 是通过 WSL&#…

MyBatis动态设置表名 获取添加功能自增的主键 自定义映射

MyBatis动态设置表名 获取添加功能自增的主键 自定义映射动态设置表名获取添加功能自增的主键自定义映射解决字段名和属性名不一致的情况为字段起别名,保持和属性名的一致设置全局配置,保持和属性名的一致通过resultMap设置自定义的映射关系动态设置表名 mapper接口&#xff1a…

Java实现线段树

问题一&#xff1a;开始的子区间是怎么分的&#xff1f; M (LR)/2&#xff0c;左子区间为[L,M]&#xff0c;右子区间为[M1,R] 问题二&#xff1a;如何进行区间统计&#xff1f; 假设这13个数为1,2,3,4,1,2,3,4,1,2,3,4,1. 在区间之后标上该区间的数字之和&#xff1a; 如…

Windows安全加固-AD建立与加入

AD建立与加入 实验环境说明&#xff1a; 域控从机&#xff1a; Windows 2003 域控主机&#xff1a; Windows 2008 IP设置 设置同一网段-保证连通性 将NDS指向Windos2008 第一步&#xff0c;域控服务器需要将服务器设为静态 IP地址 1.将Windows2008服务器IP地址修改为192.1…

c++ - 第24节 - c++的IO流

1.C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf()与printf()。 scanf(): 从标准输入设备(键盘)读取数据&#xff0c;并将值存放在变量中。printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)。注意宽度输出和精度输出控制。C语言借助了相应的缓冲区…

【Android gradle】自定义一个android gradle插件之buildSrc

文章目录1. 前言2. 简单使用3. 其余用法3.1 依赖&版本管理3.2 插件版本自增3.3 其余4. 链接1. 前言 在【Android gradle】自定义一个android gradle插件&#xff0c;并发布到私有Artifactory仓库这篇文章中介绍了定义一个gradle插件&#xff0c;然后发布到远程或者本地仓库…

对数据库索引和事务的理解

1.数据库授权命令&#xff1a; GRANT<权限> on 表名(或列名) to 用户。 举例&#xff1a; 授予用户SQLTest对数据库Sales的CUSTOMERS表的列cid、cname的查询权限 grant select on CUSTOMERS(cid,cname) to SQLTest; 2.MySQL索引&#xff08;index&#xff09; 什么是索引…

C++5:初见模板

目录 函数模板 函数模板的实例化&#xff1a; 隐式实例化 显示实例化 类模板 虽然学习了类和对象&#xff0c;能很方便的处理一些容器类的问题&#xff0c;但是我们还是会遇到如下这种情况。 我们创建一个简单的stack类 class Stack { public:Stack(){} private:int* _a;…

【机器学习】Logistic Regression 逻辑回归算法详解 + Java代码实现

文章目录一、逻辑回归简介1.1 什么是逻辑回归1.2 Sigmoid函数1.3 预测函数二、逻辑回归实战 - Java代码实现一、逻辑回归简介 1.1 什么是逻辑回归 逻辑回归&#xff08;Logistic Regression&#xff09;是一种用于解决二分类&#xff08;0 or 1&#xff09;问题的机器学习方法…

时间序列模型SCINet模型(自定义项目)

前言 读完代码解析篇&#xff0c;我们针对开源项目中的模型预测方法做一下介绍。Github源码下载地址下载数据集ETTh、PEMS、Traffic、Splar-Energy、Electricity、Exchange-Rate&#xff0c;这几类公共数据集的任意一类就行。这里以ETTh数据集为例&#xff0c;先在项目文件夹下…

whistle抓包工具应用

原文地址&#xff1a;(67条消息) whistle抓包工具学习_BBC蟹耳总的博客-CSDN博客_w2 抓包 一、安装whistle 首先安装好whistle抓包工具&#xff0c;有以下两个步骤 在终端中全局安装whistle&#xff1a;npm install -g whistle可以通过whistle help查看相关信息&#xff0c;…

《零基础学机器学习》读书笔记一

《零基础学机器学习》读书笔记一 一、机器学习快速上手路径 1.1 机器学习的家族谱 人工智能&#xff0c;可以被简单地定义为努力将通常由人类完成的智力任务自动化。 AI效应的2个阶段&#xff1a; &#xff08;1&#xff09;AI将新技术、新体验带进人类的生活&#xff0c;完…

linux环境安装mysql5.7版本

目录 一、下载准备阶段 二、安装运行阶段 linux环境安装mysql是我们工程师必备的技能之一&#xff0c;今天我们实战分享一下安装流程&#xff1a; 一、下载准备阶段 1、查看linux系统是否已经安装mysql rpm -qa|grep -i mysql 显示没有 如果安装过&#xff0c;可以删除&…

DFS排列组合与连通性

目录 一、前言 二、DFS与排列组合 1、DFS&#xff1a;自写排列算法1 &#xff08;1&#xff09;基础模板 &#xff08;2&#xff09;基于(1)输出前n个数任意m个都全排列 2、DFS&#xff1a;自写排列算法2&#xff08;这个写法更常见&#xff09; &#xff08;1&#xff…