【开发环境】
硬件:mac OS 15.2
代码编辑:Vscode
编译工具:arm-none-eabi gcc 14.2
【移植步骤】
1、下载官方示例,在示例中有FreeRTOS的源码,在目录3rdPartySoftwarePorting/FreeRTOS目录下面。
2、把该目录的FreeRTOS-KernelV10.5.1复制到工程目录下面,并重命名为FreeRTOS
3、复制Demos/FreeRTOS_Blinky目录下面的FreeRTOSConfig.h到app目录下面。
工程文件如下图所示:
4、编写FreeRTOS下面的makefile.mk如下:
# 模块名_DIR 是上一层传递下来的参数, # 是从工程根目录到该模块文件夹的路径 # 向 C_SOURCES 中添加需要编译的源文件 C_SOURCES += $(wildcard $(FreeRTOS_DIR)/*.c) C_SOURCES += $(wildcard $(FreeRTOS_DIR)/portable/GCC/ARM_CM33_NTZ/non_secure/*.c) C_SOURCES += $(wildcard $(FreeRTOS_DIR)/portable/MemMang/heap_4.c) # 向 C_INCLUDES 中添加头文件路径 C_INCLUDES += -I$(FreeRTOS_DIR)/include C_INCLUDES += -I$(FreeRTOS_DIR)/portable/GCC/ARM_CM33_NTZ/non_secure
意思是把FreeRTOS下面所有的.c,portable/GCC/ARM_CM33_NTZ/non_secure目录下面所有的.c 以及portable/MemMang/heap_4.c添加进编译。同时添加include 、portable/GCC/ARM_CM33_NTZ/non_secure头文件到工程中。
5、注释掉mm32f5370_it.c中的三个函数SVCall_Handler、PendSV_Handler、SysTick_Handler。
【测试代码】
#define _MAIN_C_ /* Files include */ #include "platform.h" #include "main.h" #include "FreeRTOS.h" #include "task.h" #include "stdio.h" /*********************************************************************************************************************** * @brief This function is main entrance * @note main * @param none * @retval none *********************************************************************************************************************/ //任务优先级 #define START_TASK_PRIO 1 //任务堆栈大小 #define START_STK_SIZE 256 //任务句柄 TaskHandle_t StartTask_Handler; //任务函数 void start_task(void *pvParameters); //任务优先级 #define LED1_TASK_PRIO 2 //任务堆栈大小 #define LED1_STK_SIZE 256 //任务句柄 TaskHandle_t LED1Task_Handler; //任务函数 void led1_task(void *pvParameters); //任务优先级 #define LED2_TASK_PRIO 3 //任务堆栈大小 #define LED2_STK_SIZE 256 //任务句柄 TaskHandle_t LED2Task_Handler; //任务函数 void led2_task(void *pvParameters); int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); PLATFORM_InitConsole(115200); PLATFORM_InitLED(); PLATFORM_PrintInfo(); //创建开始任务 xTaskCreate( start_task , //任务函数 (const char* )"start_task", //任务名称 (uint16_t )START_STK_SIZE, //任务堆栈大小 (void* )NULL, //传递给任务函数的参数 (UBaseType_t )START_TASK_PRIO, //任务优先级 (TaskHandle_t* )&StartTask_Handler); //任务句柄 vTaskStartScheduler(); //开启任务调度 while (1) { } } //开始任务任务函数 void start_task(void *pvParameters) { taskENTER_CRITICAL(); //进入临界区 //创建LED0任务 xTaskCreate((TaskFunction_t )led1_task, (const char* )"led1_task", (uint16_t )LED1_STK_SIZE, (void* )NULL, (UBaseType_t )LED1_TASK_PRIO, (TaskHandle_t* )&LED1Task_Handler); //创建LED1任务 xTaskCreate((TaskFunction_t )led2_task, (const char* )"led2_task", (uint16_t )LED2_STK_SIZE, (void* )NULL, (UBaseType_t )LED2_TASK_PRIO, (TaskHandle_t* )&LED2Task_Handler); vTaskDelete(StartTask_Handler); //删除开始任务 taskEXIT_CRITICAL(); //退出临界区 } //LED0任务函数 void led1_task(void *pvParameters) { while(1) { printf("led1_task\r\n"); GPIO_WriteBit(GPIOB, GPIO_Pin_15, 0); vTaskDelay(500); GPIO_WriteBit(GPIOB, GPIO_Pin_15, 1); vTaskDelay(500); } } //LED1任务函数 void led2_task(void *pvParameters) { while(1) { printf("task2\r\n"); GPIO_WriteBit(GPIOB, GPIO_Pin_14, 0); vTaskDelay(200); GPIO_WriteBit(GPIOB, GPIO_Pin_14, 1); vTaskDelay(200); } }
【测试效果】
下载到开发板后,可以看到两个LED灯以不同频率显示,同时串口也打印出相关的任务:
【总结】
我在前面移植过MM32F5260的FreeRTOS工程,这次移植也是不尽相同,所以上手比较快。注意的是,不要再执行PLATFORM_InitDelay这个初始化函数,否则会卡死在printf里面。