Skip to content

多任务程序

1.1 RTOS的统一接口

cmsis_os2.c文件中由一个osThreadNew()函数,用于统一各种操作系统的任务接口,我们学习FreeRTOS所以优先使用FreeRTOS原生代码函数。

image-20250110214542412

1.2 FreeRTOS默认任务

在使用STM32CubeMX配置完FreeRTOS以后,会有一个默认任务生成,可以在Core\Src\freertos.c文件中找到:

C
void MX_FREERTOS_Init(void) {
    ...
    /* creation of defaultTask */
    defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

    /* USER CODE BEGIN RTOS_THREADS */
    ...
}

找到osThreadNew()函数的第一个参数,即StartDefaultTask()函数,并替换默认函数内容,我们就有第一个循环任务:

C
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument) {
    /* USER CODE BEGIN StartDefaultTask */
    /* Infinite loop */
    for (;;) {
        rtBuzzer_ON_Time();
//        osDelay(1);
    }
    /* USER CODE END StartDefaultTask */
}
Danger

Bsp_Loop()是一个蜂鸣器加LED的死循环函数。

此外,我们应知道,默认任务封装在MX_FREERTOS_Init()函数中(RTOS初始化函数),在main.c文件中约 126 行可以找到这个函数。

C
/* Call init function for freertos objects (in cmsis_os2.c) */
MX_FREERTOS_Init();

1.3 创建一个原生FreeRTOS任务

首先了解FreeRTOS的任务创建函数xTaskCreate(),然后参考默认任务osThreadNew()的传入参数。

C
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
                        const char * const pcName, // 任务的名字
                        const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
                        void * const pvParameters, // 调用任务函数时传入的参数
                        UBaseType_t uxPriority,    // 优先级
                        TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务

关于默认任务的参数设置,找到osThreadNew()的第三参数&defaultTask_attributes的定义位置:

C
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
        .name = "defaultTask",
        .stack_size = 128 * 4,
        .priority = (osPriority_t) osPriorityNormal,
};

接下来创建,我们的第一个原生任务:

① 任务函数,位置在freertos.c文件的最下方,函数类型参数参考void StartDefaultTask(void *argument),注意看注释找任务函数定义位置。

C
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void MyTask(void *argument)
{
    rtMotor_Test();
}
/* USER CODE END Application */

② 声明任务函数,在C语言学习时我们就知道的知识点,位置紧挨着void StartDefaultTask(void *argument);

C
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
void MyTask(void *argument);
/* USER CODE END FunctionPrototypes */

③ 创建任务,位置在MX_FREERTOS_Init()函数中,根据注释找位置创建我们自己的任务。

C
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
xTaskCreate(MyTask, "RbTask_1", 124, NULL, osPriorityNormal, NULL);
/* USER CODE END RTOS_THREADS */

1.4 驱动初始化

C
...
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "freertos_ITF.h"
/* USER CODE END Includes */
...
int main(void) {    
    ...
    /* USER CODE BEGIN 2 */
    Motor_Init();
    /* USER CODE END 2 */
    ...
}