05_FreeRTOS中斷管理

爱吃冰激凌的黄某某發表於2024-03-21

FreeRTOS中斷管理

什麼是中斷?

image-20240320170332894

中斷優先順序分組設定

image-20240320170345479

不同時發生具有相同搶佔優先順序的兩個中斷時,順序執行

image-20240320170355917

image-20240320170406132

中斷相關暫存器

image-20240320170421525

每個地址儲存8位

image-20240321003034191

FreeRTOS如何配置PendSV和Systick中斷優先順序?

image-20240320170610328

image-20240320170631489

image-20240320170639374

image-20240320170649951

image-20240320170657507

FreeRTOS中斷管理實驗

image-20240320170710929

程式碼

btim.c

/**
 ****************************************************************************************************
 * @file        btim.c
 * @author      正點原子團隊(ALIENTEK)
 * @version     V1.0
 * @date        2021-10-15
 * @brief       基本定時器 驅動程式碼
 * @license     Copyright (c) 2020-2032, 廣州市星翼電子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 實驗平臺:正點原子 探索者 F407開發板
 * 線上影片:www.yuanzige.com
 * 技術論壇:www.openedv.com
 * 公司網址:www.alientek.com
 * 購買地址:openedv.taobao.com
 *
 * 修改說明
 * V1.0 20211015
 * 第一次釋出
 *
 ****************************************************************************************************
 */

#include "./BSP/LED/led.h"
#include "./BSP/TIMER/btim.h"
#include "./SYSTEM/usart/usart.h"


TIM_HandleTypeDef g_timx_handler;         /* 定時器引數控制代碼 */
TIM_HandleTypeDef g_tim7_handler;         /* 定時器引數控制代碼 */

/**
 * @brief       基本定時器TIMX定時中斷初始化函式
 * @note
 *              基本定時器的時鐘來自APB1,當PPRE1 ≥ 2分頻的時候
 *              基本定時器的時鐘為APB1時鐘的2倍, 而APB1為42M, 所以定時器時鐘 = 84Mhz
 *              定時器溢位時間計算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定時器工作頻率,單位:Mhz
 *
 * @param       arr : 自動重灌值。
 * @param       psc : 時鐘預分頻數
 * @retval      無
 */
void btim_timx_int_init(uint16_t arr, uint16_t psc)
{
    g_timx_handler.Instance = BTIM_TIMX_INT;                      /* 定時器x */
    g_timx_handler.Init.Prescaler = psc;                          /* 分頻 */
    g_timx_handler.Init.CounterMode = TIM_COUNTERMODE_UP;         /* 遞增計數模式 */
    g_timx_handler.Init.Period = arr;                             /* 自動裝載值 */
    HAL_TIM_Base_Init(&g_timx_handler);
    
    HAL_TIM_Base_Start_IT(&g_timx_handler);                       /* 使能定時器x和定時器更新中斷 */
}

/* TIM7初始化函式 */
void btim_tim7_int_init(uint16_t arr, uint16_t psc)
{
    g_tim7_handler.Instance = BTIM_TIM7_INT;                      /* 定時器x */
    g_tim7_handler.Init.Prescaler = psc;                          /* 分頻 */
    g_tim7_handler.Init.CounterMode = TIM_COUNTERMODE_UP;         /* 遞增計數模式 */
    g_tim7_handler.Init.Period = arr;                             /* 自動裝載值 */
    HAL_TIM_Base_Init(&g_tim7_handler);
    
    HAL_TIM_Base_Start_IT(&g_tim7_handler);                       /* 使能定時器x和定時器更新中斷 */
}

/**
 * @brief       定時器底層驅動,開啟時鐘,設定中斷優先順序
                此函式會被HAL_TIM_Base_Init()函式呼叫
 * @param       無
 * @retval      無
 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        BTIM_TIMX_INT_CLK_ENABLE();                     /* 使能TIMx時鐘 */
        HAL_NVIC_SetPriority(BTIM_TIMX_INT_IRQn, 6, 0); /* 搶佔6,子優先順序0 */
        HAL_NVIC_EnableIRQ(BTIM_TIMX_INT_IRQn);         /* 開啟ITMx中斷 */
    }
	
	if (htim->Instance == BTIM_TIM7_INT)
    {
        BTIM_TIM7_INT_CLK_ENABLE();                     /* 使能TIM7時鐘 */
        HAL_NVIC_SetPriority(BTIM_TIM7_INT_IRQn, 4, 0); /* 搶佔4,子優先順序0 */
        HAL_NVIC_EnableIRQ(BTIM_TIM7_INT_IRQn);         /* 開啟ITM7中斷 */
    }
}

/**
 * @brief       基本定時器TIMX中斷服務函式
 * @param       無
 * @retval      無
 */
void BTIM_TIMX_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_timx_handler);  /* 定時器回撥函式 */
}

/* 基本定時器TIM7中斷服務函式 */
void BTIM_TIM7_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_tim7_handler);  /* 定時器回撥函式 */
}

/**
 * @brief       回撥函式,定時器中斷服務函式呼叫
 * @param       無
 * @retval      無
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        printf("TIM6正在執行\r\n");
    }
	else if (htim->Instance == BTIM_TIM7_INT)
    {
        printf("TIM7正在執行\r\n");
    }
}

btim.h

/**
 ****************************************************************************************************
 * @file        btim.h
 * @author      正點原子團隊(ALIENTEK)
 * @version     V1.0
 * @date        2021-10-15
 * @brief       基本定時器 驅動程式碼
 * @license     Copyright (c) 2020-2032, 廣州市星翼電子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 實驗平臺:正點原子 探索者 F407開發板
 * 線上影片:www.yuanzige.com
 * 技術論壇:www.openedv.com
 * 公司網址:www.alientek.com
 * 購買地址:openedv.taobao.com
 *
 * 修改說明
 * V1.0 20211015
 * 第一次釋出
 *
 ****************************************************************************************************
 */

#ifndef __BTIM_H
#define __BTIM_H

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


/******************************************************************************************/
/* 基本定時器 定義 */

/* TIMX 中斷定義 
 * 預設是針對TIM6/TIM7
 * 注意: 透過修改這4個宏定義,可以支援TIM1~TIM8任意一個定時器.
 */
 
#define BTIM_TIMX_INT                       TIM6
#define BTIM_TIMX_INT_IRQn                  TIM6_DAC_IRQn
#define BTIM_TIMX_INT_IRQHandler            TIM6_DAC_IRQHandler
#define BTIM_TIMX_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM6_CLK_ENABLE(); }while(0)  /* TIM6 時鐘使能 */

#define BTIM_TIM7_INT                       TIM7
#define BTIM_TIM7_INT_IRQn                  TIM7_IRQn
#define BTIM_TIM7_INT_IRQHandler            TIM7_IRQHandler
#define BTIM_TIM7_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM7_CLK_ENABLE(); }while(0)  /* TIM7 時鐘使能 */

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

void btim_timx_int_init(uint16_t arr, uint16_t psc);    /* 基本定時器 定時中斷初始化函式 */
void btim_tim7_int_init(uint16_t arr, uint16_t psc);    /* 基本定時器 定時中斷初始化函式 */

#endif

main.c

/**
 ****************************************************************************************************
 * @file        main.c
 * @author      正點原子團隊(ALIENTEK)
 * @version     V1.0
 * @date        2021-11-04
 * @brief       任務掛起和恢復 實驗
 * @license     Copyright (c) 2020-2032, 廣州市星翼電子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 實驗平臺:正點原子 探索者 F407開發板
 * 線上影片:www.yuanzige.com
 * 技術論壇:www.openedv.com
 * 公司網址:www.alientek.com
 * 購買地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SRAM/sram.h"
#include "./MALLOC/malloc.h"
#include "freertos_demo.h"
#include "./BSP/TIMER/btim.h"

int main(void)
{

    HAL_Init();                         /* 初始化HAL庫 */
    sys_stm32_clock_init(336, 8, 2, 7); /* 設定時鐘,168Mhz */
    delay_init(168);                    /* 延時初始化 */
    usart_init(115200);                 /* 串列埠初始化為115200 */
    led_init();                         /* 初始化LED */
    lcd_init();                         /* 初始化LCD */
    key_init();                         /* 初始化按鍵 */
    sram_init();                        /* SRAM初始化 */
	
	btim_timx_int_init(10000-1,8400-1);
	btim_tim7_int_init(10000-1,8400-1);
    my_mem_init(SRAMIN);                /* 初始化內部SRAM記憶體池 */
    my_mem_init(SRAMEX);                /* 初始化外部SRAM記憶體池 */
    my_mem_init(SRAMCCM);               /* 初始化內部CCM記憶體池 */
	
    freertos_demo();
    
}

freertos_demo.c

/**
 ****************************************************************************************************
 * @file        freertos.c
 * @author      正點原子團隊(ALIENTEK)
 * @version     V1.4
 * @date        2022-01-04
 * @brief       FreeRTOS 移植實驗
 * @license     Copyright (c) 2020-2032, 廣州市星翼電子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 實驗平臺:正點原子 探索者F407開發板
 * 線上影片:www.yuanzige.com
 * 技術論壇:www.openedv.com
 * 公司網址:www.alientek.com
 * 購買地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

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

/* START_TASK 任務 配置
 * 包括: 任務控制代碼 任務優先順序 堆疊大小 建立任務
 */
 #define START_TASK_STACK_SIZE 	128
 #define START_TASK_PRIO		1
 TaskHandle_t start_task_handler;
 
 #define TASK1_STACK_SIZE 	128
 #define TASK1_PRIO		2
 TaskHandle_t task1_handler;
 
void start_task( void * pvParameters );

void task1( void * pvParameters )
{
	uint8_t task1_num = 0;
	while(1)
	{
		if(++task1_num == 5)
		{
			task1_num = 0;
			printf("關中斷\r\n");
			portDISABLE_INTERRUPTS();
			delay_ms(5000);
			printf("開中斷\r\n");
			portENABLE_INTERRUPTS();
		}
		vTaskDelay(1000);
	}
}

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

/**
 * @brief       FreeRTOS例程入口函式
 * @param       無
 * @retval      無
 */
void freertos_demo(void)
{
    xTaskCreate(start_task, "start_task", START_TASK_STACK_SIZE, NULL, START_TASK_PRIO, &start_task_handler);
    vTaskStartScheduler();
}

void start_task( void * pvParameters )
{
	taskENTER_CRITICAL(); //進入臨界區
	xTaskCreate(task1, "task1", TASK1_STACK_SIZE, NULL, TASK1_PRIO, &task1_handler);
    vTaskDelete(NULL);
	taskEXIT_CRITICAL(); //退出臨界區
}