1 首先准备一份上一个博客里的GD32F103C8T6的工程模版
2 从 FreeRTOS官网下载源码,链接如下
FreeRTOS™ - FreeRTOS™
博主下载的是这一版本
FreeRTOSv202406.01-LTS.zip
这两份文件都会上传CSDN资源,或者需要的私聊,下面正式开始移植
1 首先将 下载下来的FreeRTOS源码解压,得到如下
2 在准备好的工程模版下新建一个文件夹命名为:FreeRTOS 如下图
3 将官方FreeRTOS源码如下路径下的文件都复制到工程模版下的FreeRTOS文件夹下
FreeRTOS-LTS\FreeRTOS\FreeRTOS-Kernel
上图红框内的文件都复制到如下图
删除一些工程模版FreeRTOS文件夹下的一些文件,仅保留如下文件
然后在当前FreeRTOS目录下新建一个文件夹src,将FreeRTOS目录下的8个文件剪切到src文件夹下,如下图:
之后进入到portable文件夹下,只保留下图三个文件夹,其余全部删除,如下图:
MemMang下是官方给的5种内存管理的方法,各有长处,根据需要选一种方式即可
实体文件移植好了,下面是虚拟文件的映射了
1 添加src下的文件到工程,如下图
2> 添加portable/MemMang/heap_4文件到工程
添加portable/RVDS/ARM_CM3/port文件到工程,因为GD32F103内核是Cortex-M3内核。
注:F407系列则选CMF4内核
之后点击OK
3 添加相应的头文件路径如下图,然后点击OK
4 缺少FreeRTOSConfig.h这个头文件,我们在FreeRTOS源码中复制一个将这个路径下的
FreeRTOSConfig.h文件添加到工程中,如下图:
至此,配置完成,接下来是测试和编译了
1 首先编译一下出现如下报错
这个报错意味着宏定义错误,因为我们是32位系统要将下列宏定义改为32位
#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS
修改后再编译出现如下报错
这个错误是 FreeRTOS 在 Cortex-M3 内核移植时的一个配置错误,具体原因是 configMAX_SYSCALL_INTERRUPT_PRIORITY 被设置为 0,而这是不允许的。
configMAX_SYSCALL_INTERRUPT_PRIORITY。这个宏定义了 FreeRTOS 可以管理的中断的最高优先级(数值越小,逻辑优先级越高)。如果设置为 0,意味着试图让 FreeRTOS 管理最高硬件优先级的中断(如硬件错误、NMI 等),这是不允许的。
我们配置为如下
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0x60 // 优先级3 表示优先级 ≤ 3 的中断可调用 FreeRTOS API
继续编译出现如下报错
这个错误是链接阶段(Linking)出现的,表示 FreeRTOS 在编译时找不到 vApplicationStackOverflowHook 函数的实现。
错误原因:
FreeRTOS 提供了堆栈溢出检测功能(如果启用了 configCHECK_FOR_STACK_OVERFLOW),但需要用户实现回调函数 vApplicationStackOverflowHook,以便在堆栈溢出时执行自定义处理(如打印错误、复位系统等)。
如果 configCHECK_FOR_STACK_OVERFLOW 设置为 1 或 2,但未提供 vApplicationStackOverflowHook 的实现,链接器就会报此错误。
解决方法
方法 1:禁用堆栈溢出检测(不推荐)
如果你暂时不需要堆栈溢出检测,可以在 FreeRTOSConfig.h 中关闭该功能:
方法 2:实现 vApplicationStackOverflowHook(推荐)
在项目中(通常是 main.c 或 freertos_hooks.c)添加该函数的实现,例如:
#include "FreeRTOS.h"
#include "task.h"void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{(void)xTask; // 避免未使用变量警告printf("ERROR: Stack overflow in task %s\n", pcTaskName);while (1); // 死循环,或触发系统复位
}
我们选用第一种办法修改成如下宏定义
#define configCHECK_FOR_STACK_OVERFLOW 0
编译无报错如下
接下来我们编写一个demo点灯测试
#include "main.h"#include "FreeRTOS.h"
#include "task.h"#define LED1_TASK_PRIO ( tskIDLE_PRIORITY + 2 )void LED1_task(void * pvParameters);int main(void)
{/* 设置优先级分组为4,16个优先级全是抢占优先级 */nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);xTaskCreate(LED1_task, "LED1", configMINIMAL_STACK_SIZE, NULL, LED1_TASK_PRIO, NULL);/* start scheduler */vTaskStartScheduler();while(1){}
}
void LED1_task(void * pvParameters)
{ for( ;; ){/* toggle LED2 each 500ms */LED_SET(1);vTaskDelay(800);LED_SET(0);vTaskDelay(800);}
}
编写好后编译如下,无报错
接下来注释掉三个中断函数,如下图
然后声明也注释掉,如下图
接下来添加一些宏定义如下图
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
然后编译无报错,如下图
点灯程序下载运行后无反应,发现是GPIO未初始化
主程序改为如下,添加IO初始化
#include "main.h"#include "FreeRTOS.h"
#include "task.h"#define LED1_TASK_PRIO ( tskIDLE_PRIORITY + 2 )void LED1_task(void * pvParameters);int main(void)
{GPIO_Init();/* 设置优先级分组为4,16个优先级全是抢占优先级 */nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);xTaskCreate(LED1_task, "LED1", configMINIMAL_STACK_SIZE, NULL, LED1_TASK_PRIO, NULL);/* start scheduler */vTaskStartScheduler();while(1){}
}
void LED1_task(void * pvParameters)
{ for( ;; ){/* toggle LED2 each 500ms */LED_SET(1);vTaskDelay(300);LED_SET(0);vTaskDelay(300);}
}
编译下载,灯闪烁了,代表移植OK
至此结束,后续继续更新这个系列