首页 > 其他分享 >FreeRTOS 中断与任务优先级关系及中断延迟处理(建议收藏!!!)

FreeRTOS 中断与任务优先级关系及中断延迟处理(建议收藏!!!)

时间:2024-12-06 22:32:45浏览次数:8  
标签:优先级 FreeRTOS 中断 void 任务 串口 USART1

一、引言

在 FreeRTOS 操作系统中,中断和任务是构建系统功能的重要组成部分。理解它们之间的优先级关系以及特殊的中断处理机制,如中断延迟处理,对于开发高效、稳定且具有良好实时性的嵌入式系统至关重要。本文将详细探讨这些概念,并提供相关代码示例以加深理解。

二、中断与任务优先级关系

(一)理论概述

在 FreeRTOS 环境下,中断优先级高于任务优先级是一个基本原则。中断由硬件触发,用于处理对时间要求极为严格的事件,如硬件设备的紧急数据传输或关键的定时事件。当一个中断发生时,无论当前正在执行的任务优先级多高,处理器都会立即暂停任务执行,转而进入中断服务程序(ISR)处理中断。只有在所有中断都处理完毕(即没有中断处于活动状态)时,任务调度器才会根据任务的优先级来选择并执行就绪任务。这种设计确保了系统能够迅速响应硬件事件,满足系统的实时性需求。

(二)代码示例

以下是一个简单的代码示例,用于演示中断与任务优先级关系。假设我们有一个简单的嵌入式系统,其中包含一个按键中断和两个任务:一个高优先级任务和一个低优先级任务。

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stm32f4xx.h"  // 以 STM32F4 为例,不同平台头文件不同

// 定义任务堆栈大小
#define HIGH_PRIORITY_TASK_STACK_SIZE 128
#define LOW_PRIORITY_TASK_STACK_SIZE 128

// 任务句柄
TaskHandle_t highPriorityTaskHandle;
TaskHandle_t lowPriorityTaskHandle;

// 按键中断处理函数
void EXTI0_IRQHandler(void)
{
    // 清除中断标志位,具体根据硬件手册操作
    GPIOA->ICR |= GPIO_ICR_IT0;  
    // 这里可以添加简单的中断处理代码,如记录按键按下次数等
    // 由于中断优先级高于任务,此时任务不会执行
    // 例如:
    // static uint8_t keyPressCount = 0;
    // keyPressCount++;
}

// 高优先级任务函数
void highPriorityTask(void *pvParameters)
{
    for (;;)
    {
        // 高优先级任务的执行代码
        // 例如:
        // printf("High priority task is running\n");
        // 可以进行一些数据处理等操作
        vTaskDelay(pdMS_TO_TICKS(1000));  // 延迟 1 秒,让出 CPU 时间
    }
}

// 低优先级任务函数
void lowPriorityTask(void *pvParameters)
{
    for (;;)
    {
        // 低优先级任务的执行代码
        // 例如:
        // printf("Low priority task is running\n");
        // 进行一些相对不紧急的操作
        vTaskDelay(pdMS_TO_TICKS(2000));  // 延迟 2 秒,让出 CPU 时间
    }
}

int main(void)
{
    // 初始化硬件相关设置,如时钟、GPIO 等

    // 配置按键中断
    // 以 STM32F4 为例,假设按键连接到 PA0,配置为下降沿触发中断
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;  // 使能 GPIOA 时钟
    GPIOA->MODER &= ~GPIO_MODER_MODER0;  // 设置为输入模式
    GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR0;  // 无上拉下拉电阻
    SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR1_EXTI0;  // 选择 PA0 作为 EXTI0 源
    SYSCFG->EXTICR[1] &= ~SYSCFG_EXTICR2_EXTI0;
    SYSCFG->EXTICR[2] &= ~SYSCFG_EXTICR3_EXTI0;
    EXTI->IMR |= EXTI_IMR_MR0;  // 使能 EXTI0 中断屏蔽
    EXTI->FTSR |= EXTI_FTSR_TR0;  // 配置为下降沿触发

    // 创建高优先级任务
    xTaskCreate(highPriorityTask, "HighPriorityTask", HIGH_PRIORITY_TASK_STACK_SIZE, NULL, 2, &highPriorityTaskHandle);

    // 创建低优先级任务
    xTaskCreate(lowPriorityTask, "LowPriorityTask", LOW_PRIORITY_TASK_STACK_SIZE, NULL, 1, &lowPriorityTaskHandle);

    // 启动 FreeRTOS 调度器
    vTaskStartScheduler();

    while (1);  // 正常情况下不会执行到这里
}

在上述代码中,当按键按下产生中断时,即使高优先级任务正在执行,处理器也会立即跳转到 EXTI0_IRQHandler 函数中处理中断。只有在中断处理完成后,才会根据任务优先级来决定是继续执行高优先级任务还是低优先级任务。
 

三、中断的延迟处理

(一)理论概述

在某些情况下,硬件中断的处理可能非常耗时。如果在中断服务程序中直接处理所有事务,可能会导致其他低优先级中断无法及时响应(因为高优先级中断服务程序执行期间会屏蔽低优先级中断),同时也会使任务长时间得不到执行,导致系统出现卡顿现象。为了解决这个问题,FreeRTOS 采用了中断延迟处理机制。该机制将中断处理分为两部分:在中断服务程序(ISR)中,尽快完成一些必要的清理和记录工作,然后触发一个任务来处理更复杂、耗时的操作。这样可以保证中断响应的及时性,同时也不会影响系统的整体性能和任务的执行。

(二)代码示例

以下是一个中断延迟处理的代码示例。假设我们有一个串口接收中断,接收大量数据并进行处理。

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stm32f4xx.h"  // 以 STM32F4 为例,不同平台头文件不同

// 定义任务堆栈大小
#define SERIAL_RX_TASK_STACK_SIZE 256

// 任务句柄
TaskHandle_t serialRxTaskHandle;

// 串口接收缓冲区
uint8_t serialRxBuffer[100];
// 记录串口接收数据长度
uint16_t serialRxLength;

// 串口中断处理函数
void USART1_IRQHandler(void)
{
    if (USART1->SR & USART_SR_RXNE)  // 接收到数据
    {
        // 快速将数据存入接收缓冲区
        serialRxBuffer[serialRxLength++] = USART1->DR;
        // 如果接收数据达到一定长度,触发串口接收任务
        if (serialRxLength >= 100)
        {
            xTaskNotifyGiveFromISR(serialRxTaskHandle, NULL);
            serialRxLength = 0;  // 重置接收长度
        }
        // 清除中断标志位,具体根据硬件手册操作
        USART1->SR &= ~USART_SR_RXNE;  
    }
}

// 串口接收任务函数
void serialRxTask(void *pvParameters)
{
    for (;;)
    {
        // 等待串口中断通知
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        // 在这里进行复杂的串口数据处理
        // 例如:数据解析、校验等操作
        // 可以将处理后的数据传递给其他任务或进行进一步操作
        // printf("Serial receive task is processing data\n");
    }
}

int main(void)
{
    // 初始化硬件相关设置,如时钟、USART1 等

    // 配置串口中断
    // 以 STM32F4 为例,假设串口 1 配置为常用参数
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;  // 使能 USART1 时钟
    // 配置 USART1 的波特率、数据位、停止位等参数
    // 这里省略具体配置代码

    // 使能 USART1 接收中断
    USART1->CR1 |= USART_CR1_RXNEIE;

    // 创建串口接收任务
    xTaskCreate(serialRxTask, "SerialRxTask", SERIAL_RX_TASK_STACK_SIZE, NULL, 2, &serialRxTaskHandle);

    // 启动 FreeRTOS 调度器
    vTaskStartScheduler();

    while (1);  // 正常情况下不会执行到这里
}

在这个示例中,串口接收中断服务程序 USART1_IRQHandler 只负责将接收到的数据快速存入缓冲区,并在接收数据达到一定长度时触发 serialRxTask 任务。serialRxTask 任务则在等待中断通知后,进行复杂的数据处理工作。这样,即使串口接收数据量很大,也不会因为中断处理时间过长而影响系统的其他功能和任务执行。

四、总结

在 FreeRTOS 中,正确理解中断与任务的优先级关系以及合理运用中断延迟处理机制对于构建高效、稳定的嵌入式系统具有重要意义。通过合理安排中断和任务的工作内容,可以充分发挥 FreeRTOS 的优势,满足系统在实时性、响应性和性能方面的要求,为开发复杂的嵌入式应用提供坚实的基础。

“学如逆水行舟,不进则退。”愿此篇文章成为你在技术之舟上的有力浆橹。有任何感悟或困惑,可于评论区交流探讨。若觉有益,点赞,收藏不妨一试,也期待你关注我。在技术的漫漫征途中,愿与君相伴而行,共赏知识繁花盛景,同历成长蜕变之喜。

标签:优先级,FreeRTOS,中断,void,任务,串口,USART1
From: https://blog.csdn.net/2401_83606346/article/details/144301379

相关文章

  • Freertos学习笔记(五)
    此篇文章在2022年2月12日被记录二进制信号量计数型信号量Mutex互斥量递归互斥量第十四课二进制信号量#include"freertos/semphr.h"xSemaphoreCreateBinary();SemphoreHandle_tHandle;//二进制信号量Handle=xSemaphoreCreateBinary();//创建xSemaphoreGive(Hand......
  • Freertos学习笔记(四)
    此篇文章在2022年2月12日被记录队列集合、队列邮箱、软件定时器第十一课队列集合多个Task写队列数据,一个Task读取队列数据QueueSet新建两个消息队列,句柄给两个发送函数,新建一个QSet句柄使用xQueueAddToSet分别添加两个消息队列到Qset在接收函数中,算了···这个是用的......
  • Freertos学习笔记(一)
    此篇文章在2022年1月29日被记录系统启动流程、Task创建与删除、Task参数传入本freertos笔记基于esp32-idf开发第一课系统启动流程第一阶段bootloader第二阶段bootloader第三阶段应用程序入口在components文件夹下有bootloader两个阶段的源代码、也有freertos的源代码......
  • 单片机中的中断处理过程
    单片机(MicrocontrollerUnit,MCU)是一种集成了处理器、存储器以及输入输出接口的微型计算机,广泛应用于各种嵌入式系统中。在单片机的应用开发中,中断系统是不可或缺的一部分,它使得单片机能及时响应并处理外部或内部的中断请求,从而实现高效的任务调度与管理。中断的基本概念中......
  • 全网最迅速的移植FreeRTOS到天空星GD32F407VET6
    注:最最最重要的若出现如图所示问题,请按第二张图片操作1、添加FreeRTOS源码    将我分享的文件复制粘贴到需要移植的开发板例程文件中2、向工程分组中添加文件打开基础工程,新建分组FreeRTOS_CORE和FreeRTOS_PORTABLE,然后向这两个分组中添加文件,如图所示:3、添......
  • STM32 串口进入中断,但是没有检查到接收数据位!!!!
    最近做项目有概率遇到串口进入中断(LED闪烁来判断),但是没有检查到接收数据位USART_IT_RXNE,导致一直卡在判断语句USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET,导致程序卡死。通过keil调试模式的软件复位都没有用,需要硬件复位才行。通过百度发现这个现象挺常见的。这边我也......
  • nginx中的正则表达式,location路径匹配规则和优先级 转载
    博客园熊仔其人原创,侵权删,前言,我这里验证的nginx-v1.23.2单机环境下的nginx中的正则表达式、location路径匹配规则和优先级。先准备好环境,基础配置是这样nginx/conf/conf.d/host.conf:server{listen8081;server_name10.90.5.70;proxy_connect_timeout60;pr......
  • 全球最大分类广告商的Karpenter落地实践:减负运维、减少中断、每月省21万 (下)
    原文链接:https://medium.com/adevinta-tech-blog/the-karpenter-effect-redefining-our-kubernetes-operations-80c7ba90a599编译:CloudPilotAI在上一篇文章中,我们介绍了Adevinta迁移至Karpenter后如何利用这一开源工具为运维团队减负、增强应用稳定性以及实现成本优化(月......
  • 一不小心就容易出错的c语言运算符优先级
      有些人说c语言是简洁高效的,又有些人说c语言是深邃复杂的,说实话,这确实是仁者见仁智者见智。但是有一点不可否认,c语言中的运算符众多,不注意的话,确实很容易弄错。一、*与.的优先级比较  对于一个结构体p包含一个指针*f,那么*p.f的运算优先规则是怎样?  *p.f=*(p......
  • ssh连接linux服务器中断后,如何让命令继续在服务器运行
    ssh连接linux服务器中断后,如何让命令继续在服务器运行这个问题也许是我们这些小白比较头疼的问题,尤其对于做机器学习需要花很久的时间才能训练出一个结果。然而就在这时,因为各种不可抗力我们使用ssh连接服务器时,ssh的窗口突然断开了连接,那么在服务器上跑的程序就也跟着断掉了,之前......