GD32E507移植FreeRTOS

一、准备工作

硬件平台:一块GD32E507Z-EVAL评估板(MCU是GD32E507ZET6)

软件开发环境:KEIL

源码:GD32官方源码(标准库),FreeRTOS源码(FreeRTOSv202107.00)

二、创建工程

由于GD32提供的源码有多份例程,这些例程会共用相同的源码,比如CMSIS里的文件,Utilities里的文件和GD32E50x_standard_peripheral里的文件等。所以最好需要单独创建一个工程,把这些文件复制一份出来,用于这个工程。这里我复制的工程师跑马灯的工程。

 

 其中FreeRTOS是后期移植的,现在暂时可以不管这个文件夹。我们来看看其他文件夹里都有什么东西:

  ①   Application文件夹

 

 

 

  ②  CMSIS文件夹

这个文件夹也是在GD32官方源码中复制过来的:

 

 

   ③  GD32E50x_standard_peripheral文件夹

GD32E50x的标准库函数:

 

 

   ④  Utilities文件夹

 

 

 复制完成后,添加必须的文件到工程中:

 

 包含头文件路径:

 

 编译看有没有什么错误,并下载到板子上,如果LED可以根据需求运行起来,说明工程创建没问题,接下来就是移植FreeRTOS了。

三、移植FreeRTOS

创建一个FreeRTOS的文件夹,进入文件夹中再创建一个“source”文件夹和一个“portable”文件夹,“source”文件夹中再创建一个“src”文件夹和一个“inc”文件夹。

  ①  把FreeRTOS源码中的“Source”文件夹中的C文件复制到我们工程中的FreeRTOS->source->src

 

 

 

 

   ②   把FreeRTOS源码中的Source目录下的“include”文件夹中的内容全部复制到FreeRTOS->source->inc中:

 

   ③  把FreeRTOS源码中的“Source”目录中的“portable”文件夹整个复制到工程目录中的FreeRTOS目录下:

 

 把一些不重要的文件夹删除,只保留“Keil”、“MemMang”、“RVDS”三个文件夹即可:

 

 然后把一些源文件添加到工程中:

 

 再添加头文件路径:

 

 PS:RVDS文件夹中本来是没有ARM_CM33_NTZ这个文件夹的,这是我从FreeRTOS源码中复制过来的,路径如下图所示:

 

 里面包含的内容如下:

 

 暂时没了解这些文件的作用是什么,打算慢慢在实践的过程中去了解,毕竟总是学习理论知识也是很枯燥的。

 

接着,我们编译一下,不出意外的话,一定会报错,而且跟“FreeRTOSConfig.h”这个头文件有关系,因为我们移植的时候并没有把它移植过来,所以现在需要去找到这个文件,把它移植过来。因为我们的MCU是Cortex-M33内核的,所以必须找这一款内核的例程来移植。我在官方的例程找到一个:

 

 这个例程的Config文件中就有这么一个头文件:

 

 复制到我们的工程中的某一个inc文件夹中,记得必须包含这个头文件路径,再编译一下,可能会出现很多报错,比如重定义,下面这三个函数在portasm.c中已经有定义,所以把此处的函数屏蔽掉即可。

 

 另外可能还有一些钩子函数的报错,这是FreeRTOSConfig.h中相关的宏定义被设置为非0数值,使能了却没有相应的函数来执行操作,所以把这些宏定义设置为0即可。

 

 可能还有其他的报错,一般都是修改FreeRTOSConfig.h中的宏定义就可以解决了。具体问题需要具体分析。

接下来,开始编写代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "gd32e50x.h"
#include "systick.h"
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
 
 
#define LED1_ON             gpio_bit_set(GPIOG, GPIO_PIN_10)
#define LED1_OFF            gpio_bit_reset(GPIOG, GPIO_PIN_10)
 
#define LED2_ON             gpio_bit_set(GPIOG, GPIO_PIN_11)
#define LED2_OFF            gpio_bit_reset(GPIOG, GPIO_PIN_11)
 
#define LED3_ON             gpio_bit_set(GPIOG, GPIO_PIN_12)
#define LED3_OFF            gpio_bit_reset(GPIOG, GPIO_PIN_12)
 
#define LED4_ON             gpio_bit_set(GPIOG, GPIO_PIN_13)
#define LED4_OFF            gpio_bit_reset(GPIOG, GPIO_PIN_13)
 
 
#define START_TASK_PRIO   1
#define START_STK_SIZE      120
TaskHandle_t Start_Task_Handler;
 
#define LED_TASK_PRIO     2
#define LED_STK_SIZE        120
TaskHandle_t LED_Task_Handler;
 
void start_task(void * parameter);
void led_task(void * parameter);
 
/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    systick_config();
 
    /* enable the LEDs clock */
    rcu_periph_clock_enable(RCU_GPIOG);
    /* configure LEDs GPIO port */
    gpio_init(GPIOG, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);
    /* reset LEDs GPIO pin */
    gpio_bit_reset(GPIOG, GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);
     
        xTaskCreate(start_task,"start_task",START_STK_SIZE,NULL,START_TASK_PRIO,&Start_Task_Handler);
     
        vTaskStartScheduler();
     
    while(1){
 
    }
}
 
 
void start_task(void * parameter)
{
    xTaskCreate(led_task,"led_task",LED_STK_SIZE,NULL,LED_TASK_PRIO,&Start_Task_Handler);
    vTaskDelete(NULL);
}
 
void led_task(void * parameter)
{
    while(1)
    {
        LED1_ON;
        vTaskDelay(1000);
        LED2_ON;
        vTaskDelay(200);
        LED3_ON;
        vTaskDelay(200);
        LED4_ON;
        vTaskDelay(200);
        LED4_OFF;
        vTaskDelay(200);
        LED3_OFF;
        vTaskDelay(200);
        LED2_OFF;
        vTaskDelay(200);
        LED1_OFF;
        vTaskDelay(1000);
 
    }
}

  

编译后下载到板子上,发现灯变化的速度很慢,经过调试,发现是FreeRTOSConfig.h中有一个宏定义的值小了,

 

 原来定义的是100,LED闪烁的频率很慢,修改为1000后频率正常。

 

posted @   沙河淘金  阅读(1109)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示