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后频率正常。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?