使用GD32VF103固件库创建Makeflie工程

使用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添加环境变量;
  • incsrc下的文件根据具体项目所实现的功能不同内容有所不同, 但基本都会包含一个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灯每秒钟亮/灭一次。

参考

  1. GD32VF103固件库Github仓库
  2. RV-STAR开发板简介
  3. 在Arch Linux下搭建GD32VF103开发环境