05_FreeRTOS中断管理

目录

什么是中断

中断相关寄存器

源码实验


什么是中断

简介:让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 ****/

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值