freeRTOS中断管理简介

freeRTOS中断管理概念

freeRTOS中断管理实验 

实验目的:学会使用 FreeRTOS 的中断管理!
        本实验会使用两个定时器,一个优先级为 4 ,一个优先级为 6 ,注意:系统所管理的优先级范围: 5~15 , 现象:两个定时器每 1s ,打印一段字符串,当关中断时,停止打印,开中断时持续打印。

实验设计:设计两个任务 start_task、task1

start_task:用来创建task1任务

task1:中断测试任务,任务中将调用关中断和开中断函数来体现对中断的管理作用!

btim.h

#ifndef __BTIM_H
#define __BTIM_H

#include "./SYSTEM/sys/sys.h"

/******************************************************************************************/
/* 基本定时器 定义 */

/* TIMX 中断定义 
 * 默认是针对TIM2~TIM5, TIM12~TIM17.
 * 注意: 通过修改这4个宏定义,可以支持TIM1~TIM17任意一个定时器.
 */
 
#define BTIM_TIM3_INT                       TIM3
#define BTIM_TIM3_INT_IRQn                  TIM3_IRQn
#define BTIM_TIM3_INT_IRQHandler            TIM3_IRQHandler
#define BTIM_TIM3_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM3_CLK_ENABLE(); }while(0)  /* TIM3 时钟使能 */

#define BTIM_TIM5_INT                       TIM5
#define BTIM_TIM5_INT_IRQn                  TIM5_IRQn
#define BTIM_TIM5_INT_IRQHandler            TIM5_IRQHandler
#define BTIM_TIM5_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM5_CLK_ENABLE(); }while(0)  /* TIM5 时钟使能 */

/******************************************************************************************/

void btim_tim3_int_init(uint16_t arr, uint16_t psc);
void btim_tim5_int_init(uint16_t arr, uint16_t psc);

#endif

btim.c

#include "./BSP/TIMER/btim.h"
#include "./SYSTEM/USART/usart.h"

TIM_HandleTypeDef g_tim3_handle;      /* 定时器3句柄 */
TIM_HandleTypeDef g_tim5_handle;      /* 定时器5句柄 */

/**
 * @brief       基本定时器TIM3定时中断初始化函数
 * @note
 *              基本定时器的时钟来自APB1,当D2PPRE1≥2分频的时候
 *              基本定时器的时钟为APB1时钟的2倍, 而APB1为120M, 所以定时器时钟 = 240Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值。
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void btim_tim3_int_init(uint16_t arr, uint16_t psc)
{
    BTIM_TIM3_INT_CLK_ENABLE();                                      /* 使能TIM3时钟 */
    
    g_tim3_handle.Instance = BTIM_TIM3_INT;                          /* 通用定时器3 */
    g_tim3_handle.Init.Prescaler = psc;                              /* 分频 */
    g_tim3_handle.Init.CounterMode = TIM_COUNTERMODE_UP;             /* 向上计数器 */
    g_tim3_handle.Init.Period = arr;                                 /* 自动装载值 */
    g_tim3_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;       /* 时钟分频因子 */
    HAL_TIM_Base_Init(&g_tim3_handle);
    
    HAL_NVIC_SetPriority(BTIM_TIM3_INT_IRQn, 4, 0);  /* 设置中断优先级,抢占优先级4,子优先级0 */
    HAL_NVIC_EnableIRQ(BTIM_TIM3_INT_IRQn);          /* 开启ITM3中断 */
    
    HAL_TIM_Base_Start_IT(&g_tim3_handle);           /* 使能定时器3和定时器3更新中断 */
}

/**
 * @brief       基本定时器TIM5定时中断初始化函数
 * @note
 *              基本定时器的时钟来自APB1,当D2PPRE1≥2分频的时候
 *              基本定时器的时钟为APB1时钟的2倍, 而APB1为120M, 所以定时器时钟 = 240Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值。
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void btim_tim5_int_init(uint16_t arr, uint16_t psc)
{
    BTIM_TIM5_INT_CLK_ENABLE();                                      /* 使能TIM5时钟 */
    
    g_tim5_handle.Instance = BTIM_TIM5_INT;                          /* 通用定时器5 */
    g_tim5_handle.Init.Prescaler = psc;                              /* 分频 */
    g_tim5_handle.Init.CounterMode = TIM_COUNTERMODE_UP;             /* 向上计数器 */
    g_tim5_handle.Init.Period = arr;                                 /* 自动装载值 */
    g_tim5_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;       /* 时钟分频因子 */
    HAL_TIM_Base_Init(&g_tim5_handle);
    
    HAL_NVIC_SetPriority(BTIM_TIM5_INT_IRQn, 6, 0);  /* 设置中断优先级,抢占优先级6,子优先级0 */
    HAL_NVIC_EnableIRQ(BTIM_TIM5_INT_IRQn);          /* 开启ITM5中断 */
    
    HAL_TIM_Base_Start_IT(&g_tim5_handle);           /* 使能定时器5和定时器5更新中断 */
}

/**
 * @brief       定时器中断服务函数
 * @param       无
 * @retval      无
 */
void BTIM_TIM3_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_tim3_handle);
}

/**
 * @brief       定时器中断服务函数
 * @param       无
 * @retval      无
 */
void BTIM_TIM5_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_tim5_handle);
}

/**
 * @brief       定时器更新中断回调函数
* @param        htim:定时器句柄指针
 * @retval      无
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == (&g_tim3_handle))
    {
        printf("TIM3输出\r\n");
    }
    else if (htim == (&g_tim5_handle))
    {
        printf("TIM5输出\r\n");
    }
}

freertos_demo.c

#include "freertos_demo.h"
#include "./SYSTEM/DELAY/delay.h"
#include "./SYSTEM/USART/usart.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/TIMER/btim.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

/******************************************************************************************************/

/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    
    xTaskCreate((TaskFunction_t )start_task,            /* 任务函数 */
                (const char*    )"start_task",          /* 任务名称 */
                (uint16_t       )START_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )START_TASK_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&StartTask_Handler);   /* 任务句柄 */
    vTaskStartScheduler();
}

/**
 * @brief       start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           /* 进入临界区 */
    /* 初始化TIM3、TIM5 */
    btim_tim3_int_init(10000-1, 7200-1);
    btim_tim5_int_init(10000-1, 7200-1);
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
}

/**
 * @brief       task1
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task1(void *pvParameters)
{
    uint32_t task1_num = 0;
    
    while (1)
    {
        if (++task1_num == 5)
        {
            printf("FreeRTOS关闭中断\r\n");
            portDISABLE_INTERRUPTS();       /* FreeRTOS关闭中断 */
            delay_ms(5000);
            printf("FreeRTOS打开中断\r\n");
            portENABLE_INTERRUPTS();        /* FreeRTOS打开中断 */
        }
        
        vTaskDelay(1000);
    }
}

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、付费专栏及课程。

余额充值