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.pswp.cn/news/379751.shtml

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

相关文章

vector向量容器

一、vector向量容器 简介: Vector向量容器可以简单的理解为一个数组,它的下标也是从0开始的,使用时可以不用确定大小,但是它可以对于元素的插入和删除,可以进行动态调整所占用的内存空间,它里面有很多系统…

netsh(二)

netsh 来自微软的网络管理看家法宝很多时候,我们可能需要在不同的网络中工作,一遍又一遍地重复修改IP地址是一件比较麻烦的事。另外,系统崩溃了,重新配置网卡等相关参数也比较烦人(尤其是无线网卡)。事实上…

java uuid静态方法_Java UUID getLeastSignificantBits()方法与示例

java uuid静态方法UUID类getLeastSignificantBits()方法 (UUID Class getLeastSignificantBits() method) getLeastSignificantBits() method is available in java.util package. getLeastSignificantBits()方法在java.util包中可用。 getLeastSignificantBits() method is us…

Google C2Dm相关文章

Android C2DM学习——云端推送:http://blog.csdn.net/ichliebephone/article/details/6591071 Android C2DM学习——客户端代码开发:http://blog.csdn.net/ichliebephone/article/details/6626864 Android C2DM学习——服务器端代码开发:http…

FreeRTOS的列表和列表项

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

string基本字符系列容器

二、string基本字符系列容器 简介:C语言只提供了一个char类型来处理字符,而对于字符串,只能通过字符串数组来处理,显得十分不方便。CSTL提供了string基本字符系列容器来处理字符串,可以把string理解为字符串类&#x…

正则表达式(一)

正则表达式概述 1.1什么是正则表达式? 正则表达式(Regular Expression)起源于人类神经系统的早期研究。神经生理学家Warren McCulloch和Walter Pitts研究出一种使用数学方式描述神经网络的方法。1956年,数学家Stephen Kleene发表了一篇标题为“神经…

42.有“舍”才有“得”

大干世界,万种诱惑,什么都想要,会累死你,该放就放,该舍就舍。人必须先有所舍,才能有所得,舍如同种子撒播出去,转了一圈,又带了一大群子子孙孙回来。“舍”永远在“得”的…

Java StringBuilder codePointCount()方法与示例

StringBuilder类codePointCount()方法 (StringBuilder Class codePointCount() method) codePointCount() method is available in java.lang package. codePointCount()方法在java.lang包中可用。 codePointCount() method is used to count the number of Unicode code point…

FreeRTOS时间管理

在使用FreeRTOS的过程中,我们通常会在一个任务函数中使用延时函数对这个任务延时,当执行延时函数的时候就会进行任务切换,并且此任务就会进入阻塞太,直到延时完成,任务重新进入就绪态。延时函数舒属于FreeRTOS的时间管…

set和multiset集合容器

三、①set集合容器 简介&#xff1a;set集合的目的就是为了快速检索。set集合容器实现了红黑树的平衡二叉检索树的数据结构。set集合里面不允许有重复的元素出现&#xff1b;使用set容器前&#xff0c;需要在程序的头文件中声明 #include < set >。 函数方法总结&#…

javascript获取select的值全解

获取显示的汉字 document.getElementById("bigclass").options[window.document.getElementById("bigclass").selectedIndex].text 获取数据库中的id window.document.getElementById("bigclass").value 获取select组分配的索引id window.docume…

Java File类void deleteOnExit()方法(带示例)

文件类void deleteOnExit() (File Class void deleteOnExit()) This method is available in package java.io.File.deleteOnExit(). 软件包java.io.File.deleteOnExit()中提供了此方法。 This method is used to delete the file or directory when the virtual machine termi…

FreeRTOS队列

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

括号配对问题(C)

描述 现在&#xff0c;有一行括号序列&#xff0c;请你检查这行括号是否配对。 输入 第一行输入一个数N&#xff08;0<N<100&#xff09;,表示有N组测试数据。后面的N行输入多组输入数据&#xff0c;每组输入数据都是一个字符串S(S的长度小于10000&#xff0c;且S不是空串…

剧情介绍:“阿甘正传”

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

java 方法 示例_Java集合syncedList()方法与示例

java 方法 示例集合类syncList()方法 (Collections Class synchronizedList() method) synchronizedList() method is available in java.util package. syncList()方法在java.util包中可用。 synchronizedList() method is used to return the synchronized view of the given…

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

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

Linux 上 rpm包管理工具的基本使用

查询是否安装某个包&#xff1a;rpm -q 包名查询所有已安装的包&#xff1a;rpm -q a查询未安装包的文件信息&#xff1a;rpm -qilp 未安装的包安装包&#xff1a;rpm -i 包测试安装包&#xff1a;rpm -i test 包删除包&#xff1a;rpm -e 包名测试删除包&#xff1a;rpm -e te…

ios 内存使用陷阱

在iphone开发过程中&#xff0c;代码中的内存泄露我们很容易用内存检测工具leaks 检测出来&#xff0c;并一一改之&#xff0c;但有些是因为ios 的缺陷和用法上的错误&#xff0c;leaks 检测工具并不能检测出来&#xff0c;你只会看到大量的内存被使用&#xff0c;最后收到didR…