FreeRTOS的任務掛起與恢復
任務的掛起與恢復的API函式
任務掛起函式介紹
任務恢復函式介紹
任務優先順序:數值越大,優先順序越高
中斷優先順序:數值越小,優先順序越高
使用中斷任務恢復時要確保在啟動 RTOS 之前呼叫
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
所有優先順序位都指定為搶佔優先順序位。
任務掛起與恢復實驗
任務掛起函式內部實現
任務恢復函式內部實現
程式碼
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"
/*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;
#define TASK2_STACK_SIZE 128
#define TASK2_PRIO 3
TaskHandle_t task2_handler;
#define TASK3_STACK_SIZE 128
#define TASK3_PRIO 4
TaskHandle_t task3_handler;
void start_task( void * pvParameters );
void task1( void * pvParameters )
{
uint32_t task1_num = 0;
while(1)
{
printf("task1_num:%d!!!\r\n", ++task1_num);
LED0_TOGGLE();
vTaskDelay(500);
}
}
void task2( void * pvParameters )
{
uint32_t task2_num = 0;
while(1)
{
printf("task2_num:%d!!!\r\n", ++task2_num);
LED1_TOGGLE();
vTaskDelay(500);
}
}
/*
* 按鍵0:任務1掛起
* 按鍵1:任務1恢復
*/
void task3( void * pvParameters )
{
uint8_t key = 0;
while(1)
{
key=key_scan(0);
if(key == KEY0_PRES)
{
if(task1_handler!=NULL)
{
vTaskSuspend(task1_handler);
printf("掛起task1\r\n");
}
}
else if(key == KEY1_PRES)
{
vTaskResume(task1_handler);
printf("在任務中恢復task1\r\n");
}
vTaskDelay(10);
}
}
/******************************************************************************************************/
/**
* @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);
xTaskCreate(task2, "task2", TASK2_STACK_SIZE, NULL, TASK2_PRIO, &task2_handler);
xTaskCreate(task3, "task3", TASK3_STACK_SIZE, NULL, TASK3_PRIO, &task3_handler);
vTaskDelete(NULL);
taskEXIT_CRITICAL(); //退出臨界區
}
exti.c
/**
****************************************************************************************************
* @file exti.c
* @author 正點原子團隊(ALIENTEK)
* @version V1.0
* @date 2021-10-14
* @brief 外部中斷 驅動程式碼
* @license Copyright (c) 2020-2032, 廣州市星翼電子科技有限公司
****************************************************************************************************
* @attention
*
* 實驗平臺:正點原子 探索者 F407開發板
* 線上影片:www.yuanzige.com
* 技術論壇:www.openedv.com
* 公司網址:www.alientek.com
* 購買地址:openedv.taobao.com
*
* 修改說明
* V1.0 20211014
* 第一次釋出
*
****************************************************************************************************
*/
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/EXTI/exti.h"
#include "FreeRTOS.h"
#include "task.h"
extern TaskHandle_t task1_handler;
/**
* @brief KEY2 外部中斷服務程式
* @param 無
* @retval 無
*/
void KEY2_INT_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(KEY2_INT_GPIO_PIN); /* 呼叫中斷處理公用函式 清除KEY2所在中斷線 的中斷標誌位,中斷下半部在HAL_GPIO_EXTI_Callback執行 */
__HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN); /* HAL庫預設先清中斷再處理回撥,退出時再清一次中斷,避免按鍵抖動誤觸發 */
}
/**
* @brief WK_UP 外部中斷服務程式
* @param 無
* @retval 無
*/
void WKUP_INT_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(WKUP_INT_GPIO_PIN); /* 呼叫中斷處理公用函式 清除KEY_UP所在中斷線 的中斷標誌位,中斷下半部在HAL_GPIO_EXTI_Callback執行 */
__HAL_GPIO_EXTI_CLEAR_IT(WKUP_INT_GPIO_PIN); /* HAL庫預設先清中斷再處理回撥,退出時再清一次中斷,避免按鍵抖動誤觸發 */
}
/**
* @brief 中斷服務程式中需要做的事情
* 在HAL庫中所有的外部中斷服務函式都會呼叫此函式
* @param GPIO_Pin:中斷引腳號
* @retval 無
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(20); /* 消抖 */
switch(GPIO_Pin)
{
BaseType_t xYieldRequired;
case KEY2_INT_GPIO_PIN:
if (KEY2 == 0)
{
xYieldRequired = xTaskResumeFromISR(task1_handler);
printf("在中斷中恢復task1\r\n");
if(xYieldRequired == pdTRUE)
{
portYIELD_FROM_ISR( xYieldRequired );
}
}
break;
default : break;
}
}
/**
* @brief 外部中斷初始化程式
* @param 無
* @retval 無
*/
void extix_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
key_init();
gpio_init_struct.Pin = KEY2_INT_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING; /* 下降沿觸發 */
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &gpio_init_struct); /* KEY2配置為下降沿觸發中斷 */
HAL_NVIC_SetPriority(KEY2_INT_IRQn, 5, 0); /* 搶佔5,子優先順序0 */
HAL_NVIC_EnableIRQ(KEY2_INT_IRQn); /* 使能中斷線2 */
}