一,代码解析
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
版权信息
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
初始化的头文件
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "user_TasksInit.h"
/* USER CODE END Includes */
用户自定义任务初始化头文件
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
这些部分都是 STM32CubeMX 预留的用户代码区。目前它们是空的,但用户可以在其中添加自己的类型定义、宏、常量或全局变量。
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
defaultTaskHandle : 这是一个 osThreadId_t 类型的变量,用于在任务创建后存储该任务的句柄。通过这个句柄,可以在程序中的其他地方引用并控制这个任务(例如暂停、恢复、删除等)。
defaultTask_attributes : 这是一个 osThreadAttr_t 结构体,定义了 defaultTask 的属性:
.name = “defaultTask”: 给任务一个字符串名称,在调试工具(如 FreeRTOS 的任务查看器)中会显示这个名称,方便识别。
.stack_size = 128 * 4: 定义任务的堆栈大小。
.priority = (osPriority_t) osPriorityNormal: 设置任务的执行优先级。osPriorityNormal 是 CMSIS-RTOS 定义的一个标准优先级。FreeRTOS 调度器总是执行处于就绪态的最高优先级任务。
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void MX_FREERTOS_Init(void);
/* (MISRA C 2004 rule 8.1) */
/* Hook prototypes */
void vApplicationIdleHook(void);
void vApplicationTickHook(void);
/* USER CODE BEGIN 2 */
void vApplicationIdleHook( void )//空闲任务钩子(作用:当没有任何其他任务可以运行时,FreeRTOS 的空闲任务(Idle Task)会被调度执行,而 vApplicationIdleHook() 会在空闲任务的每次迭代中被调用。)
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
}
/* USER CODE END 2 */
/* USER CODE BEGIN 3 */
void vApplicationTickHook( void )时钟节拍钩子(作用:这个函数会在每个 FreeRTOS 时钟节拍中断发生时被调用。时钟节拍中断是 FreeRTOS 调度器的心跳,用于时间管理和任务调度。)
{
/* This function will be called by each tick interrupt if
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
added here, but the tick hook is called from an interrupt context, so
code must not attempt to block, and only the interrupt safe FreeRTOS API
functions can be used (those that end in FromISR()). */
TaskTickHook();
}
/* USER CODE END 3 */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
User_Tasks_Init();
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
}
这是 FreeRTOS 的主初始化函数,通常在 main() 函数中通过 MX_FREERTOS_Init(); 调用。
User_Tasks_Init(): 这是用户自定义任务的初始化函数,它会在 defaultTask 创建之前被调用。这意味着用户可以在这个函数中创建其他应用所需的任务。这体现了模块化的设计,将用户自定义任务的创建逻辑与 freertos.c 的骨架分离。
RTOS_MUTEX / SEMAPHORES / TIMERS / QUEUES / THREADS / EVENTS: 这些都是 STM32CubeMX 生成的用户代码区。它们预留了位置,供用户通过 CMSIS-RTOS API 创建:
互斥量 (Mutexes) : 用于保护共享资源,防止多个任务同时访问导致数据不一致。
信号量 (Semaphores) : 用于任务同步或资源计数。
软件定时器 (Timers) : 用于周期性执行代码或在一定时间后执行一次代码。
消息队列 (Queues) : 用于任务间传递数据。
其他线程 (Threads) : 除了 defaultTask,用户可以在这里创建更多自己的任务。
事件标志组 (Events) : 用于任务之间发送和接收事件信号。
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);: 这是实际创建 defaultTask 的代码。
StartDefaultTask: 是该任务的入口函数。
NULL: 表示没有参数传递给 StartDefaultTask 函数。
&defaultTask_attributes: 使用前面定义的任务属性。
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;
;
)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
osDelay(500);
}
/* USER CODE END StartDefaultTask */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */
这是默认任务执行的代码
二,总结
首先是定义了defaultask的句柄,通过defaultTask_attributes定义了defaulttask的属性(名字,栈的大小,优先级),在MX_FREERTOS_Init(void) 中调用User_Tasks_Init()。最后定义了默认任务