STM32 HAL库FreeRTOS 中断管理

一、引言

在嵌入式系统开发中,STM32 微控制器凭借其高性能、低功耗和丰富的外设资源,被广泛应用于各种领域。FreeRTOS 作为一款轻量级、开源且功能强大的实时操作系统,为多任务处理提供了良好的支持。中断是嵌入式系统中实现实时响应外部事件的重要机制,合理管理中断对于系统的稳定性和实时性至关重要。本文将深入探讨基于 STM32 HAL 库与 FreeRTOS 的中断管理,详细介绍中断的基本概念、STM32 的中断机制、FreeRTOS 对中断的处理方式以及如何在两者结合的环境下进行有效的中断管理。

二、中断基本概念

2.1 中断的定义

中断是指 CPU 在执行程序的过程中,遇到外部或内部的紧急事件需要处理时,暂时停止当前程序的执行,转去执行相应的中断服务程序,处理完中断事件后,再返回原来被中断的程序继续执行。中断机制使得系统能够及时响应外部事件,提高了系统的实时性和处理能力。

2.2 中断的分类

  • 硬件中断:由外部硬件设备产生的中断请求,如按键按下、定时器溢出、串口接收到数据等。硬件中断又可分为可屏蔽中断和不可屏蔽中断。可屏蔽中断可以通过软件设置来允许或禁止,而不可屏蔽中断通常用于处理紧急事件,不能被软件屏蔽。
  • 软件中断:由软件指令触发的中断,通常用于系统调用、异常处理等。软件中断是程序主动发起的,用于实现特定的功能。

2.3 中断处理流程

中断处理的基本流程包括以下几个步骤:

  1. 中断请求:外部或内部设备向 CPU 发送中断请求信号。
  2. 中断响应:CPU 检测到中断请求后,暂停当前程序的执行,保存现场信息(如寄存器值),然后跳转到相应的中断服务程序入口地址。
  3. 中断服务程序执行:CPU 执行中断服务程序,处理中断事件。
  4. 恢复现场:中断服务程序执行完毕后,恢复之前保存的现场信息,使 CPU 能够继续执行被中断的程序。
  5. 返回主程序:CPU 返回到原来被中断的程序继续执行。

三、STM32 的中断机制

3.1 STM32 中断控制器

STM32 系列微控制器采用了嵌套向量中断控制器(NVIC)来管理中断。NVIC 具有以下特点:

  • 支持多个中断源:STM32 不同型号的芯片支持的中断源数量不同,一般在几十个到上百个之间。
  • 中断优先级管理:NVIC 支持中断优先级分组,每个中断源可以设置不同的抢占优先级和子优先级。抢占优先级高的中断可以打断抢占优先级低的中断服务程序,而子优先级用于在抢占优先级相同的情况下确定中断的执行顺序。
  • 中断嵌套:支持中断嵌套功能,即高优先级的中断可以打断低优先级的中断服务程序,提高了系统的实时响应能力。

3.2 STM32 中断优先级分组

STM32 的 NVIC 支持多种中断优先级分组方式,通过设置 AIRCR 寄存器的 PRIGROUP 位来选择不同的分组方式。不同的分组方式将抢占优先级和子优先级的位数进行了不同的分配,例如:

  • 分组 0:0 位抢占优先级,4 位子优先级。
  • 分组 1:1 位抢占优先级,3 位子优先级。
  • 分组 2:2 位抢占优先级,2 位子优先级。
  • 分组 3:3 位抢占优先级,1 位子优先级。
  • 分组 4:4 位抢占优先级,0 位子优先级。

3.3 STM32 中断处理流程

在 STM32 中,中断处理的基本流程如下:

  1. 中断请求:外部或内部设备产生中断请求信号,通过 GPIO 引脚或内部总线发送到 NVIC。
  2. NVIC 处理:NVIC 检测到中断请求后,根据中断优先级分组和中断源的优先级设置,判断是否响应该中断请求。如果响应,则将中断请求挂起,并通知 CPU。
  3. CPU 响应:CPU 检测到 NVIC 的中断通知后,暂停当前程序的执行,保存现场信息(如寄存器值),然后跳转到相应的中断向量表中查找中断服务程序的入口地址。
  4. 中断服务程序执行:CPU 执行中断服务程序,处理中断事件。
  5. 恢复现场:中断服务程序执行完毕后,恢复之前保存的现场信息,使 CPU 能够继续执行被中断的程序。
  6. 返回主程序:CPU 返回到原来被中断的程序继续执行。

四、FreeRTOS 对中断的处理方式

4.1 FreeRTOS 中断管理的基本原则

FreeRTOS 是一个实时操作系统,需要保证系统的实时性和任务调度的正确性。在处理中断时,FreeRTOS 遵循以下基本原则:

  • 中断服务程序应尽量短小:中断服务程序的执行时间应尽量短,避免长时间占用 CPU 资源,影响其他任务的执行。
  • 中断服务程序中避免调用阻塞函数:在中断服务程序中应避免调用 FreeRTOS 提供的阻塞函数,如 vTaskDelay()xQueueReceive() 等,因为这些函数可能会导致任务调度,而中断服务程序中不允许进行任务调度。
  • 使用中断安全的 API 函数:在中断服务程序中应使用 FreeRTOS 提供的中断安全的 API 函数,如 xSemaphoreGiveFromISR()xQueueSendFromISR() 等,这些函数可以在中断服务程序中安全地调用。

4.2 FreeRTOS 中断优先级配置

FreeRTOS 对中断优先级有一定的要求,需要将中断优先级分为两类:

  • 可管理的中断优先级:这些中断优先级低于 configMAX_SYSCALL_INTERRUPT_PRIORITY,FreeRTOS 可以对这些中断进行管理,在中断服务程序中可以安全地调用 FreeRTOS 提供的中断安全的 API 函数。
  • 不可管理的中断优先级:这些中断优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY,FreeRTOS 无法对这些中断进行管理,在中断服务程序中不允许调用 FreeRTOS 提供的 API 函数。

4.3 FreeRTOS 中断服务程序的编写

在 FreeRTOS 中,编写中断服务程序时需要注意以下几点:

  1. 保存现场信息:在中断服务程序开始时,需要保存现场信息,如寄存器值,以便在中断服务程序执行完毕后恢复现场。
  2. 处理中断事件:根据中断源的类型,处理相应的中断事件,如读取按键状态、处理定时器溢出等。
  3. 使用中断安全的 API 函数:如果需要在中断服务程序中与 FreeRTOS 任务进行通信,可以使用 FreeRTOS 提供的中断安全的 API 函数,如 xSemaphoreGiveFromISR()xQueueSendFromISR() 等。
  4. 恢复现场信息:在中断服务程序执行完毕后,恢复之前保存的现场信息,使 CPU 能够继续执行被中断的程序。

五、基于 STM32 HAL 库与 FreeRTOS 的中断管理实现

5.1 工程搭建

首先,需要使用 STM32CubeMX 工具创建一个基于 STM32 HAL 库和 FreeRTOS 的工程。具体步骤如下:

  1. 打开 STM32CubeMX,选择对应的 STM32 芯片型号。
  2. 配置系统时钟、GPIO 引脚、定时器等外设。
  3. 在 “Middleware” 选项卡中选择 FreeRTOS,配置 FreeRTOS 的相关参数,如任务栈大小、任务优先级等。
  4. 配置中断优先级分组,确保将中断优先级分为可管理的中断优先级和不可管理的中断优先级。
  5. 生成代码,并选择合适的 IDE 进行开发。

5.2 中断初始化

在生成的代码中,需要对中断进行初始化。以下是一个简单的示例,初始化一个外部中断:

#include "stm32xxxx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"// 定义一个信号量句柄
SemaphoreHandle_t xSemaphore;// 外部中断服务函数
void EXTIx_IRQHandler(void)
{BaseType_t xHigherPriorityTaskWoken = pdFALSE;// 清除中断标志位HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_x);// 释放信号量xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);// 如果有更高优先级的任务被唤醒,则进行任务切换portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}// 初始化外部中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if (GPIO_Pin == GPIO_PIN_x){// 处理外部中断事件}
}// 任务函数
void vTaskFunction(void *pvParameters)
{for (;;){// 等待信号量if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdPASS){// 处理信号量事件}}
}// 主函数
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();// 创建信号量xSemaphore = xSemaphoreCreateBinary();if (xSemaphore != NULL){// 初始化信号量为不可用状态xSemaphoreTake(xSemaphore, 0);}// 创建任务xTaskCreate(vTaskFunction, "Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);// 启动调度器vTaskStartScheduler();while (1){// 不会执行到这里}
}

5.3 中断服务程序与任务通信

在中断服务程序中,可以使用 FreeRTOS 提供的中断安全的 API 函数与任务进行通信。例如,使用信号量来通知任务有中断事件发生:

// 中断服务程序
void EXTIx_IRQHandler(void)
{BaseType_t xHigherPriorityTaskWoken = pdFALSE;// 清除中断标志位HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_x);// 释放信号量xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);// 如果有更高优先级的任务被唤醒,则进行任务切换portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}// 任务函数
void vTaskFunction(void *pvParameters)
{for (;;){// 等待信号量if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdPASS){// 处理信号量事件}}
}

5.4 中断优先级管理

在使用 STM32 HAL 库和 FreeRTOS 时,需要合理配置中断优先级。将中断优先级分为可管理的中断优先级和不可管理的中断优先级,确保在可管理的中断服务程序中可以安全地调用 FreeRTOS 提供的中断安全的 API 函数。以下是一个配置中断优先级的示例:

// 配置中断优先级分组
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);// 配置外部中断优先级
HAL_NVIC_SetPriority(EXTIx_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1, 0);
HAL_NVIC_EnableIRQ(EXTIx_IRQn);

六、中断管理的常见问题及解决方法

6.1 中断服务程序执行时间过长

如果中断服务程序执行时间过长,会影响系统的实时性和任务调度的正确性。解决方法是尽量缩短中断服务程序的执行时间,将一些复杂的处理任务放到任务中去执行。例如,可以在中断服务程序中设置一个标志位,然后在任务中检查该标志位并进行相应的处理。

6.2 中断服务程序中调用阻塞函数

在中断服务程序中调用阻塞函数会导致任务调度,而中断服务程序中不允许进行任务调度。解决方法是使用 FreeRTOS 提供的中断安全的 API 函数,如 xSemaphoreGiveFromISR()xQueueSendFromISR() 等,这些函数可以在中断服务程序中安全地调用。

6.3 中断优先级配置错误

如果中断优先级配置错误,可能会导致中断嵌套异常或无法正确处理中断事件。解决方法是仔细配置中断优先级分组和每个中断源的优先级,确保将中断优先级分为可管理的中断优先级和不可管理的中断优先级,并根据实际需求设置合适的优先级。

七、总结

本文详细介绍了基于 STM32 HAL 库与 FreeRTOS 的中断管理。首先介绍了中断的基本概念、STM32 的中断机制和 FreeRTOS 对中断的处理方式。然后,通过实际的代码示例,展示了如何在 STM32 HAL 库和 FreeRTOS 环境下进行中断初始化、中断服务程序与任务通信以及中断优先级管理。最后,讨论了中断管理中常见的问题及解决方法。通过合理的中断管理,可以提高系统的实时性和稳定性,确保系统能够及时响应外部事件。在实际开发中,需要根据具体的应用场景和需求,合理配置中断优先级,编写高效的中断服务程序,以充分发挥 STM32 和 FreeRTOS 的优势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/79917.shtml

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

相关文章

在 UE5 编辑器中,由于游戏设置 -> EV100 设置,点击播放前后的光照不同。如何保持点击播放前后的光照一致?

​In Unreal Engine 5 (UE5), discrepancies in lighting between the editor and play modes are often due to auto exposure settings, particularly when using the EV100 system. To maintain consistent lighting across both modes, follow these steps:​YouTube1Epic …

[python] set

1.添加元素 在 Python 中,向 set 添加一个元素可以使用 add() 方法。如果添加的元素已经存在于 set 中,add() 不会重复添加(因为 set 具有自动去重的特性)。 方法 1:add(element)(添加单个元素&#xff0…

第一期第18讲26:23

shell脚本以 .sh为后缀,里面存放着一行行要运行的linux指令。 shell脚本第一行一定为 #!/bin/bash,表示使用bash。 shell文件举例如下: #!/bin/bash echo "hello shell!" shell文件默认没有可执行权限,因此 chmod 777 m…

解决 Ubuntu 下 VTune 无法收集 CPU 硬件时间计数数据的问题

解决 Ubuntu 下 VTune 无法收集 CPU 硬件时间计数数据的问题 在 Ubuntu 上使用 Intel VTune Profiler 时遇到无法收集 CPU 硬件性能计数器数据的问题,通常是由于权限和系统配置问题导致的。以下是解决方案: 1. 检查并加载性能监控模块 首先确保 Linux…

健康元 以韧性换弹性

拼韧性的时候到了! 一面是复杂的市场、政策环境与医药行业转型所叠加形成的向下压力;一面是AI技术深度赋能医药企业创新加速的向上机遇。 中国药企在经历了一轮群体性低潮期后,进入“结构性”分化的阶段。 在这一阶段上,一些财…

csv数据的读取

在地理信息系统(GIS)项目中,CSV(Comma-Separated Values)文件是一种常见的数据格式,用于存储表格数据。CSV 文件因其简单易用、可被多种软件读取而广泛应用于数据交换和存储。ArcPy 提供了强大的功能&#…

android Stagefright框架

作为Android音视频开发人员,学习Stagefright框架需要结合理论、源码分析和实践验证。以下是系统化的学习路径: 1. 基础准备 熟悉Android多媒体体系 掌握MediaPlayer、MediaCodec、MediaExtractor等核心API的用法。 理解Android的OpenMAX IL&#xff08…

【基于WSAAsyncSelec模型的通信程序设计】

文章目录 一、实验背景与目的二、实验设计与实现思路1. 设计思想2. 核心代码实现 总结 一、实验背景与目的 这次实验主要是为了让大家了解基于 WSAAsyncSelect 模型通信程序的编写、编译和执行过程。通过实践操作,深入掌握这种模型在实现计算机之间通信时的应用。 …

JAVA:利用 Apache Tika 提取文件内容的技术指南

1、简述 Apache Tika 是一个强大的工具,用于从各种文件中提取内容和元数据。📄Tika 支持解析文档、📸图像、🎵音频、🎥视频文件以及其他多种格式,非常适合构建🔍搜索引擎、📂内容管理系统和📊数据分析工具。 样例代码:https://gitee.com/lhdxhl/springboot-…

数码管静态显示一位字符(STC89C52单片机)

#include <reg52.h> sbit ADDR0 P1^0; sbit ADDR1 P1^1; sbit ADDR2 P1^2; sbit ADDR3 P1^3; sbit ENLED P1^4; //用数组来存储数码管的真值表&#xff0c;数组将在下一章详细介绍 unsigned char code LedChar[] { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82…

计算机视觉与深度学习 | 工业视觉缺陷检测如何检小缺陷?背景概述,原理,检测难点,常用的检测算法,算法评估指标,新项目算法选择,算法部署

工业视觉小缺陷检测技术解析 背景概述 工业视觉缺陷检测是智能制造中质量控制的核心环节,而小缺陷检测(如微米级划痕、点状污渍、细微裂纹等)因其目标小、易受干扰等特点,成为技术难点。随着制造业对精度要求提升(如3C电子、半导体、精密零部件行业),传统人工目检和基…

OBS 日期时间.毫秒时间脚本 date-and-time.lua

文章目录 OBS 日期时间.毫秒时间脚本&#xff1a;效果 OBS 日期时间.毫秒时间脚本&#xff1a; obs obslua source_name ""last_text "" format_string "" activated false-- 此函数用于获取精确的毫秒级时间戳&#…

进程和线程(1)

前言&#xff1a; 在计算机中cpu就像一座工厂&#xff0c;这个工厂里面有许多的车间&#xff0c;但是假如工厂的电力有限&#xff0c;一次只能供给一个车间使用&#xff0c;也就是说当一个车间在进行工作的时候&#xff0c;其他车间是不能工作的&#xff08;单个cpu只能运行一…

入门-C编程基础部分:16、 预处理器

飞书文档https://x509p6c8to.feishu.cn/wiki/DzSJwsGiTiXkeCkyEYUcuXbKnbf C 预处理是编译过程中一个单独的步骤&#xff0c;是一个文本替换工具而已。所有的预处理命令都是以井号&#xff08;#&#xff09;开头。 指令描述#define定义宏#ifdef如果宏已经定义&#xff0c;则返…

Ubuntu下安装和卸载MySQL

Ubuntu下安装和卸载MySQL 下面的演示系统版本&#xff1a;Ubuntu 24.04 更新系统软件包 在开始安装之前&#xff0c;建议先更新系统的软件包列表&#xff0c;以确保所有依赖项是最新的。 sudo apt update && sudo apt upgrade -y安装MySQL服务器 Ubuntu的官方软件…

【Python爬虫实战篇】--爬取豆瓣电影信息(静态网页)

网站&#xff0c;&#xff1a;豆瓣电影 Top 250 爬取豆瓣前250电影的信息&#xff0c; F12打开网页控制台&#xff0c;查看网页元素&#xff0c; 发现网页数据直接可以查看到&#xff0c;为静态网页数据&#xff0c;较为简单 目录 1.第一步使用urllib库获取网页 2.第二步使…

【Unity知识点详解】Unity中泛型单例的使用,兼容WebGL

今天来讲下Unity中泛型单例的使用&#xff0c;包含普通单例和继承MonoBehaviour的单例。重点是需要两种泛型单例兼容WebGL平台&#xff0c;话不多说直接开始。 泛型单例的设计目标 作为泛型单例&#xff0c;需要实现以下几个目标&#xff1a; 全局唯一&#xff0c;在程序的整个…

Python进程与线程的深度对比

一、核心概念对比 1. 进程&#xff08;Process&#xff09; 操作系统级独立单元&#xff1a;每个进程拥有独立的内存空间&#xff08;堆、栈、代码段&#xff09; 资源隔离性&#xff1a;崩溃不影响其他进程 多核并行&#xff1a;可充分利用多核CPU资源 2. 线程&#xff0…

Django 入门指南:构建强大的 Web 应用程序

什么是 Django&#xff1f; Django 是一个开源的高层次 Python Web 框架&#xff0c;旨在快速开发安全且可维护的网站。它通过简化常见的 Web 开发任务&#xff0c;帮助开发者专注于开发应用的核心功能。Django 实现了“快速开发”和“尽量少的重复”的理念&#xff0c;提供了…

ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(显示输出类外设之IS31FL3216)

目录 ESP-ADF外设子系统深度解析&#xff1a;esp_peripherals组件架构与核心设计&#xff08;显示输出类外设之IS31FL3216&#xff09;简介模块概述功能定义架构位置核心特性 IS31FL3216外设分析IS31FL3216外设概述IS31FL3216外设层次架构图 IS31FL3216外设API和数据结构外设层…