STM32FreeRtos入门(二)——创建第一个多任务程序
文章目录
- 前言
- 一、FreeRTOS 创建任务的流程图描述
- 二、reeRTOS 创建多任务的代码描述
- 1.示例代码
- 2.原理
- 总结
前言
实习后,FreeRtos感觉是必须要会的,不会找不到工作。因此,实习半年后我又开始买了一块二手的韦东山的板子,重新学习。所以,我的工程是基于韦东山FreeRtos的教学来的,纯是为了方便后续面试复习。
我大学的时候,学校是比较差的,教的很杂,学的很差。单片机就教到了HAL库,FreeRtos更是教都没教。LINUX和FPGA教的完全学不会。尤其是LINUX,请的企业工程师来教课,企业都不怎么上课,一节课总共就说三四句话。当时是连学习都不知道怎么入门。讲偏了,当个乐子听就行了。
一、FreeRTOS 创建任务的流程图描述
FreeRTOS 创建任务的流程图描述
- 初始化任务参数
- 调用 xTaskCreate
- 分配任务堆栈内存 (使用 pvPortMalloc)
- 分配任务控制块内存 (使用 pvPortMalloc)
- 初始化任务控制块 (包括任务堆栈等)
- 将任务加入就绪列表 (prvAddNewTaskToReadyList)
- 启动任务调度器 (vTaskStartScheduler)
创建任务分两种,静态创建任务和动态创建任务(因为内存分配)
FreeRTOS 创建任务静态分配内存和动态分配内存区别
动态:
静态:
二、reeRTOS 创建多任务的代码描述
1.示例代码
代码如下(示例):
/*********************************************************************** 函数名称: Led_Test* 功能描述: Led测试程序* 输入参数: 无* 输出参数: 无* 无* 返 回 值: 0 - 成功, 其他值 - 失败* 修改日期 版本号 修改人 修改内容* -----------------------------------------------* 2023/08/03 V1.0 韦东山 创建***********************************************************************/
void Led_Test(void)
{Led_Init();while (1){Led_Control(LED_GREEN, 1);mdelay(500);Led_Control(LED_GREEN, 0);mdelay(500);}
}
void OLED_Test(void)
{OLED_Init();// 清屏OLED_Clear();while (1){// 在(0, 0)打印'A'OLED_PutChar(0, 0, 'A');// 在(1, 0)打印'Y'OLED_PutChar(1, 0, 'Y');// 在第0列第2页打印一个字符串"Hello World!"OLED_PrintString(0, 2, "Hello World!");}
}
上述是两个while(1)循环的代码
如果想让这两个循环的代码都执行,就要用到RTOS
如下图:
原本创建的任务是CUBEMX自动帮我们创建的任务
osThreadNew 是 CMSIS-RTOS2 标准中用于创建新线程(任务)的 API 函数,常用于 STM32 等基于 Cortex-M 的嵌入式系统中。它是对底层 RTOS(如 FreeRTOS)线程创建函数的封装,提供统一的接口,提升代码的可移植性。
创建的是一个动态的任务,需要包含任务指针,任务名称,栈的大小,传入参数,优先级,任务句柄
任务指针:如下void maTask
任务名称:可以自己随意命名
栈的大小:默认,测试程序一般128*4
传入参数:无,这个程序不需要传入
优先级:默认,详情请看韦东山内部机制
任务句柄:钩子;
在 FreeRTOS 里,任务句柄(TaskHandle_t)就是系统给这个任务发“快递”时必须填的“收件人地址”。
没有它,内核就找不到目标任务,也就无法完成后续操作。
一句话先记住
任务句柄 = 任务的身份证/门牌号,内核和用户凭它“指名道姓”地操作某个任务。
任务句柄是 FreeRTOS 里“指名道姓”操作某个任务的唯一凭证,创建时拿到手,后续删、挂、恢复、改优先级、发通知都离不开它。
此时,FreeRTOS工程执行了两个任务,都是循环任务。
2.原理
首先初始化 CMSIS-RTOS2 内核(底层是 FreeRTOS)。
osKernelInitialize();
MX_FREERTOS_Init();
CubeMX 自动生成的函数,在里面创建线程、队列、信号量等。
注意:
这个函数必须在 osKernelInitialize() 之后调用。
如果你手动改了这个函数,确保没有使用未初始化的 RTOS 对象。
osKernelStart();
作用:启动调度器,从此开始多任务调度。
vTaskStartScheduler() 是 FreeRTOS 的函数,不会返回,除非调度器启动失败(如内存不足)。
如果 osKernelStart() 返回了 osOK,说明调度器已启动;返回任何其他值都表示启动失败。
总结
整个FreeRTOS工程详细步骤说明:
1初始化任务参数:
定义任务函数、任务名称、任务优先级、任务栈大小等参数。
2调用 xTaskCreate:
使用 xTaskCreate 函数创建任务,传入任务函数、任务名称、栈大小、任务参数、优先级和任务句柄。
3分配任务堆栈内存:
xTaskCreate 内部调用 pvPortMalloc 为任务堆栈分配内存。
4分配任务控制块内存:
同样使用 pvPortMalloc 为任务控制块(TCB)分配内存。
5初始化任务控制块:
初始化任务控制块中的各个字段,包括任务堆栈、任务名称、优先级等。
6将任务加入就绪列表:
调用 prvAddNewTaskToReadyList 将新创建的任务加入到就绪列表中。
7启动任务调度器:
调用 vTaskStartScheduler 启动任务调度器,开始任务调度。