FreeRTOS学习笔记(一)

📅 2026/6/26 7:33:10
FreeRTOS学习笔记(一)
FreeRTOS学习笔记一在STM32F407ZGT6上手动移植FreeRTOS开发板型号STM32F407ZGT6核心板FreeRTOS版本V10.4.6使用开发工具STM32CubeMX V6.3.0 keil 5.36移植前准备STM32CubeMX生成基础工程配置RCC配置Debug模式将 Debug 栏设置为Serial WireSW 模式占用引脚少、通用性强。因为后面FreRTOS要用systick故将debug时钟改为TIM6。配置GPIO从开发板配套的电路图上可知LED0和LED1是推挽输出连接的MCU引脚是PF9、PF10我们只需要设置为输出口并且为低电平时LED就会亮,故初始化时拉高。配置时钟还是通过电路图可知外部晶振为8MHz。这里使用最高频率168MHz。设置相关参数Project Name和Project Location必须为纯英文/数字/无空格不能中文不然会报错选择Toolchain/IDE为MDK-ARM这样我们就可以用Keil进行开发调试了。生成代码点击右上角的GENERATE CODE。跳出弹框选择“Open the project”。如果不报错并且跳转到Keil界面中编译没有错误生成代码成功。要是报错建议重新下载安装开发工具重复上述步骤注意安装路径为C盘默认。Core用户平时要编写的文件都在这文件夹里如main.cDrives芯片内核支持文件、 HAL库文件。不可修改MDK-ARM工程入口文件、仿真调试记录文件工程名称.iocCubeMX的配置文件双击它就可以再次对工程进行配置FreeRTOS源码的获取​ 使用的 FreeRTOS 内核源码的版本 V10.4.6即 FreeRTOS v202112.00。相关资源很多就不在这里提供连接了。FreeRTOS的移植创建文件夹复制源码内容到文件夹下将 FreeRTOS 的源代码下Source文件夹下的所有文件复制到刚刚新建的 FreeRTOS 子文件中。打开portable文件夹除了Keil、MemMang、RVDS这3 个目录保留以外其他都删除。向工程添加.c文件打 开 基 础 工 程 在左边的工程项目分组中添加 Middlewares/FreeRTOS/Source和 Middlewares/FreeRTOS/Portable两个分组。将Source文件夹下的7个.c文件添加到Middlewares/FreeRTOS/Source分组下这是FreeRTOS的核心。Middlewares/FreeRTOS_PORT 分组用于存放 FreeRTOS 内核的移植文件需要添加两类文件到这个分组分别为portable\RVDS\ARM_CM4F文件夹下的heap_4.c 和portable\MemMang下的 port .c。配置头文件路径接下来添加 FreeRTOS 源码的头文件路径需要添加两个头文件路径。在option配置选型的C/C选型卡中配置头文件包含路径添加 FreeRTOS\include和FreeRTOS\portable\RVDS\ARM_CM4F。中不同类型开发板与 port 文件的对应关系进行添加即可。配置FreeRTOSConfig.hFreeRTOSConfig.h 是 FreeRTOS 操作系统的配置文件FreeRTOS 操作系统是可裁剪的用户可以根据需求对 FreeRTOS 进行裁剪裁剪掉不需要用到的 FreeRTOS 功能以此来节约 MCU中的内存资源。可以在 Demo 文件夹中找到与自己所使用芯片相似的演示工程中的 FreeRTOSConfig.h文件并根据自己的需求稍作修改。示例从解压的源码FreeRTOSv202112.00\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK路径下复制FreeRTOSConfig.h文件。FreeRTOS在FreeRTOSConfig.h 文件中使用SystemCoreClock这个全局变量来标记系统时钟示例使用了条件编译来声明这个全局变量。#ifdef __ICCARM__ #include stdint.h extern uint32_t SystemCoreClock; #endif编译宏对应的是EWARM编译环境这里我们使用Keil,故需要对条件编译进行修改。#if defined(__ICCARM__) || defined(__CC_ARM) #include stdint.h extern uint32_t SystemCoreClock; #endif修改FreeRTOSConfig.h中的configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configCHECK_FOR_STACK_OVERFLOW和configUSE_MALLOC_FAILED_HOOK四个宏值这四个宏不为零时会触发钩子函数这些钩子函数需要用户自定义编写如果没有编译会报错。#define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( SystemCoreClock ) #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES ( 5 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 10 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 8 #define configCHECK_FOR_STACK_OVERFLOW 0 #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_MALLOC_FAILED_HOOK 0 #define configUSE_APPLICATION_TASK_TAG 0 #define configUSE_COUNTING_SEMAPHORES 1 #define configGENERATE_RUN_TIME_STATS 0这里测试移植需要进行简化故全部改为0。修改stm32f4xx_it.c文件在 FreeRTOS 的移植过程中会这几到三个重要的中断分别是 FreeRTOS 系统时基定时器的中断SysTick 中断、SVC 中断、PendSV 中断。而STM32CubeMX自动生成的配置代码中会默认在stm32f4xx_it.c文件生成中断的对应中断服务函数。移植需要将原本生成的中断服务函数内容移除不然编译时会报重复定义的错误。在main.h文件中使用了宏 SYS_SUPPORT_OS 来作为屏蔽开关定义是否支持 OS。支持 FreeRTOS时将宏 SYS_SUPPORT_OS 定义为 1。/* USER CODE BEGIN Private defines */ /** * SYS_SUPPORT_OS用于定义系统文件夹是否支持OS * 0,不支持OS * 1,支持OS */ #define SYS_SUPPORT_OS 1 /* USER CODE END Private defines */修改stm32f4xx_it.c对应的三个中断服务函数。/** * brief This function handles System service call via SWI instruction. */ #if (!SYS_SUPPORT_OS) void SVC_Handler(void) { /* USER CODE BEGIN SVCall_IRQn 0 */ /* USER CODE END SVCall_IRQn 0 */ /* USER CODE BEGIN SVCall_IRQn 1 */ /* USER CODE END SVCall_IRQn 1 */ } #endif/** * brief This function handles Pendable request for system service. */ #if (!SYS_SUPPORT_OS) void PendSV_Handler(void) { /* USER CODE BEGIN PendSV_IRQn 0 */ /* USER CODE END PendSV_IRQn 0 */ /* USER CODE BEGIN PendSV_IRQn 1 */ /* USER CODE END PendSV_IRQn 1 */ } #endif/** * brief This function handles System tick timer. */ #if (!SYS_SUPPORT_OS) void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ } #endif编译项目单击“编译”按钮编译完显示“0 Error(s)、0 Warning(s)”。至此FreeRTOS在STM32F407上的移植全部完成。移植验证增加头文件路径/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include freertos.h #include task.h /* USER CODE END Includes */创建测试任务看到小灯LED1闪烁功能验证完成。提供示例代码方便验证。/* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */staticTaskHandle_t LedTaskHandleNULL;/** * brief led0Task * param pvParameters * retval */staticvoidLed0Task(void*pvParameters){while(1){/* USER CODE END WHILE */HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);HAL_Delay(500);}}/* USER CODE END 0 *//** * brief The application entry point. * retval int */intmain(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 */xTaskCreate((TaskFunction_t)Led0Task,(constchar*)Led0Task,(uint16_t)128,(void*)NULL,(UBaseType_t)4,(TaskHandle_t*)LedTaskHandle);vTaskStartScheduler();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1){/* USER CODE BEGIN 3 *//* USER CODE END 3 */}}