使用GD32VF103固件库创建Makeflie工程

本文简单介绍如何使用GD32VF103固件库创建一个 Makeflie模板工程,基于RV-STAR开发板。
相关介绍
GD32VF103固件库
GD32VF103固件库类似STM32固件库,是MCU厂商提供的一套对 GD32VF103外设进行封装的C语言库,为开发者提供了比直接 操作寄存器更友好的接口,提高开发效率。
Makefile工程
Makeflie工程
指用Makeflie
管理的整个编译项目工程,
在C项目中经常使用Makeflie
自动化管理多个源文件、头文件、库、目标文件等之间的关系。
其他
本文仅介绍Makeflie模板工程的创建,关于如何获取与配置 工具链、搭建开发环境可参考本站另一篇文章: 在Arch Linux下搭建GD32VF103开发环境。
准备工作
GD32VF103固件库文件目录说明
从GD32VF103固件库Github仓库 下载固件库源码,主要文件说明如下:
Examples
路径下对GD32VF103各主要功能模块给出示例程序。Firmware
路径是创建Makeflie工程的核心部分,包含了对 各主要功能模块和外设接口、MCU内核功能的封装,还有创建 Makeflie工程需要的链接脚本(.lds
文件),启动代码(.s
文件)等。Template
基于GD32VF103V-EVAL-V1.0
评估板给出了一个Makeflie示例 工程。Utilities
路径下给出了针对GD32VF103V-EVAL-V1.0
评估板部分硬件 接口的封装。
准备我们需要的文件
我们的Makeflie工程文件目录如下:
Template
├── Firmware
│ ├── GD32VF103_standard_peripheral
│ ├── GD32VF103_usbfs_driver
│ └── RISCV
├── Makefile
├── openocd_gd32vf103.cfg
├── setup
├── inc
│ ├── gd32vf103_libopt.h
│ └── main.h
└── src
├── handlers.c
├── init.c
└── main.c
Firmware
从固件库中拷贝得到;Makefile
文件从固件库中的Template
拷贝得到,将会根据我们的 实际工程进行修改;openocd_gd32vf103.cfg
是供OpenOCD
使用的配置文件;setup
文件用于在构建工程前执行make setup
添加环境变量;inc
和src
下的文件根据具体项目所实现的功能不同内容有所不同, 但基本都会包含一个main.c
文件实现main
函数,init.c
包含 板初始化,handlers.c
包含中断和异常服务程序,gd32vf103_libopt.h
配置哪些外设和功能模块开启。
完善模板工程
-
我们的项目可能不需要启用所有的外设功能,因此可以不用在构建时 编译所有外设相关的代码,以缩短构建所需的时间。去掉
Makeflie
文件C_SOURCES
中的$(wildcard $(FIRMWARE_DIR)/GD32VF103_standard_peripheral/Source/*.c)
, 取而代之地一一列出需要编译的外设代码对应的.c
文件,如下:# C sources C_SOURCES = \ $(wildcard $(FIRMWARE_DIR)/GD32VF103_standard_peripheral/*.c) \ $(wildcard $(FIRMWARE_DIR)/RISCV/stubs/*.c) \ $(wildcard $(FIRMWARE_DIR)/RISCV/drivers/*.c) \ $(wildcard src/*.c) \ $(wildcard ./*.c) \ $(FIRMWARE_DIR)/GD32VF103_standard_peripheral/Source/gd32vf103_rcu.c \ $(FIRMWARE_DIR)/GD32VF103_standard_peripheral/Source/gd32vf103_gpio.c \ $(FIRMWARE_DIR)/GD32VF103_standard_peripheral/Source/gd32vf103_usart.c
然后在
gd32vf103_libopt.h
去掉所有不需要的外设相关头文件的include
:#ifndef GD32VF103_LIBOPT_H #define GD32VF103_LIBOPT_H // #include "gd32vf103_adc.h" // ... // #include "gd32vf103_fmc.h" #include "gd32vf103_gpio.h" #include "gd32vf103_rcu.h" #include "gd32vf103_usart.h" #include "n200_func.h" #endif /* GD32VF103_LIBOPT_H */
-
板初始化过程中通常包含配置系统时钟相关的操作,在
Firmware
中的system_gd32vf103.c
文件中包含了一个SystemInit
接口函数,根据 相关宏定义配置MCU主频。如以下所示,在调用SystemInit
后主频会被 配置为108Mhz:/* select a system clock by uncommenting the following line */ /* use IRC8M */ //#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) //#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) //#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) /********************************************************************/ //#define __SYSTEM_CLOCK_HXTAL (HXTAL_VALUE) //#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000) /********************************************************************/ //#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000) //#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) //#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000) //#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) //#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) #define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)
可以在
main
函数中调用SystemInit()
,也可以在启动代码中在call main
操作之前添加call _init
:call _init /* argc = argv = 0 */ li a0, 0 li a1, 0 call main tail exit
-
Makeflie
文件中根据实际的开发板和调试工具,OpenOCD
相关的操作调整为 如下部分:flash: all -openocd -f ./openocd_gd32vf103.cfg -c "program {$(BUILD_DIR)/$(TARGET).elf} verify reset exit" debug: -openocd -f ./openocd_gd32vf103.cfg
使用
make flash
即可下载程序到开发板;使用make debug
即可 开启gdb调试服务。
测试
以点亮LED灯作为测试Makeflie工程的例子,main.c
文件示例如下:
#include "gd32vf103_rcu.h"
#include "gd32vf103_gpio.h"
#include "n200_func.h"
#define LEDG_PIN GPIO_PIN_1
#define LEDG_GPIO_PORT GPIOA
void delay_ms(uint32_t nms)
{
uint64_t delta_time;
uint64_t delay_ticks = TIMER_FREQ * (uint64_t)nms / 1000;
uint64_t start_time = get_timer_value();
do{
delta_time = get_timer_value() - start_time;
} while(delta_time < delay_ticks);
}
void main()
{
rcu_periph_clock_enable(RCU_GPIOA);
gpio_bit_set(LEDG_GPIO_PORT, LEDG_PIN);
gpio_init(LEDG_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_10MHZ, LEDG_PIN);
while(1){
gpio_bit_set(LEDG_GPIO_PORT, LEDG_PIN);
delay_ms(1000);
gpio_bit_reset(LEDG_GPIO_PORT, LEDG_PIN);
delay_ms(1000);
}
}
- 执行
make
构建工程; - 连接开发板;
- 执行
make flash
把程序下载到开发板; - 以上几步都成功可以看到开发板的绿色LED灯每秒钟亮/灭一次。