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

STM32 FreeRTOS中断管理

STM32 FreeRTOS 中断管理
一、中断优先级配置
在STM32上使用FreeRTOS时,合理配置中断优先级是非常重要的。STM32使用8位宽的寄存器来配置中断的优先等级,但实际只使用了高4位(7:4),因此提供了最大16级的中断优先级。中断优先级数值越小,优先级越高。
二、中断优先级分组
STM32的中断优先级可以分为抢占优先级和子优先级:
•  抢占优先级:抢占优先级高的中断可以打断正在执行但抢占优先级低的中断。
•  子优先级:当同时发生具有相同抢占优先级的中断时,子优先级数值小的优先执行,但不能互相打断。
为了方便FreeRTOS管理,建议将所有优先级位指定为抢占优先级位,即将优先级分组设置为组4。可以通过以下代码设置:
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

这样,4位优先级就都作为抢占优先级,没有子优先级,共有0~15共16个优先级。
三、FreeRTOS 中断管理
1. 中断优先级配置
FreeRTOS通过宏configMAX_SYSCALL_INTERRUPT_PRIORITY来定义可管理的最高中断优先级。例如:
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (5 << 4)

这意味着FreeRTOS可以管理优先级数值大于等于5的中断。
2. 中断服务例程(ISR)
在中断服务例程中,如果需要调用FreeRTOS的API函数,只能使用带“FromISR”后缀的函数。例如:
xQueueSendFromISR(queue, &data, &higherPriorityTaskWoken);

这样可以确保在中断服务例程中安全地与FreeRTOS任务进行通信。
3. 临界区保护
FreeRTOS提供了宏taskENTER_CRITICAL()和taskEXIT_CRITICAL()来进入和退出临界区。这些宏通过禁用和启用中断来保护临界区代码。例如:
void vPortEnterCritical(void) {
    portDISABLE_INTERRUPTS();
    uxCriticalNesting++;
    if (uxCriticalNesting == 1) {
        configASSERT((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK) == 0);
    }
}

void vPortExitCritical(void) {
    configASSERT(uxCriticalNesting);
    uxCriticalNesting--;
    if (uxCriticalNesting == 0) {
        portENABLE_INTERRUPTS();
    }
}

这些宏确保在临界区代码执行期间,不会被其他中断打断,从而保证操作的原子性。
四、中断控制器配置
在使用FreeRTOS时,需要合理配置中断控制器。例如,设置SysTick和PendSV中断的优先级:
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (5 << 4)
NVIC_SetPriorityGrouping(0);
NVIC_SetPriority(SysTick_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY);
NVIC_SetPriority(PendSV_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY);

这样可以确保FreeRTOS的系统任务切换不会阻塞其他中断的响应。
五、延迟中断处理
FreeRTOS采用延迟中断处理机制,将中断处理任务延迟到RTOS任务中执行。例如:
•  t1-t2这段时间低优先级的任务Task1正在执行,高优先级的任务Task2因等待事件被阻塞。
•  t2时刻发生了中断,该中断就是Task2等待的事件,因此Task2进入就绪态。
•  t3时刻中断服务程序执行完毕,由于就绪任务中Task2优先级更高,因此调度器选择Task2进入运行态。
六、实际案例
以下是一个实际案例,展示了如何在STM32上使用FreeRTOS进行中断处理和任务调度:
1. 初始化代码
#include "stm32f10x.h"
#include "OLED.h"
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOS_experiment.h"
#include "Key.h"
#include "LED.h"
#include "Timer.h"

int main(void) {
    Key_Init();
    LED_Init();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    Timer2_Init();
    Timer3_Init();
    FreeRTOS_Test();
    while (1) {
    }
}

void TIM2_IRQHandler(void) {
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) {
        LED1_Turn();
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

void TIM3_IRQHandler(void) {
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) {
        LED2_Turn();
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    }
}

2. 任务创建和调度
#include "FreeRTOS.h"
#include "task.h"
#include "LED.h"
#include "Key.h"
#include "Delay.h"

#define START_TASK_STACK_SIZE 128
#define START_TASK_PRIO       1
#define TASK3_STACK_SIZE      128
#define TASK3_PRIO            4

void start_task(void);
void task3(void);
TaskHandle_t start_task_handler;
TaskHandle_t task3_handler;

void FreeRTOS_Test(void) {
    xTaskCreate((TaskFunction_t)start_task,
                "start_task",
                START_TASK_STACK_SIZE,
                NULL,
                START_TASK_PRIO,
                (TaskHandle_t *)&start_task_handler);
    vTaskStartScheduler();
}

void start_task(void) {
    taskENTER_CRITICAL();
    xTaskCreate((TaskFunction_t)task3,
                "task3",
                TASK3_STACK_SIZE,
                NULL,
                TASK3_PRIO,
                (TaskHandle_t *)&task3_handler);
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();
}

void task3(void) {
    uint8_t key = 0;
    while (1) {
        key = Key_GetNum();
        if (key == 1) {
            portDISABLE_INTERRUPTS();
        }
        if (key == 2) {
            portENABLE_INTERRUPTS();
        }
        Delay_ms(10);
    }
}

七、总结
通过合理配置中断优先级、使用临界区保护、延迟中断处理等机制,FreeRTOS可以在STM32上实现高效、稳定的中断管理。这些机制不仅提高了系统的实时性,还确保了任务调度的正确性和可靠性。


http://www.kler.cn/a/506040.html

相关文章:

  • docker 部署 MantisBT
  • JDK8新特性
  • Redis集群部署详解:主从复制、Sentinel哨兵模式与Cluster集群的工作原理与配置
  • TensorFlow深度学习实战(5)——神经网络性能优化技术详解
  • Kylin Linux V10 替换安装源,并在服务器上启用 EPEL 仓库
  • 我这不需要保留本地修改, 只需要拉取远程更改
  • 语音识别的预训练模型
  • 初始Java5
  • 49.字母异位词
  • 单芯片控制多个高性能伺服电机
  • 【Linux】多路转接select
  • PyTorch使用教程(1)—PyTorch简介
  • MongoDB 学习建模与设计思路--统计数据更新案例
  • Ubuntu本地部署网站
  • 实现小球不断往下滚动
  • LabVIEW实现油浸式变压器自主监测与实时报告
  • tplink rt406路由器如何配置端口映射
  • 人脸识别SDK(Android)之Github示例及集成详解
  • C语言初阶习题【29】杨氏矩阵
  • 代码随想录算法训练营day30
  • python爬虫根据需要查找某个链接并保存
  • 阿里云 EMR 发布托管弹性伸缩功能,支持自动调整集群大小,最高降本60%
  • 如何解决 XGBoost 控制台警告:版本不一致导致的模型加载问题
  • day10_Structured Steaming
  • 【MATLAB代码】CV和CA模型组成的IMM(滤波方式为UKF),可复制粘贴源代码
  • 神经网络常见操作(卷积)输入输出