03_FreeRTOS中断管理

0. 前言

硬件平台:STM32F103

FreeRTOS移植教程:FreeRTOS移植STM32F103:保姆级教程
FreeRTOS任务相关:01_FreeRTOS任务的动态/静态创建与删除:保姆级教程

1. 中断管理基础知识

1.1 STM32中的中断

什么是STM32的中断?

  • 中断就是当程序执行时遇到突发事件,转而去处理事件,处理完后又回到被打断的地方重新执行程序,就叫中断。

![[Pasted image 20250106170457.png]]

STM32中断的作用:

  • 中断功能可以让系统自动识别指定事件发生,不需要CPU检测某个事件是否发生,从而减少CPU负担, 提高系统的稳定性。
  • 比如当当我们需要检测一个按键是否按下时,使用CPU轮询检测会一直在while循环内检测对应引脚的信号变化,当我们对该引脚配置外部中断,即按键按下的时候即可自动触发对应的事件,从而解放CPU,让CPU可以执行其他事务。

Cortex-M3内核支持256个中断

  • 16个内部中断
  • 240个外部中断
  • 具备256级的可编程中断设置

一般厂商都会对Cortex-M3内核进行裁剪

  • STM32有84个中断
    • 16个内部中断
    • 68个可屏蔽中断
  • 具有16级可编程中断设置
    • 16种优先级
      • 00最大

STM32中断优先级配置:

  • STM32中,中断优先级的配置通过中断有限制配置寄存器的高4位[7:4]来配置

1.2 FreeRTOS中断管理

什么是FreeRTOS中断管理?

  • 为了更灵活的任务调度和管理功能,FreeRTOS提供了自己的中断管理机制。
  • FreeRTOS利用BASEPRI寄存器实现中断管理,屏蔽优先级低于阈值的中断。
  • BASEPRI寄存器的作用:
    • 将一些优先级低于设定值的,进行排除
    • 也就是优先级的值,大于BASEPRI设置的值,就排除该中断

简单来说,FreeRTOS中断管理就是通过配置一个阈值,当开启中断管理时,优先级比阈值低的中断,就会被关闭,只留优先级比阈值高的中断。

  • 比如阈值为5,那么优先级比5小的,也就是优先级高,就可以继续使用,数字比5大的,也就是优先级比5小的,中断会被关闭。

![[Pasted image 20250106171410.png]]

在中断服务函数中调用FreeRTOS的API函数需注意:

  1. 中断服务函数的优先级需在FreeRTOS所管理的分为内,阈值由configMAX_SYSCALL_INTERRUPT_PRIORITY指定。
  2. NVIC的优先级组设置位3,也就是4位全部用于抢占优先级
  3. 中断服务函数中调用FreeRTOS的函数时,该函数必须带有FromISR后缀

2. 中断管理示例流程

示例流程:

  1. 创建一个起始任务
  2. 创建一个任务1
    1. 扫面按键
      1. KEY1按下的时候关闭中断
      2. KEY2被按下时打开中断
  3. 配置1个定时器6
    1. 每500ms打印一次信息

2.1 在项目中配置

配置流程:

  1. 创建定时器驱动文件
    1. Driver_TIM6.h
    2. Driver_TIM6.c
  2. Keil配置项目结构
    1. 配置timer目录
    2. 配置timer头文件路径
  3. 编写定时器驱动驱动寄存器

2.1.1 创建定时器驱动文件

在Driver文件夹中创建timer文件夹,用于存放定时器的驱动文件。

![[Pasted image 20250106192924.png]]

2.1.2 Keil配置项目结构

将驱动文件添加进Driver文件夹

![[Pasted image 20250106193137.png]]

将timer路径添加进头文件路径中:
![[Pasted image 20250106193245.png]]

2.1.3 编写定时器驱动驱动寄存器

定时器初始化函数:
![[Pasted image 20250106195154.png]]

中断处理函数:
![[Pasted image 20250106195202.png]]

2.2 创建任务与配置中断管理

  1. 配置FreeRTOS中断管理
  2. 起始任务
    1. 用于创建任务1
  3. 任务1
    1. 扫描按键1:关闭中断
    2. 扫描按键2:启动中断

2.2.1 配置FreeRTOS中断管理

配置中断管理的阈值为5,配置滴答定时器的中断优先级为15,配置内核中断优先级为最低级。

![[Pasted image 20250106195427.png]]

2.2.2 起始任务

在启动函数中启动定时器,同时创建起始任务,在起始任务中创建任务1。


void FreeRTOS_Start(void)
{
    /* 启动定时器 */
    Driver_TIM6_Init();
    Driver_TIM6_Start();

    /* 1. 创建启动任务 */
    xTaskCreate(startTask,                                          /* 启动任务执行函数 */
                    START_TASK_NAME,                                /* 启动任务的名称 */
                    START_TASK_STACK_DEPTH,                         /* 启动任务栈大小 = 2 * 128 */
                    NULL,                                           /* 启动任务优先级 */
                    START_TASK_PRIORITY,                            /* 启动任务的控制块 */
                    &startTaskTCB);                               
    printf("创建任务......");

    /* 2. 启动任务调度器 */
    vTaskStartScheduler();
}

void startTask(void *args)
{
    // 1. 代码进入临界区,防止代码中断
    vPortEnterCritical();      
    printf("执行启动任务...");         

    // 2. 创建3个任务
    xTaskCreate(                                        /* 任务1 */
        taskFunc1,
        TASK_NAME_1,
        START_TASK_STACK_DEPTH,
        NULL,
        TASK1_PRIORITY,
        &task1TCB);
    
    // 3. 代码退出临界区
    printf("启动任务执行完毕...\n回收启动任务...");
    vPortExitCritical();

    // 4. 回收启动任务
    vTaskDelete(NULL);
}

2.2.3 任务1

在任务1中进行扫描按键:

  • 按键1:关闭中断
  • 按键2:开启中断
void taskFunc1(void *args)                                  /* 任务1执行函数 */
{
    uint8_t key;
    while (1)
    {
        key = Inf_Key_Detect();
        switch (key)
        {
        case KEY1_PRESS:                                    /* 按下1,关闭中断 */
            portDISABLE_INTERRUPTS();
            debug_printfln("关闭中断...");
            break;
        case KEY2_PRESS:                                    /* 按下2,开启中断 */
            portENABLE_INTERRUPTS();
            debug_printfln("开启中断...");
            break;

        }
        vTaskDelay(20);
    }
}

运行效果:
![[Pasted image 20250106200107.png]]

注意事项,中断的原理是让代码进入了灵界去,因此,在关闭了中断后,不能使用vTaskDelay延时函数,这个函数本身会关闭临界区,从而导致关闭中断失败
![[Pasted image 20250106200231.png]]

3. 总结

FreeRTOS中断管理是为了让系统更加灵活实现任务调度等功能,提高系统的实时性和稳定性,FreeRTOS是通过配置BASEPRI寄存器达到效果的,该寄存器的作用就是让阈值以外的优先级的中断不可用。
portDISABLE_INTERRUPTS函数本身是让代码进入临界区,而vTaskDelay也是使用了相同的原理,因此会让关闭中断效果失效。

文章声明:

  • 本文章为作者学习FreeRTOS实时操作系统的笔记与巩固输出,欢迎同行交流与指教,文章借鉴来源小破站的某谷RTOS教程。
FreeRTOS是一个实时操作系统,它的中断管理是其核心功能之一。在FreeRTOS中,中断管理主要是围绕中断服务例程(ISR)和任务调度来实现的。以下是一些关于FreeRTOS中断管理的关键概念和特性: 1. 中断服务例程(ISR):在FreeRTOS中,当硬件中断发生时,中断服务例程会被调用。ISR应该尽可能简短和快速地执行,因为在其执行期间,中断通常是被禁用的。在ISR中,通常只做必要的硬件状态的保存和恢复,以及设置一个任务通知或信号量等,来通知一个或多个任务中断已经发生。 2. 任务通知:ISR通过FreeRTOS提供的API(例如xSemaphoreGiveFromISR(), xQueueSendFromISR())来通知任务。这些函数允许ISR将事件传递给任务,而不需要任务处于阻塞状态。 3. 中断优先级和FreeRTOS优先级:FreeRTOS可以运行在具有多种中断优先级的硬件上。通常,FreeRTOS会为自己的任务分配高于或等于最低硬件中断优先级的优先级,以确保中断不会被低优先级的任务阻塞。 4. 响应中断:当中断发生时,FreeRTOS的任务调度器会根据当前的中断处理和系统状态来决定是否进行任务切换。如果有必要,调度器会在ISR完成后切换到适当的高优先级任务。 5. 中断和上下文切换:FreeRTOS的上下文切换是由中断触发的,特别是由系统时钟中断触发,它允许调度器周期性地检查是否有更高优先级的任务准备运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值