FreeRTOS实时操作系统(四)中断任务管理

文章详细介绍了FreeRTOS中的中断管理,包括中断优先级、中断配置寄存器、中断屏蔽寄存器的使用,以及在STM32中如何设置中断优先级。在FreeRTOS中,低于特定优先级的中断才能调用API,并强调了PendSV和SysTick的优先级设置。文中还给出了中断管理的实战示例,展示了如何初始化和处理中断。
摘要由CSDN通过智能技术生成

系列文章

FreeRTOS实时操作系统(一)RTOS的基本概念

FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库)

FreeRTOS实时操作系统(三)任务挂起与恢复

FreeRTOS实时操作系统(四)中断任务管理

FreeRTOS实时操作系统(五)进入临界区、任务调度器挂起与恢复

FreeRTOS实时操作系统(六)列表与列表项

FreeRTOS实时操作系统(七)时间片调度及RTOS的滴答定时器

FreeRTOS实时操作系统(八)任务状态查询及时间统计函数

FreeRTOS实时操作系统(九)时间延时函数及消息队列

FreeRTOS实时操作系统(十)信号量

FreeRTOS实时操作系统(十一)队列集

FreeRTOS实时操作系统(十二)事件标志组

FreeRTOS实时操作系统(十三)任务通知

FreeRTOS实时操作系统(十四)软件定时器

FreeRTOS实时操作系统(十五)Tickless低功耗模式

FreeRTOS实时操作系统(十六)内存管理



前言

跟着正点原子学习一下中断管理,正好之间没有总结过,还有些地方不清楚。


中断优先级

中断的工作方式就不介绍了,一般ARM-Cortex-M使用的是8位的寄存器来配置中断的优先级,但是在STM32中,只使用了高4位来配置中断优先级,所以最大只有16级。

在这里插入图片描述
STM32的中断优先级分为抢占优先级和子优先级

抢占优先级:高优先级可以打断低优先级的中断
子优先级:相同抢占优先级的两个中断同时发生的时候,子优先级数值小的先执行(数值小优先级高)(子优先级的中断之间不会抢占)

在这里插入图片描述
一般这个优先级设置在HAL_Init()函数中(HAl库),通过调用HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)完成设置。

FreeRTOS中的中断管理

要点:
1、低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS 的API函数。
2、建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理(设置成分组4),HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)。
3、中断优先级数值越小越优先,任务优先级数值越大越优先。

一系列中断管理寄存器

中断配置寄存器

SHPR1寄存器地址:0xE000ED18-0xE000ED1B
SHPR2寄存器地址:0xE000ED1C-0xE000ED1F
SHPR3寄存器地址:0xE000ED20-0xE000ED23
在这里插入图片描述
上表出自《Cortex M3权威指南(中文)》第286页。

在STM32cubeMX中生成的HAL库FreeRTOS中,SHPR3寄存器的名字及地址如下:
在这里插入图片描述

这里需要注意PendSV的优先级和SysTick的优先级,他们两是关于系统工作和任务调度的,所以保证其他中断能随时打断任务切换等,在库中按照如下方式设置优先级为最低。

在Cortex-M3中,如果OS在某个中断活跃时,抢占了该中断,而且又发生了任务调度,并执行了任务,切换到了线程运行模式,将直接触发Fault异常。(所以把SysTick和PendSV中断优先级设置最低也是有原因的,就是为了OS调度不抢占其他中断导致Fault的问题)

虽然这样看系统工作时钟会不稳定,但是没有办法,有文章说如果外部IRQ很多,那么可以考虑提高SysTick优先级,PendSV一直设置最低,来适当解决OS调度SysTick被抢占太厉害的问题。

在FreeRTOS中,需要设置这两个优先级:

1.首先,由于高四位是用来设置优先级的,所以,要设置这两个优先级为15,就需要将15左移4位
在这里插入图片描述
在这里插入图片描述
2.由于SHPR3寄存器是4个地址,每个地址是8位的,所以按照上表,PendSV需要左移16位,SysTick需要左移24位,UL是标记该宏是无符号长整型十进制数据。
在这里插入图片描述
3.将PendSV和SysTick的优先级设置为15,即最低优先级。
在这里插入图片描述

中断屏蔽寄存器

平常见的有三种:
1.PRIMASK:1,关闭所有,只剩下NMI和硬fault两个中断,默认是0;
2.FAULTMASK:1,关闭所有,只有NMI可以相应。默认是0;
3.BASEPRI:最多有9位,当他设置为某个值的时候,优先级比这个值低的全部为屏蔽(数值比这个值大),默认是0,不关闭任何中断。

在FreeRTOS中,利用的就是BASEPRI这个寄存器。比如设置为0x50的时候,优先级在5-15内的所有都被屏蔽,0-4的正常运行。

在这里插入图片描述

__asm 关键字用于调用内联汇编程序,并且可在 C 或 C++ 语句合法时出现,__asm与大括号一起使用,则该关键字表示大括号之间的每一行都是一条汇编语言语句。

在这里插入图片描述在这里插入图片描述
默认生成的HAl中,如果调用该函数就把优先级为5-15的中断全部都关闭了,可以自己更改第一张图中的u1NEWBASEPRI的值来更改屏蔽的寄存器优先级

在这里插入图片描述
5-15的优先级中断被FreeRTOS所屏蔽,不会直接触发中断,要经过内核的管控,可能会存在一些延时,所以一般将一些实时性高的中断放在0-4中。而在5-15的中断中,可以应用FreeRTOS的API函数,但这些必须以“FromISR”结束

中断管理实战

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        BTIM_TIMX_INT_CLK_ENABLE();                     /* 使能TIMx时钟 */
        HAL_NVIC_SetPriority(BTIM_TIMX_INT_IRQn, 6, 0); /* 抢占6,子优先级0 */
        HAL_NVIC_EnableIRQ(BTIM_TIMX_INT_IRQn);         /* 开启ITMx中断 */
    }
    if(htim->Instance == BTIM_TIM7_INT)
    {
        BTIM_TIM7_INT_CLK_ENABLE();                     /* 使能TIM7时钟 */
        HAL_NVIC_SetPriority(BTIM_TIM7_INT_IRQn, 4, 0); /* 抢占4,子优先级0 */
        HAL_NVIC_EnableIRQ(BTIM_TIM7_INT_IRQn);         /* 开启ITM7中断 */
    }
}

正点原子的程序中,设置两个定时器中断的优先级为4和6,然后再任务中进行关闭和打开

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

在这里插入图片描述
这里使用delay_ms(5000);而不使用vTaskDelay(1000);是因为vTaskDelay()函数内部中,在其内部的临界区调用了开中断的函数,使得中断会自动打开。
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值