当前位置: 首页 > news >正文

FreeRTOS学习(九):中断管理

FreeRTOS学习(九):中断管理


文章目录

  • FreeRTOS学习(九):中断管理
  • 前言
  • 一、中断优先级分组设置
    • 特点
    • 中断优先级分组设置
  • 二、FreeRTOS中断优先级配置
    • PendSV和SysTick中断优先级配置
  • 三、中断相关寄存器
    • PRIMASK
    • FAULTMASK
    • BASEPRI(本实验用)
  • 实验代码
    • 定时器中断配置:
    • 中断优先级设置:
    • FreeRTOS任务与中断交互:
      • 中断恢复过程
  • 总结


前言

本章节带大家来先回顾中断的相关知识,然后根据中断来做实验


一、中断优先级分组设置

特点

  1. 低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS的API函数
  2. 建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理
  3. 中断优先级数值越小越优先任务优先级数值越大越优先

中断优先级分组设置

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

优先级分组抢占优先级子优先级优先级配置寄存器高4位
NVIC_PriorityGroup_00级抢占优先级0-15级子优先级0bit用于抢占优先级,4bit用于子优先级
NVIC_PriorityGroup_10-1级抢占优先级0-7子优先级1bit用于抢占优先级,3bit用于子优先级
NVIC_PriorityGroup_20-3级抢占优先级0-3子优先级2bit用于抢占优先级,2bit用于子优先级
NVIC_PriorityGroup_30-7级抢占优先级0-1子优先级3bit用于抢占优先级,1bit用于子优先级
NVIC_PriorityGroup_40-15级抢占优先级0级子优先级4bit用于抢占优先级,0bit用于子优先级

一般在FreeRTOS中使用HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)函数设置优先级分组。
就是表格的最后一组

二、FreeRTOS中断优先级配置

FreeRTOS中对于中断优先级的配置主要基于以下几个关键定义:

/* 中断嵌套行为配置 */
#ifdef NVIC_PRIO_BITS
    #define configPRIO_BITS NVIC_PRIO_BITS
#else
    #define configPRIO_BITS 4
#endif

/* 中断最低优先级 */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY    15  /* 中断最低优先级 */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5  /* 可以调用FreeRTOS核心API的最高中断优先级 */
#define configKERNEL_INTERRUPT_PRIORITY           (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#define configMAX_SYSCALL_INTERRUPT_PRIORITY      (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#define configMAX_API_CALL_INTERRUPT_PRIORITY     configMAX_SYSCALL_INTERRUPT_PRIORITY

PendSV和SysTick中断优先级配置

在这里插入图片描述
左移4位的原因是因为低4位用不到,NVIC优先级寄存器只使用高4位。

三、中断相关寄存器

FreeRTOS中有三个重要的中断屏蔽寄存器,分别是:

PRIMASK

  • 这是一个只有1个位的寄存器
  • 当它置1时,关掉所有可屏蔽的异常,只剩下NMI和硬fault可以响应
  • 它的缺省值是0,表示没有关中断

FAULTMASK

  • 这也是一个只有1个位的寄存器
  • 当它置1时,只有NMI才能响应,所有其它的异常(包括中断和fault)通通闭嘴
  • 它的缺省值也是0,表示没有关异常

BASEPRI(本实验用)

  • 这个寄存器最多有9位(由表达优先级的位数决定)
  • 它定义了被屏蔽优先级的阈值
  • 当它被设成某个值后,所有优先级号大于等于此值的中断都被关(优先级号越大,优先级越低)
  • 但若被设成0,则不关闭任何中断,0也是缺省值

实验代码

定时器中断配置:

TIM3和TIM5都被配置为基本定时器,时钟频率为72MHz
两个定时器都使用相同的计数参数:

btim_tim3_int_init(10000-1, 7200-1);
btim_tim5_int_init(10000-1, 7200-1);

根据定时器计算公式:Tout = ((arr + 1) * (psc + 1)) / Ft
定时时间 = ((10000) * (7200)) / 72000000 = 1秒

中断优先级设置:

TIM3的中断优先级:抢占优先级4,子优先级0

HAL_NVIC_SetPriority(BTIM_TIM3_INT_IRQn, 4, 0);

TIM5的中断优先级:抢占优先级6,子优先级0

HAL_NVIC_SetPriority(BTIM_TIM5_INT_IRQn, 6, 0);

TIM3的优先级高于TIM5

FreeRTOS任务与中断交互:

在task1中,每5次循环会执行一次中断控制:

if (++task1_num == 5)
{ 
    task1_num=0;
    printf("FreeRTOS关闭中断\r\n");
    portDISABLE_INTERRUPTS();       /* FreeRTOS关闭中断 */
    delay_ms(5000);                 /* 延时5秒 */
    printf("FreeRTOS打开中断\r\n");
    portENABLE_INTERRUPTS();        /* FreeRTOS打开中断 */
}

当中断被关闭时,TIM5定时器的中断会被屏蔽5秒钟
但是TIM3是不会被影响的

现象:
在这里插入图片描述
这是为什么呢
FreeRTOS中的portDISABLE_INTERRUPTS()不是真正地关闭所有中断,而是使用BASEPRI机制:
在portmacro.h中

static portFORCE_INLINE void vPortRaiseBASEPRI(void)
{
    uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

    __asm
    {
        msr basepri, ulNewBASEPRI
        dsb
        isb
    }
}

这段代码的作用是:

将configMAX_SYSCALL_INTERRUPT_PRIORITY值写入BASEPRI寄存器
执行DSB (数据同步屏障)和ISB (指令同步屏障)确保内存操作完成
而在配置文件中
在这里插入图片描述

  • configMAX_SYSCALL_INTERRUPT_PRIORITY设置为5

  • TIM3优先级设置为4

  • TIM5优先级设置为6
    优先级号越大,优先级越低
    当执行portDISABLE_INTERRUPTS()时:

  • TIM3中断继续工作,因为其优先级(4)高于阈值(5)

  • TIM5中断被屏蔽,因为其优先级(6)低于阈值(5)

中断恢复过程

当执行portENABLE_INTERRUPTS()时,通常会执行类似下面的操作:

static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI)
{
    __asm
    {
        msr basepri, ulBASEPRI
    }
}

通常会将BASEPRI重置为0,这样所有优先级的中断都会重新启用。


总结

FreeRTOS的"中断关闭"实际上是一种优先级阈值机制,而不是真正意义上的全部中断关闭。这种设计允许关键的高优先级中断(如TIM3)即使在临界区内也能执行,同时阻止低优先级中断(如TIM5)干扰系统的关键代码执行,这是RTOS实时特性的重要保障。

相关文章:

  • Android Compose框架的值动画(animateTo、animateDpAsState)(二十二)
  • 【MySQL】~/.my.cnf文件
  • 深入探讨MySQL数据库备份与恢复:策略与实践
  • EasyUI数据表格中嵌入下拉框
  • 【c++】【STL】unordered_set 底层实现总结
  • Spring Boot整合SSE实现消息推送:跨域问题解决与前后端联调实战
  • Siri接入DeepSeek快捷指令
  • matlab 模拟 闪烁体探测器全能峰
  • 计算机复试面试
  • 【软考网工-理论篇】第六章 网络安全
  • 工业物联网的范式革命:从“云边“ 到“边边” 协的技术跃迁
  • npm打包时出现ENOTFOUND registry.nlark.com
  • 【XPipe】一款好用的SSH工具
  • linux常用指令(6)
  • C# 打印模板设计-ACTIVEX打印控件-多模板加载
  • 案例:使用网络命名空间模拟多主机并通过网桥访问外部网络
  • CDN基本原理剖析与代码实现测试
  • 【语法】C++的vector
  • 芋道uniapp用户端
  • scNET:整合scRNA-seq和PPI用于学习基因和细胞的embedding
  • 伊朗阿巴斯港港口爆炸已致47人受伤
  • 南方医科大学原副校长宁习洲主动投案,接受审查调查
  • 历史一刻,两个航天员乘组拍摄全家福
  • 上海黄浦一季度实到外资总量全市第二,同比增速领先全市
  • 大家聊中国式现代化|彭羽:为国家试制度探新路,推进高水平对外开放
  • 乌代表团与美特使在伦敦举行会谈,双方同意继续对话