Freertos

本文最后更新于 2025年8月17日 下午

1、FreeRTOS 任务相关 API 函数

1.1、FreeRTOS 创建和删除任务相关 API 函数

image-20250816211106218.png

1.1.1、动态创建函数 xTaskCreate()

此函数用于使用动态的方式创建任务,任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配, 若使用此函数,需要在 FreeRTOSConfig.h 文件中将宏 configSUPPORT_DYNAMIC_ALLOCATION 配置为 1。此函数创建的任务会立刻进入就绪态,由任务调度器调度运行。 函数原型如下所示:

1
2
3
4
5
6
7
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);

函数 xTaskCreate()的形参描述,如下表所示:

image-20250816211106218.png

image-20250816211344349.png

函数 xTaskCreate()的返回值,如下表所示:

image-20250816211423963.png

1.1.2、静态创建函数 xTaskCreateStatic()

此函数用于使用静态的方式创建任务,任务的任务控制块以及任务的栈空间所需的内存,需 要 由 用 户 分 配 提 供 , 若 使 用 此 函 数 , 需 要 在 FreeRTOSConfig.h 文 件 中 将 宏configSUPPORT_STATIC_ALLOCATION 配置为 1。此函数创建的任务会立刻进入就绪态,由任务调度器调度运行。函数原型如下所示:

1
2
3
4
5
6
7
8
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);

函数 xTaskCreateStatic()的形参描述,如下表所示:

image-20250816211746668.png

函数 xTaskCreateStatic()的返回值,如下表所示:

image-20250816211423963.png

1.1.3、删除函数 vTaskDelete()

此函数用于删除已被创建的任务,被删除的任务将被从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除,要注意的是,空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露。若使用此函数,需要在FreeRTOSConfig.h文件中将宏INCLUDE_vTaskDelete配置为 1。函数原型如下所示:

1
void vTaskDelete(TaskHandle_t xTaskToDelete);  

函数 vTaskDelete()的形参描述,如下表所示:

image-20250817150731350.png

2、FreeRTOS 任务创建与删除实验(动态方法)

本实验主要实现 FreeRTOS 使用动态方法创建和删除任务,本实验设计了四个任务,这四个任务的功能如下表所示:

image-20250817151009881.png

程序流程图

image-20250817151044168.png

  • start_task 任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* @brief start_task
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务 1 */
xTaskCreate(
(TaskFunction_t )task1, /* 任务函数 */
(const char* )"task1", /* 任务名称 */
(uint16_t )TASK1_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK1_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task1Task_Handler); /* 任务句柄 */
/* 创建任务 2 */
xTaskCreate(
(TaskFunction_t )task2, /* 任务函数 */
(const char* )"task2", /* 任务名称 */
(uint16_t )TASK2_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK2_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task2Task_Handler); /* 任务句柄 */
/* 创建任务 3 */
xTaskCreate(
(TaskFunction_t )task3, /* 任务函数 */
(const char* )"task3", /* 任务名称 */
(uint16_t )TASK3_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK3_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task3Task_Handler); /* 任务句柄 */
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
  • task1 和 task2 任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
uint32_t task1_num = 0;
while (1)
{
lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);
lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);
vTaskDelay(500);
}
}
/**
* @brief task2
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task2(void *pvParameters)
{
uint32_t task2_num = 0;
while (1)
{
lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);
lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);
vTaskDelay(500);
}
}
  • task3 任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* @brief task3
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task3(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
key = key_scan(0);
switch (key)
{
case KEY0_PRES:/* 删除任务 1 */
{
if (Task1Task_Handler != NULL)
{
vTaskDelete(Task1Task_Handler);
Task1Task_Handler = NULL;
}
break;
}
case KEY1_PRES:/* 删除任务 2 */
{
if (Task2Task_Handler != NULL)
{
vTaskDelete(Task2Task_Handler);
Task2Task_Handler = NULL;
}
break;
}
default:
{
break;
}
}
vTaskDelay(10);
}
}

3、FreeRTOS 挂起和恢复任务相关 API 函数

FreeRTOS 中用于挂起和恢复任务的 API 函数如下表所示:

image-20250817151439209.png

3.1、函数 vTaskSuspend()

此 函 数 用 于 挂 起 任 务 , 若 使 用 此 函 数 , 需 要 在 FreeRTOSConfig.h 文 件 中 将 宏 INCLUDE_vTaskSuspend 配置为 1。 无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复。此函数并不支持嵌套,不论使用此函数重复挂起任务多少次,只需调用一次恢复任务的函数,那么任务就不再被挂起。函数原型如下所示:

1
void vTaskSuspend(TaskHandle_t xTaskToSuspend)

函数 vTaskSuspend()的形参描述,如下表所示:

image-20250817151628121.png

3.2、函数 vTaskResume()

此函数用于在任务中恢复被挂起的任务, 若使用此函数,需要在 FreeRTOSConfig.h 文件中将宏 INCLUDE_vTaskSuspend 配置为 1。不论一个任务被函数 vTaskSuspend()挂起多少次,只需要使用函数 vTakResume()恢复一次,就可以继续运行。 函数原型如下所示:

1
void vTaskResume(TaskHandle_t xTaskToResume)

函数 vTaskResume()的形参描述,如下表所示:

image-20250817151727078.png

3.3、函数 xTaskResumeFromISR()

此函数用于在中断中恢复被挂起的任务, 若使用此函数,需要在 FreeRTOSConfig.h 文件中将宏 INCLUDE_xTaskResumeFromISR 配置为 1。不论一个任务被函数 vTaskSuspend()挂起多少次,只需要使用函数 vTakResumeFromISR()恢复一次,就可以继续运行。函数原型如下所示:

1
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume)  

函数 xTaskResumeFromISR()的形参描述,如下表所示:

image-20250817151727078.png函数 xTaskResumeFromISR()的返回值,如下表所示:

image-20250817151849262.png

3.4、FreeRTOS 任务挂起与恢复实验

本实验主要实现 FreeRTOS 挂起和恢复任务,本实验设计了四个任务,这四个任务的功能如下表所示

image-20250817152024220.png

程序流程图

image-20250817152047204.pngstart_task 任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* @brief start_task
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务 1 */
xTaskCreate(
(TaskFunction_t )task1, /* 任务函数 */
(const char* )"task1", /* 任务名称 */
(uint16_t )TASK1_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK1_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task1Task_Handler); /* 任务句柄 */
/* 创建任务 2 */
xTaskCreate(
(TaskFunction_t )task2, /* 任务函数 */
(const char* )"task2", /* 任务名称 */
(uint16_t )TASK2_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK2_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task2Task_Handler); /* 任务句柄 */
/* 创建任务 3 */
xTaskCreate(
(TaskFunction_t )task3, /* 任务函数 */
(const char* )"task3", /* 任务名称 */
(uint16_t )TASK3_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )TASK3_PRIO, /* 任务优先级 */
(TaskHandle_t* )&Task3Task_Handler); /* 任务句柄 */
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}

task1 和 task2 任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
uint32_t task1_num = 0;
while (1)
{
lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);
lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);
vTaskDelay(500);
}
}
/**
* @brief task2
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task2(void *pvParameters)
{
uint32_t task2_num = 0;
while (1)
{
lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);
lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);
vTaskDelay(500);
}
}

task3 任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* @brief task3
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task3(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
key = key_scan(0);
switch (key)
{
case KEY0_PRES: /* 挂起任务 1 */
{
vTaskSuspend(Task1Task_Handler);
break;
}
case KEY1_PRES: /* 恢复任务 1 */
{
vTaskResume(Task1Task_Handler);
break;
}
default:
{
break;
}
}
vTaskDelay(10);
}
}

本文作者: zhangJinLong
本文链接: https://zhang426fly.github.io/2025/08/17/Freertos/FreeRTOS01/
版权声明: 本博客所有文章除特别声明外,均采用BY-NC-SA许可协议。转载请注明出处!


Freertos
https://zhang426fly.github.io/2025/08/17/Freertos/FreeRTOS01/
作者
zhangJinLong
发布于
2025年8月17日
许可协议