FreeRTOS中断配置与临界段

Cortex-M中断

中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序(中断服务程序),处理完毕后又返回原被暂停的程序继续运行。Cortex-M内核的MCU提供了一个用于中断管理的嵌套向量中断控制器(NVIC)。
当多个中断来临的时候,处理器应响应哪一个中断是由中断的优先级来决定的,高优先级(优先级的编号小)的中断首先得到响应,可以抢占低优先级的中断。Cortex-M处理器有三个固定优先级和256个可编程优先级,最多有128个抢占等级,优先级配置寄存器是8位宽的,处理器还把优先级分为高低两段:抢占优先级和亚优先级,但实际的优先级数量是由芯片厂商决定的,STM32选择了4位作为优先级,只有16个优先级,FreeRTOS的中断配置没有处理亚优先级这种情况,所以全是抢占优先级,设置分组时候,选择中断优先级分组4,优先级分组配置在HAL_Init()中。
在这里插入图片描述

FreeRTOS中断配置宏

  1. configPRIO_BITS
    设置MCU使用几位优先级,STM32使用的是4位

  2. configLIBRARY_LOWEST_INTERRUPT_PRIORITY
    设置最低优先级,STM32配置使用组4,都是抢占优先级,最低优先级为15
    在这里插入图片描述

  3. configKERNEL_INTERRUPT_PRIORITY
    设置内核中断优先级

  4. configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
    系统可管理的最大优先级
    在这里插入图片描述
    优先级数低于5不归FreeRTOS管理

  5. configMAX_SYSCALL_INTERRUPT_PRIORITY
    此宏设置好后,优先级低于此的中断可以安全调用FreeRTOS的API函数,优先级高于此的中断FreeRTOS是不能禁止的,中断服务函数也不能调用FreeRTOS的API函数。
    在这里插入图片描述
    由于高于configMAX_SYSCALL_INTERRUPT_PRIORITY的优先级不会被FreeRTOS内核屏蔽,因此对于那些实时性要求严格的任务就可以使用这些优先级。

FreeRTOS开关中断

开关中断函数为portENABLE_INTERRUPTS和portDISABLE_INTERRUPTS
当关闭中断后,优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY(优先级数大于configMAX_SYSCALL_INTERRUPT_PRIORITY)的中断将被屏蔽,高于configMAX_SYSCALL_INTERRUPT_PRIORITY(优先级数小于configMAX_SYSCALL_INTERRUPT_PRIORITY)的不会被屏蔽

临界段代码

临界段代码也叫临界区,是指那些必须完整运行,不能被打断的代码段。FreeRTOS在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。
FreeRTOS与临界段代码保护有关的函数有4个:taskENTER_CRITICAL、taskEXIT_CRITICAL、taskENTER_CRITICAL_FROM_ISR、taskEXIT_CRITICAL_FROM_ISR,前两个是任务级别的临界段代码保护,后两个是中断级的临界区保护。

中断测试

start_task:创建另一个任务
interrupt_task:中断测试实验,任务中会调用FreeRTOS的关中断函数portDISABLE_INTERRUPTS来将中断关闭一段时间。

任务设置

//任务优先级
#define START_TASK_PRIO			1
//任务堆栈大小	
#define START_STK_SIZE 			256  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define INTERRUPT_TASK_PRIO		2
//任务堆栈大小	
#define INTERRUPT_STK_SIZE 		256  
//任务句柄
TaskHandle_t INTERRUPTTask_Handler;
//任务函数
void interrupt_task(void *p_arg);

main函数

int main(void)
{HAL_Init();                     //初始化HAL库   Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhzdelay_init(180);                //初始化延时函数LED_Init();                     //初始化LED uart_init(115200);              //初始化串口TIM3_Init(10000-1,9000-1); 		//初始化定时器3,定时周期1STIM5_Init(10000-1,9000-1); 		//初始化定时器5,定时周期1S//创建开始任务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();          //开启任务调度
}

任务函数

//开始任务任务函数
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建中断测试任务xTaskCreate((TaskFunction_t )interrupt_task,  			//任务函数(const char*    )"interrupt_task", 			//任务名称(uint16_t       )INTERRUPT_STK_SIZE,		//任务堆栈大小(void*          )NULL,						//传递给任务函数的参数(UBaseType_t    )INTERRUPT_TASK_PRIO,		//任务优先级(TaskHandle_t*  )&INTERRUPTTask_Handler); 	//任务句柄vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}//中断测试任务函数 
void interrupt_task(void *pvParameters)
{static u32 total_num=0;while(1){total_num+=1;if(total_num==5) {printf("关闭中断.............\r\n");portDISABLE_INTERRUPTS();			//关闭中断delay_xms(5000);					//延时5sprintf("打开中断.............\r\n");	//打开中断portENABLE_INTERRUPTS();}LED0=~LED0;vTaskDelay(1000);}
}   

中断初始化

TIM_HandleTypeDef TIM3_Handler;	//定时器3句柄
TIM_HandleTypeDef TIM5_Handler;	//定时器5句柄//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!(定时器3挂在APB1上,时钟为HCLK/2)
void TIM3_Init(u16 arr,u16 psc)
{TIM3_Handler.Instance = TIM3;TIM3_Handler.Init.Period = arr;TIM3_Handler.Init.Prescaler = psc;TIM3_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;TIM3_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;HAL_TIM_Base_Init(&TIM3_Handler);
}//通用定时器5中断初始化
//arr:自动重装值(TIM2,TIM5是32位的!!)
//psc:时钟预分频数
void TIM5_Init(u32 arr,u16 psc)
{TIM5_Handler.Instance = TIM3;TIM5_Handler.Init.Period = arr;TIM5_Handler.Init.Prescaler = psc;TIM5_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;TIM5_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;HAL_TIM_Base_Init(&TIM5_Handler);
}//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){__HAL_RCC_TIM3_CLK_ENABLE();HAL_NVIC_EnableIRQ(TIM3_IRQn);HAL_NVIC_SetPriority(TIM3_IRQn,4,0);HAL_TIM_Base_Start_IT(&TIM3_Handler);	//开启定时器并更新中断,以后每次更新中断,都会调用TIM3_IRQHandler}else if(htim->Instance == TIM5){__HAL_RCC_TIM5_CLK_ENABLE();HAL_NVIC_EnableIRQ(TIM5_IRQn);HAL_NVIC_SetPriority(TIM5_IRQn,5,0);HAL_TIM_Base_Start_IT(&TIM5_Handler);	//开启定时器并更新中断,以后每次更新中断,都会调用TIM3_IRQHandler}
}
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{HAL_TIM_IRQHandler(&TIM3_Handler);
}//定时器5中断服务函数
void TIM5_IRQHandler(void)
{HAL_TIM_IRQHandler(&TIM5_Handler);
}//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){printf("TIM3输出.....\r\n");}else if(htim->Instance == TIM5){printf("TIM5输出.....\r\n");}
}

运行结果

在这里插入图片描述
一开始没有关闭中断,所以TIM3和TIM5都正常运行,当interrupt_task运行5次之后,此时由于TIM5的中断优先级为5,等于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此TIM5会被关闭。但是,TIM3的中断优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY,不会被关闭,所以TIM3正常运行,中断运行5s后调用函数portENABLE_INTERRUPTS重新打开中断,重新打开中断后TIM5恢复运行。

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

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

相关文章

FreeRTOS的列表和列表项

列表和列表项 列表 列表是FreeRTOS中的一个数据结构,概念上和链表有点类型,是一个循环双向链表,列表被用来跟踪FreeRTOS中的任务。列表的类型是List_T,具体定义如下: typedef struct xLIST {listFIRST_LIST_INTEGRI…

FreeRTOS队列

在实际应用中,我们会遇到一个任务或者中断服务需要和另一个任务进行消息传递,FreeRTOS提供了队列的机制来完成任务与任务、任务与中断之间的消息传递。 0x01 队列简介 队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务…

剧情介绍:“阿甘正传”

阿甘是个智商只有75的低能儿。在学校里为了躲避别的孩子的欺侮,听从一个朋友珍妮的话而开始“跑”。他跑着躲避别人的捉弄。在中学时,他为了躲避别人而跑进了一所学校的橄榄球场,就这样跑进了大学。阿甘被破格录取,并成了橄榄球巨…

FreeRTOS信号量---二值信号量

信号量可以用来进行资源管理和任务同步,FreeRTOS中信号量又分为二值信号量、计算型信号量、互斥信号量和递归互斥信号量。 0x01 二值信号量 二值信号量其实就是一个只有一个队列项的队列,这个特殊的队列要么是满的,要么是空的,任…

FreeRTOS软件定时器

软件定时器允许设置一段时间,当设置的时间达到后就执行指定的功能函数,被软件定时器调用的功能函数叫做定时器的回调函数。软件定时器的回调函数是在定时器服务任务中执行的,所以一定不能在回调函数中调用任何阻塞任务的API函数,比…

WP7之Application Bar控件

Microsoft.Phone.Shell命名空间中定义了ApplicationBar及其相关类(ApplicationBarIconButton和ApplicationBarMenuItem),这些类派生自Object,并完全独立于常规Silverlight编程中的DependencyObject,UIElement和FrameworkElement类层次结构。A…

TomCat使用以及端口号被占用的处理方法

一.HTTP协议 什么是HTTP协议 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。 HTTP请求 HTTP响应 2.如何处理端口被占用 方法一&#xff…

FreeRTOS事件标志组

使用信号量来同步的话,任务只能与单个事务或任务进行同步,有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了,FreeRTOS为此提供了一个可选的解决方法,那就是事件标志组。 0x01 事件标志组 事…

FusionCharts等产品简介

以前做柱状图、饼形图等图表都是根据数据绘制出来的静态图,偶然看到别人的一套系统,居然可以让柱状图的柱子动画般的逐个出现,效果还是很不错的。不要跟我抬杠说不就是展现数据嘛,静态图表有什么不好,要知道用户一般可…

Eclipse和Tomcat绑定并且将上传资源到Tomcat上

步骤如下: 创建一个Dynamic Web Project(图一) Target runtime 选择Apache Tomcat v7.0版本(图二) 切记要选择 v7.0 和2.5 (若没有图二选项见图三) 然后,点击window --> Prefer…

FreeRTOS任务通知

从v8.2.0版本开始,FreeRTOS新增了任务通知这个功能,可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西,使用任务通知的话效率会更高。 任务通知在FreeRTOS是一个可选的选项,要使用任务通知的话就需要将宏configUSE_T…

kinect在openni下也能玩抠出人物换背景

之前想了个很拉风的名字《用kinect玩穿越》,但是现在功能还不是很完善,细节处理也不是很好,脸皮没有足够的厚,所以呢还是叫换背景吧。 这里面包含两个技术要点: 一、抠出活动人物 在微软的SDK里深度图像的前3位即0-2位…

Emit学习-基础篇-基本概念介绍

之前的Hello World例子应该已经让我们对Emit有了一个模糊的了解,那么Emit到底是什么样一个东西,他又能实现些什么功能呢?昨天查了点资料,大致总结了下,由于才开始学习肯定有不完善的地方,希望大家能够批评指…

The FreeRTOS Distribution(介绍、移植、类型定义)

1 Understand the FreeRTOS Distribution 1.1 Definition :FreeRTOS Port FreeRTOS目前可以在20种不同的编译器构建,并且可以在30多种不同的处理器架构上运行,每个受支持的编译器和处理器组合被认为是一个单独的FreeRTOS Port。 1.2 Build…

Eclipse项目左上角出现大红色感叹号怎么办?

出现大红色感叹号是因为环境不匹配 解决方法: 右击出现大红色感叹号的项目 点击 Libraries,将有叉号的给Remove掉 然后再点击 Add Library —> JRE System Library —> Next 勾选第二个即可 之后,就不会出现大红色感叹号了。

PCB---STM32最小系统制作过程

PCB 制作过程STM32核心模块连接外部电源晶振OSC_IN(8MHz)OSC32_IN(32.768MHz)复位下载口BOOT模式电源模块添加功能UARTWKUPSTM32核心模块 这里我们以STM32F103C8T6为列,先将芯片的原理图放到原理图中 对于STM32,有几个模块是核心&#xff0…

FreeRTOS---堆内存管理(一)

FreeRTOS的堆内存管理简介动态内存分配及其与 FreeRTOS 的相关性动态内存分配选项内存分配方案Heap_1heap_2Heap_3Heap_4设置heap_4的起始地址Heap_5vPortDefineHeapRegions()堆相关的函数xPortGetFreeHeapSizexPortGetMinimumEverFreeHeapSizeMalloc调用失败的Hook函数这篇文章…

FreeRTOS--堆内存管理(二)

堆内存管理代码具体实现heap_1内存申请函数内存释放函数heap_2内存块内存堆初始化函数内存块插入函数内存申请函数判断是不是第一次申请内存开始分配内存内存释放函数heap_3heap_4内存堆初始化函数内存块插入函数heap_5上一篇文章说了FreeRTOS实现堆内存的原理,这一…

css中的node.js_在Node App中使用基本HTML,CSS和JavaScript

css中的node.jsYou may think this is not important, but it is!. As a beginner in node.js, most coding exercises are always server sided. 您可能认为这并不重要,但确实如此! 作为node.js的初学者,大多数编码练习始终都是服务器端的。…

Binary String Matching(C++)

题目描述: Given two strings A and B, whose alphabet consist only ‘0’ and ‘1’. Your task is only to tell how many times does A appear as a substring of B? For example, the text string B is ‘1001110110’ while the pattern string A is ‘11’, you should…