GD32F470ZGT6和GD32F450ZGT6是一样的!就是频率不一样摆了。本例程也适用与GD32F450系列。
准备工作
- 准备一块立创梁山派开发板。
- 准备一个可以跑起来的例程(最好有点灯)。如果没有,可以使用立创梁山派官方的例程。
- 准备好FreeRTOS的源码。我使用的版本是202212.01。官网下载链接:https://www.freertos.org/zh-cn-cmn-s/a00104.html
说明:FreeRTOS的官网下载速度很慢,这里我提供我下载好的,里面还有移植前的例程和移植成功之后的例程,链接:https://pan.baidu.com/s/1jFZoOJyp2BnUMQsScmFKvQ?pwd=1234
提取码:1234
移植环境
电脑是WIN10系统。运行与编译环境是使用Keil5.37。
移植步骤
裁剪文件
将下载下来的FreeRTOS 源码进行解压,并删除我们不需要的文件。(只删除【Source】文件夹下的其余文件!)
工程移植
在我们的项目工程里面新建个文件夹【Middlewares】,在【Middlewares】文件夹里再新建一个文件夹【FreeRTOS】,将我们剪裁后的FreeRTOS源码的复制到【FreeRTOS】文件夹下。
文件修改
下图的【portable】文件夹中只留下我们需要的两个文件【MemMang】【RVDS】,【portable】文件夹下的其余文件夹全部删除。
删除完成之后,剩下的文件。
导入工程文件
- 打开我们的工程.
- 新增一个工程目录.
- 添加FreeRTOS文件夹下的.c文件。
- 添加heap_4.c文件,具体路径:【FreeRTOS】->【portable】->【MemMang】-> heap_4.c
- 添加port.c文件,具体路径:【FreeRTOS】->【portable】->【RVDS】->【ARM_CM4F】-> port.c
- 全部添加完成之后,是下图中展示的样子
添加源码缺少的文件
工程还缺少一个FreeRTOSConfig.h文件,因为Cortex_STM32f4系列和GD32f4用的是同一个内核,配置文件可以通用,所以去到FreeRTOS源码中的【Demo】文件夹下复制。
具体路径:【FreeRTOS】->【Demo】-> 【CORTEX_M4F_STM32F407ZG-SK】-> FreeRTOSConfig.h
将FreeRTOSConfig.h(配置文件)复制到我们工程文件夹下。
具体路径:【005串口打印信息】->【Middlewares】->【FreeRTOS】->【include】
导入文件路径
将FreeRTOS的.h路径导入到我们的工程。
- 最终导入的两个路径。
操作到这里,文件的移植就完成了。
修改报错
- 尝试编译。出现以下这个报错。(如果有其他的错误,请看文章最后的说明)
- 双击问题,一路追下去追到了config文件,很明显是因为宏定义没有被开启。(如果有其他的错误,请看文章最后的说明)
- 添加下面的代码。
- 重新编译,出现3个错误。是因为FreeRTOS的port文件和库文件的配置文件重复定义。(如果有其他的错误,请看文章最后的说明)
- 打开gd32f4xx_it.c文件,注释重复定义的三个函数,分别是【PendSV_Handler】、【SVC_Handler】、【SysTick_Handler】。
- 重新编译,出现4个错误。(如果有其他的错误,请看文章最后的说明)
- 上面的4个错误是因为在FreeRTOSConfig文件中宏定义的问题。按照下图在【FreeRTOSConfig.h】中修改四个宏定义。
再编译没有报错啦。(如果有其他的错误,请看文章最后的说明)
移植验证
直接将main.c替换如下:
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "bsp_led.h"
#include "sys.h"
#include "bsp_usart.h"
#include "FreeRTOS.h"
#include "task.h"
TaskHandle_t StartTask_Handler;
void LED_Init(void);
void CrateTask(void *pvParameters);
void task_led2(void *pvParameters);
void task_led4(void *pvParameters);
int main(void)
{
systick_config();
LED_Init(); // led初始化
usart_gpio_config(9600U);
xTaskCreate(CrateTask ,"CrateTask" , 128, NULL, 1, &StartTask_Handler);
vTaskStartScheduler(); //开启任务调度
while(1)
{
;
}
}
void LED_Init(void)
{
//LED2
rcu_periph_clock_enable(RCU_GPIOD);
gpio_mode_set(GPIOD,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_7);
gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_7);
//LED4
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOA,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_5);
gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_5);
}
void CrateTask(void *pvParameters){
taskENTER_CRITICAL();
xTaskCreate(task_led2 , "task_led2" ,50 ,NULL , 2 ,0);
xTaskCreate(task_led4 , "task_led4" ,50 ,NULL , 2 ,0);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
void task_led2(void *pvParameters)
{
while(1)
{
gpio_bit_write(GPIOD, GPIO_PIN_7, SET);
vTaskDelay(300);
gpio_bit_write(GPIOD, GPIO_PIN_7, RESET);
vTaskDelay(300);
}
}
void task_led4(void *pvParameters)
{
while(1)
{
gpio_bit_write(GPIOA, GPIO_PIN_5, SET);
vTaskDelay(200);
gpio_bit_write(GPIOA, GPIO_PIN_5, RESET);
vTaskDelay(200);
}
}
我这里的实验现象是两个灯以不同的频率闪烁。
说明
工程的配置请尽量和我一样。