本文最后更新于 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 中断简介

在裸机课程中已经做过介绍了,这里就不做介绍了,请去看前面裸机开发中对中断的介绍。