03_STM32_Freertos_应用篇
本文最后更新于 2025-06-10,学习久了要注意休息哟
第一章 任务创建和删除
1.1 API函数
1.1.1 API函数分类
1、任务创建与删除相关函数
xTaskCreate() // 创建任务(自动分配内存)
xTaskCreateStatic() // 静态方式创建任务(手动提供堆栈和任务控制块)
vTaskDelete() // 删除任务
📌 静态任务适用于对内存控制更严格的系统,特别是在不启用动态内存的配置下(如使用
heap_4.c
被禁用或使用heap_1.c
时)。
2、调度器控制函数
vTaskStartScheduler() // 启动调度器
xTaskGetSchedulerState() // 获取调度器状态(运行/未运行)
xTaskGetCurrentTaskHandle() // 获取当前任务句柄
3、临界区管理函数
保护共享资源
taskENTER_CRITICAL() // 进入临界区(禁止中断)
taskEXIT_CRITICAL() // 退出临界区(恢复中断)
📌 临界区函数用于防止任务或中断在访问共享资源时出现竞态,适合短时间保护代码段。
1.1.2 任务创建与删除相关函数
1、动态任务创建函数
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
说明:
// 动态创建任务,自动分配堆栈和控制块
参数:
@pxTaskCode: // 任务函数指针,格式为 void Func(void *pvParameters)
@pcName: // 任务名称,仅用于调试
@usStackDepth: // 任务栈大小,以 word 为单位,一个 word 通常为 4 字节
@pvParameters: // 传入任务的参数(可以为 NULL)
@uxPriority: // 任务优先级(值越大优先级越高)
@pxCreatedTask: // 任务句柄输出地址(可为 NULL)
返回值:
// pdPASS 表示成功,其他值表示失败(如内存不足)
2、静态任务创建函数
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer )
说明:
// 静态创建任务,手动提供堆栈数组和控制块结构体
参数:
@pxTaskCode: // 任务函数指针
@pcName: // 任务名称,仅用于调试
@ulStackDepth: // 任务栈深度,单位为字(word)
@pvParameters: // 传入任务的参数
@uxPriority: // 任务优先级
@puxStackBuffer: // 用户提供的栈内存数组(StackType_t 类型)
@pxTaskBuffer: // 用户提供的控制块结构体(StaticTask_t 类型)
返回值:
// 返回创建的任务句柄(TaskHandle_t)
1、删除指定任务函数
void vTaskDelete( TaskHandle_t xTaskToDelete );
说明:
// 删除指定任务,释放相关资源
参数:
@xTaskToDelete: // 要删除的任务句柄,传入 NULL 表示删除当前任务
1.1.3 调度器控制函数
1、启动调度器
void vTaskStartScheduler( void )
说明:
// 启动任务调度器,系统从此刻开始运行任务,函数本身不会返回(除非失败)
2、获取调度器状态
BaseType_t xTaskGetSchedulerState( void )
说明:
// 获取当前调度器的状态,用于判断是否已启动或已挂起
返回值:
// 返回值类型为 enum(0 ~ 2):
// 0:taskSCHEDULER_NOT_STARTED
// 1:taskSCHEDULER_RUNNING
// 2:taskSCHEDULER_SUSPENDED
3、获取当前任务句柄
TaskHandle_t xTaskGetCurrentTaskHandle( void )
说明:
// 获取当前正在运行的任务的任务句柄
返回值:
// 返回当前任务的句柄(TaskHandle_t)
1.1.4 任务控制块
1、动态任务控制块
/*
* FreeRTOS 任务控制块结构体(TCB)
* 每个任务都会分配一个 TCB,用于记录任务的运行环境与状态
*/
typedef struct tskTaskControlBlock
{
/* ======== 基本堆栈信息 ======== */
volatile StackType_t * pxTopOfStack; // 当前任务栈顶指针(必须为第一个成员)
StackType_t * pxStack; // 任务栈起始地址
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
StackType_t * pxEndOfStack; // 栈空间末地址(最大可访问地址)
#endif
/* ======== MPU 相关(可选) ======== */
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; // MPU 设置结构体(必须为第二个成员)
#endif
/* ======== 内核链表相关 ======== */
ListItem_t xStateListItem; // 任务状态链表节点(就绪、挂起等)
ListItem_t xEventListItem; // 等待事件链表节点(阻塞等)
/* ======== 优先级信息 ======== */
UBaseType_t uxPriority; // 当前任务优先级(0 为最低)
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxBasePriority; // 原始优先级(用于优先级继承)
UBaseType_t uxMutexesHeld; // 当前持有的互斥量数量
#endif
/* ======== 调试与标识 ======== */
char pcTaskName[ configMAX_TASK_NAME_LEN ]; // 任务名称(用于调试)
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTCBNumber; // TCB 创建编号(调试用)
UBaseType_t uxTaskNumber; // 第三方 trace 工具编号
#endif
/* ======== 嵌套临界区计数(部分平台) ======== */
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting; // 临界区嵌套计数
#endif
/* ======== 任务钩子函数(可选) ======== */
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t pxTaskTag; // 用户任务钩子函数
#endif
/* ======== 线程本地存储(TLS) ======== */
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
configTLS_BLOCK_TYPE xTLSBlock; // C库线程本地存储块(如 newlib)
#endif
/* ======== 任务通知机制 ======== */
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
#endif
/* ======== 运行时间统计(可选) ======== */
#if ( configGENERATE_RUN_TIME_STATS == 1 )
configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; // 任务累计运行时间(tick)
#endif
/* ======== 静态任务标识(避免释放) ======== */
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
uint8_t ucStaticallyAllocated; // 标识是否为静态创建(pdTRUE 不释放)
#endif
/* ======== 延时中止标识(用于 xTaskAbortDelay) ======== */
#if ( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDelayAborted;
#endif
/* ======== POSIX errno 支持(可选) ======== */
#if ( configUSE_POSIX_ERRNO == 1 )
int iTaskErrno; // 每个任务独立 errno 值
#endif
} tskTCB;
2、静态任务控制块
/*
* 静态任务控制块结构体 StaticTask_t
*
* ⚠️ 注意:该结构体 仅用于静态任务创建(xTaskCreateStatic)时内存预分配。
* 它的大小和对齐方式与内部 tskTCB 保持一致,但成员名称经过模糊化,
* FreeRTOS 强烈不建议用户访问其字段,仅用于占位和尺寸匹配。
*
* ✅ 特点:
* - 可完全替代动态内存方式,避免使用 malloc。
* - 可应用于裸机/安全敏感/高可靠嵌入式系统中。
* - 必须与用户提供的堆栈数组 `StackType_t[]` 一起使用。
*/
typedef struct xSTATIC_TCB
{
void * pxDummy1; // 对应 pxTopOfStack 或调度用指针
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xDummy2; // MPU 设置占位字段
#endif
StaticListItem_t xDummy3[2]; // 状态链表 + 事件链表 占位
UBaseType_t uxDummy5; // 任务优先级、嵌套等字段占位
void * pxDummy6; // 指向栈底的指针占位
uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; // 任务名称
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
void * pxDummy8; // 栈尾指针(最高地址)
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxDummy9; // 临界区嵌套计数
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy10[2]; // TCB编号与任务编号占位
#endif
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxDummy12[2]; // 原始优先级 + 持有互斥量数
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
void * pxDummy14; // 用户任务钩子占位
#endif
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void * pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; // TLS数组
#endif
#if ( configGENERATE_RUN_TIME_STATS == 1 )
configRUN_TIME_COUNTER_TYPE ulDummy16; // 运行时间统计值
#endif
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
configTLS_BLOCK_TYPE xDummy17; // C库线程本地存储块
#endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; // 通知值
uint8_t ucDummy19[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; // 通知状态
#endif
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
uint8_t uxDummy20; // 静态分配标识(pdTRUE)
#endif
#if ( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDummy21; // 延时中止标志
#endif
#if ( configUSE_POSIX_ERRNO == 1 )
int iDummy22; // 每个任务独立 errno 值
#endif
} StaticTask_t;
1.2 实验:动态创建任务
1.2.1 任务目标
start_task
:系统启动任务,创建其他三个任务。task1
:控制 LED1 每 500ms 闪烁一次。task2
:控制 LED2 每 300ms 闪烁一次。task3
:检测按键 KEY1 是否按下,按下则删除task1
。
1.2.2 创建步骤
1、默认情况下,FreeRTOS 已开启动态任务创建,如未开启可在FreeRTOSConfig.h
中设置:
#define configSUPPORT_DYNAMIC_ALLOCATION 1
2、创建任务句柄 和 任务优先级定义
// 创建任务句柄
TaskHandle_t Task_Start_Handle = NULL;
TaskHandle_t Task_1_Handle = NULL;
TaskHandle_t Task_2_Handle = NULL;
TaskHandle_t Task_3_Handle = NULL;
// 创建任务优先级
#define Task_Start_Priority 3
#define Task_1_Priority 2
#define Task_2_Priority 2
#define Task_3_Priority 2
3、创建任务
// 创建 启动任务
xTaskCreate( (TaskFunction_t) Start_Task,
(char *) "Start_Task",
(uint16_t ) 128,
(void *) NULL,
(UBaseType_t) Task_Start_Priority,
(TaskHandle_t * ) & Task_Start_Handle );
4、编写任务函数
// 系统启动任务
void Start_Task(void * pvParameters)
{
/* 编写任务 */
}
1.2.3 示例代码
#include "RTOS_demo_01.h"
// 创建动态任务
// start_task:系统启动任务,创建其他三个任务。
// task1:控制 LED1 每 500ms 闪烁一次。
// task2:控制 LED2 每 300ms 闪烁一次。
// task3:检测按键 KEY1 是否按下,按下则删除 task1。
// 创建任务句柄
TaskHandle_t Task_Start_Handle = NULL;
TaskHandle_t Task_1_Handle = NULL;
TaskHandle_t Task_2_Handle = NULL;
TaskHandle_t Task_3_Handle = NULL;
// 创建任务优先级
#define Task_Start_Priority 3
#define Task_1_Priority 2
#define Task_2_Priority 2
#define Task_3_Priority 2
// task1:控制 LED1 每 500ms 闪烁一次。
void task_1(void * pvParameters)
{
while (1)
{
LED_Tog(1);
vTaskDelay(500);
}
}
// task2:控制 LED2 每 300ms 闪烁一次。
void task_2(void * pvParameters)
{
while (1)
{
LED_Tog(2);
vTaskDelay(300);
}
}
// task3:检测按键 KEY1 是否按下,按下则删除 task1。
void task_3(void * pvParameters)
{
uint8_t key_val;
while (1)
{
key_val = Key_read();
if (key_val == 1)
{
if (NULL != Task_1_Handle)
{
// 删除任务
vTaskDelete(Task_1_Handle);
// 手动情况为NULL
Task_1_Handle = NULL;
}
}
vTaskDelay(10);
}
}
// 系统启动任务
void Start_Task(void * pvParameters)
{
// 创建 任务1
xTaskCreate( (TaskFunction_t) task_1,
(char *) "task_1",
(uint16_t ) 128,
(void *) NULL,
(UBaseType_t) Task_1_Priority,
(TaskHandle_t * ) & Task_1_Handle );
// 创建 任务2
xTaskCreate( (TaskFunction_t) task_2,
(char *) "task_2",
(uint16_t ) 128,
(void *) NULL,
(UBaseType_t) Task_2_Priority,
(TaskHandle_t * ) & Task_2_Handle );
// 创建 任务3
xTaskCreate( (TaskFunction_t) task_3,
(char *) "task_3",
(uint16_t ) 128,
(void *) NULL,
(UBaseType_t) Task_3_Priority,
(TaskHandle_t * ) & Task_3_Handle );
// 删除本任务
vTaskDelete(NULL);
}
// RTOS_demo_01_main 主任务
void RTOS_demo_01_main(void)
{
// 创建 启动任务
xTaskCreate( (TaskFunction_t) Start_Task,
(char *) "Start_Task",
(uint16_t ) 128,
(void *) NULL,
(UBaseType_t) Task_Start_Priority,
(TaskHandle_t * ) & Task_Start_Handle );
// 启动调度器
vTaskStartScheduler();
}
1.3 实验:静态创建任务
1.3.1 任务目标
start_task
:系统启动任务,创建其他三个任务。task1
:控制 LED1 每 500ms 闪烁一次。task2
:控制 LED2 每 300ms 闪烁一次。task3
:检测按键 KEY1 是否按下,按下则删除task1
。
1.3.2 实现步骤
1、在FreeRTOSConfig.h
文件中 开启静态创建任务的宏
#define configSUPPORT_STATIC_ALLOCATION 1
2、创建任务控制块和任务栈空间
// 任务控制块
StaticTask_t Task_Start_TCB;
// 任务栈空间
StackType_t Task_Start_Stack[128];
3、重写空闲任务配置函数
// 空闲任务配置
static StaticTask_t IdleTask_TCB; // TCB 控制块
static StackType_t IdleTask_Stack[configMINIMAL_STACK_SIZE]; // 栈空间
// 重写 空闲任务配置函数
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer = &IdleTask_TCB;
*ppxIdleTaskStackBuffer = IdleTask_Stack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
4、重写软件定时器配置函数
// 软件定时器配置
static StaticTask_t TimerTask_TCB;
static StackType_t TimerTask_Stack[configTIMER_TASK_STACK_DEPTH];
// 重写 软件定时器配置函数
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
*ppxTimerTaskTCBBuffer = &TimerTask_TCB;
*ppxTimerTaskStackBuffer = TimerTask_Stack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
5、创建任务并启动任务调动器
// 系统启动任务
void Start_Task(void * pvParameters)
{
// 略
vTaskDelete(NULL); // 删除自己
}
6、编写任务函数
// 创建主任务
Task_Start_Handle = xTaskCreateStatic( (TaskFunction_t) Start_Task,
(char *) "Start_Task",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) Task_Start_Priority,
(StackType_t *) Task_Start_Stack,
(StaticTask_t *) & Task_Start_TCB );
// 启动任务调动器
vTaskStartScheduler();
1.3.3 示例代码
#include "RTOS_demo_02.h"
// 创建静态任务
// start_task:系统启动任务,创建其他三个任务。
// task1:控制 LED1 每 500ms 闪烁一次。
// task2:控制 LED2 每 300ms 闪烁一次。
// task3:检测按键 KEY1 是否按下,按下则删除 task1。
// 创建任务句柄
TaskHandle_t Task_Start_Handle = NULL;
TaskHandle_t Task_1_Handle = NULL;
TaskHandle_t Task_2_Handle = NULL;
TaskHandle_t Task_3_Handle = NULL;
// 创建任务优先级
#define Task_Start_Priority 3
#define Task_1_Priority 2
#define Task_2_Priority 2
#define Task_3_Priority 2
// 创建任务控制块
StaticTask_t Task_Start_TCB;
StaticTask_t Task_1_TCB;
StaticTask_t Task_2_TCB;
StaticTask_t Task_3_TCB;
// 创建任务栈空间
StackType_t Task_Start_Stack[128];
StackType_t Task_1_Stack[128];
StackType_t Task_2_Stack[128];
StackType_t Task_3_Stack[128];
// task1:控制 LED1 每 500ms 闪烁一次。
void task_1(void * pvParameters)
{
while (1)
{
LED_Tog(1);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
// task2:控制 LED2 每 300ms 闪烁一次。
void task_2(void * pvParameters)
{
while (1)
{
LED_Tog(2);
vTaskDelay(pdMS_TO_TICKS(300));
}
}
// task3:检测按键 KEY1 是否按下,按下则删除 task1。
void task_3(void * pvParameters)
{
uint8_t key_val;
while (1)
{
key_val = Key_read();
if (key_val == 1)
{
if (NULL != Task_1_Handle)
{
// 删除任务
vTaskDelete(Task_1_Handle);
// 手动情况为NULL
Task_1_Handle = NULL;
}
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
// 系统启动任务
void Start_Task(void * pvParameters)
{
// 创建任务1
Task_1_Handle = xTaskCreateStatic( (TaskFunction_t) task_1,
(char *) "task_1",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) Task_1_Priority,
(StackType_t *) Task_1_Stack,
(StaticTask_t *) & Task_1_TCB );
// 创建任务2
Task_2_Handle = xTaskCreateStatic( (TaskFunction_t) task_2,
(char *) "task_2",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) Task_2_Priority,
(StackType_t *) Task_2_Stack,
(StaticTask_t *) & Task_2_TCB );
// 创建任务3
Task_3_Handle = xTaskCreateStatic( (TaskFunction_t) task_3,
(char *) "task_3",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) Task_3_Priority,
(StackType_t *) Task_3_Stack,
(StaticTask_t *) & Task_3_TCB );
vTaskDelete(NULL); // 删除自己
}
void RTOS_demo_02_main(void)
{
// 创建主任务
Task_Start_Handle = xTaskCreateStatic( (TaskFunction_t) Start_Task,
(char *) "Start_Task",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) Task_Start_Priority,
(StackType_t *) Task_Start_Stack,
(StaticTask_t *) & Task_Start_TCB );
// 启动任务调动器
vTaskStartScheduler();
}
// FreeRTOS 在使用静态内存创建任务时,必须手动实现如下函数,以便为系统内置的空闲任务和软件定时器任务提供内存。
// 这样做的好处是避免使用动态内存,特别适用于内存受限的嵌入式系统中。
// 空闲任务配置
static StaticTask_t IdleTask_TCB; // TCB 控制块
static StackType_t IdleTask_Stack[configMINIMAL_STACK_SIZE]; // 栈空间
// 软件定时器配置
static StaticTask_t TimerTask_TCB;
static StackType_t TimerTask_Stack[configTIMER_TASK_STACK_DEPTH];
// 重写 空闲任务配置函数
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer = &IdleTask_TCB;
*ppxIdleTaskStackBuffer = IdleTask_Stack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
// 重写 软件定时器配置函数
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
*ppxTimerTaskTCBBuffer = &TimerTask_TCB;
*ppxTimerTaskStackBuffer = TimerTask_Stack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
第二章 任务挂起与恢复
2.1 API 函数
2.1.1 API 函数分类
1、任务恢复与挂起
vTaskSuspend() // 挂起指定任务
vTaskResume() // 恢复指定任务
vTaskSuspendAll() // 挂起所有任务调度
xTaskResumeAll() // 恢复所有任务调度
2、查看任务状态
vTaskList() // 获取当前任务列表信息(用于调试)
3、任务恢复(中断恢复)
xTaskResumeFromISR() // 从中断服务函数中恢复任务
2.1.2 任务挂起与恢复函数
1、挂起与恢复任务
// 所需开启的宏
#define INCLUDE_vTaskSuspend 1
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
// 功能:挂起指定任务,使其停止调度。
// 参数:
// @xTaskToSuspend: 要挂起的任务句柄,传 NULL 表示挂起当前任务。
// 返回值:无
void vTaskResume( TaskHandle_t xTaskToResume )
// 功能:恢复被挂起的任务,使其重新进入就绪状态。
// 参数:
// @xTaskToResume: 要恢复的任务句柄。
// 返回值: 无
2、挂起与恢复调度器
void vTaskSuspendAll( void )
// 功能: 挂起整个任务调度器,防止任务切换,当前任务继续运行。
BaseType_t xTaskResumeAll( void )
// 功能: 恢复任务调度器,重新启用任务切换。
// 返回值:
// pdTRUE 表示恢复调度后有更高优先级任务被唤醒,
// pdFALSE 表示无任务切换。
2.1.2 查看任务状态函数
// 所需开启的宏
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
void vTaskList( char * pcWriteBuffer )
// 功能:获取当前系统中所有任务的运行信息(任务状态、优先级、剩余栈空间等)。
// 参数:
// @pcWriteBuffer: 指向用于存放任务信息的字符数组。
// 返回值: 无(结果通过参数返回)
2.1.3 任务恢复函数(中断恢复)
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
// 功能:在中断服务函数中恢复被挂起的任务。
// 参数:
// @xTaskToResume: 要恢复的任务句柄。
// 返回值:
// pdTRUE 表示恢复的任务优先级高于当前任务,需要进行一次上下文切换,
// pdFALSE 表示无需切换。
2.2 实验:任务挂起与恢复
2.2.1 任务目标
start_task
:系统启动任务,创建其他三个任务。task1
:控制 LED1 每 500ms 闪烁一次。task2
:控制 LED2 每 300ms 闪烁一次。task3
:检测按键 KEY1 是否按下,按下则挂起task1
,检测按钮 KEY2 是否按钮,按下则恢复task1
。
2.2.2 示例代码
其他部分沿用前面动态创建任务的代码,不需要修改其他部分,仅需修改task3
任务。
修改后如下:
// task3:检测按键 KEY1 是否按下,按下则删除 task1。
void task_3(void *pvParameters)
{
// 定义按钮值
uint8_t key_val;
// 定义字符串 用于打印信息
char vTaskList_FIFO[128];
while (1)
{
// 获取任务状态
vTaskList(vTaskList_FIFO);
printf("%s\n", vTaskList_FIFO);
key_val = Key_read();
if (key_val == 1)
{
// 任务挂起
printf("task_1 任务挂起\n");
vTaskSuspend(Task_1_Handle);
}
else if (key_val == 2)
{
// 任务恢复
printf("task_1 任务恢复\n");
vTaskResume(Task_1_Handle);
}
vTaskDelay(10);
}
}
第三章 中断管理
3.1 中断简介
在裸机课程中已经做过介绍了,这里就不做介绍了,请去看前面裸机开发中对中断的介绍。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 小道士