GD32VW553-IOT 测评和vscode开发环境搭建
分享作者:chuan
评测品牌:萤火工场
评测型号:GD32VW553-IOT
发布时间:2025-09-08 15:34:37
2
前言
iCEasy商城的产品, Firefly Workshop 萤火工场的样片, 是一款基于GD32VW553 MCU的开源硬件, 这款MCU内置了32bit的RISC-V内核, 支持双模无线WIFI-6和BLE-5.2, 最高主频可达160Mhz.
开源口碑分享内容

# GD32VW553-IOT 测评和vscode开发环境搭建

##  1. 背景介绍

iCEasy商城的产品, Firefly Workshop 萤火工厂的样片, 是一款基于GD32VW553 MCU的开源硬件, 这款MCU内置了32bit的RISC-V内核, 支持双模无线WIFI-6和BLE-5.2, 最高主频可达160Mhz.

本人曾在公司参与开发了一款基于RISC-V内核的触控芯片, 所以之前接触过兆易更早的一款RISC-V的MCU, 即GD32VF103, 同时也使用过GD32W5系列的IOT MCU, 这次正好看到了结合GD的V和W联手的产品, 于是就申请了一块板子回来研究研究。


##  2. 准备工作

样品拿到手之后, 先去GD官网把手册和开发软件下载一下, 同时也可以去iCEasy商城网站上下载对应资料。https://www.gd32mcu.com/cn/download/0?kw=GD32VW5

- 用户手册、数据手册

- 固件库、原理图

- GD32AllInOneProgrammer_win

- GD32EmbeddedBuilder


##  3. 展示一下


## 4. 创建工程

基于GD32EmbeddedBuilder可以很方便快速的把demo程序跑起来, 下面是创建工程的步骤, 软件提供了MCU的ARM C project和RISC-V Cproject, 本次测试的芯片是基于RISC-V的, 因此选择对应的选项.

##  5. 工程结构

Firmware目录中是GD的外设库和RISC-V的驱动库, inc和src是具体实现的功能, 可以参考官方提供的demo来移植想要的功能, idscripts提供的链接文件, 指定了芯片的内存大小和布局, openocd提供了基于gd_link的openocd下载脚本。

比较需要注意的是Firmware/RISC-V/env_Eclipse和stubs文件夹, 其中stubs文件夹提供的是一些系统调用的桩函数, env_Eclipse文件夹下提供的entry.S和start.S实现了芯片启动部分和中断向量表设置。

编译选项如图所示:

`riscv-nuclei-elf-gcc -march=rv32imac -mabi=ilp32 -mcmodel=medlow -msmall-data-limit=8 -mdiv -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -std=gnu11 -DGD_ECLIPSE_GCC -DUSE_STDPERIPH_DRIVER ........

`

`riscv-nuclei-elf-gcc -march=rv32imac -mabi=ilp32 -mcmodel=medlow -msmall-data-limit=8 -mdiv -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -Wa,-adhlns=Firmware/RISCV/env_Eclipse/entry.o.lst   -x assembler-with-cpp -I"../Firmware/RISCV/drivers" -c -o "Firmware/RISCV/env_Eclipse/entry.o" "../Firmware/RISCV/env_Eclipse/entry.S"

`

`riscv-nuclei-elf-gcc -march=rv32imac -mabi=ilp32 -mcmodel=medlow -msmall-data-limit=8 -mdiv -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -Wl,-Map,"gd32vw553_test.map" -T GD32VW55X.lds -nostartfiles -Xlinker --gc-sections -L"../ldscripts/" --specs=nano.specs --specs=nosys.specs -o "gd32vw553_test.elf" ......  

`

## 6. 代码下载

1. 启动模式修改, 从表中可以看出, 将BOOT0接高之后, 会从Bootloader启动, 就能用串口ISP更新固件, 根据原理图可以看出, 首先需要将R4和R5两个电阻焊接上


##  7. 串口LOG打印和LED闪烁

1. 使用的是串口0和PA15作为LED口

 ```c

   int main(void)

   {

       /* configure systick */

       systick_config();

       eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL3_PRIO1);

       /* enable the led clock */

       rcu_periph_clock_enable(RCU_GPIOA);

       /* configure led GPIO port */

       gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_15);

       gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_15);

       GPIO_BC(GPIOA) = GPIO_PIN_15;

       /* initilize the LEDs, USART and key */

       gd_eval_com_init(EVAL_COM0);

       /* print out the clock frequency of system, AHB, APB1 and APB2 */

       printf("CK_SYS is %d\r\n", rcu_clock_freq_get(CK_SYS));

       printf("CK_AHB is %d\r\n", rcu_clock_freq_get(CK_AHB));

       printf("CK_APB1 is %d\r\n", rcu_clock_freq_get(CK_APB1));

       printf("CK_APB2 is %d\r\n", rcu_clock_freq_get(CK_APB2));

       while(1) {

           delay_1ms(500);

           GPIO_TG(GPIOA) = GPIO_PIN_15;

       }

   }

```

2. 在桩函数中修改串口打印的功能


 ```c

  int _put_char(int ch)

  {

    usart_data_transmit(EVAL_COM0, (uint8_t) ch );

    while (usart_flag_get(EVAL_COM0, USART_FLAG_TBE)== RESET){

    }

    return ch;

  }

```


3. 将代码下载进板子, 打开串口助手, 可以看到log打印


## 8. vscode开发环境搭建

1. 目录修改


2. CmakeList.txt编写

```

cmake_minimum_required(VERSION 3.22)


# Setup compiler settings

set(CMAKE_C_STANDARD 11)

set(CMAKE_C_STANDARD_REQUIRED ON)

set(CMAKE_C_EXTENSIONS ON)


###########################################################

# Set the project name

set(CMAKE_PROJECT_NAME gd32vw553_test)


set(APP_ADDR "0x08000000")      # 从0x08000000启动

add_definitions(-DDOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP -DDOWNLOAD_MODE_STRING=\"FLASHXIP\" -D__IDE_RV_DE_RV_CORE=n303 -DSYSTEM_CLOCK=160000000 -DSYSCLK_USING_HXTAL)


# Define the build type

if(NOT CMAKE_BUILD_TYPE)

   set(CMAKE_BUILD_TYPE "Debug")

endif()


find_program(CCACHE_FOUND ccache)

if(CCACHE_FOUND)

set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)

set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)

endif(CCACHE_FOUND)


###########################################################

# Include toolchain file

set(CMAKE_SYSTEM_NAME       Generic)

set(CMAKE_SYSTEM_PROCESSOR  riscv)


set(CMAKE_C_COMPILER_FORCED TRUE)

set(CMAKE_CXX_COMPILER_FORCED TRUE)

set(CMAKE_C_COMPILER_ID GNU)

set(CMAKE_CXX_COMPILER_ID GNU)


# Some default GCC settings

# riscv64-unknown-elf- must be part of path environment

set(TOOLCHAIN_PREFIX                riscv64-unknown-elf-)


set(CMAKE_C_COMPILER                ${TOOLCHAIN_PREFIX}gcc)

set(CMAKE_ASM_COMPILER              ${CMAKE_C_COMPILER})

set(CMAKE_CXX_COMPILER              ${TOOLCHAIN_PREFIX}g++)

set(CMAKE_LINKER                    ${TOOLCHAIN_PREFIX}g++)

set(CMAKE_OBJCOPY                   ${TOOLCHAIN_PREFIX}objcopy)

set(CMAKE_SIZE                      ${TOOLCHAIN_PREFIX}size)

set(CMAKE_OpenOCD                   "E:/Program Files/NucleiStudio/toolchain/openocd/bin/openocd.exe")



set(CMAKE_EXECUTABLE_SUFFIX_ASM     ".elf")

set(CMAKE_EXECUTABLE_SUFFIX_C       ".elf")

set(CMAKE_EXECUTABLE_SUFFIX_CXX     ".elf")


set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)


# MCU specific flags

set(TARGET_FLAGS "-march=rv32imac -mabi=ilp32 -mtune=nuclei-200-series -mcmodel=medlow -mno-save-restore")


set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -fno-common")



if(CMAKE_BUILD_TYPE MATCHES Debug)

   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Og -g -gdwarf-2")

endif()

if(CMAKE_BUILD_TYPE MATCHES Release)

   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")

endif()

if(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)

   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g")

endif()

if(CMAKE_BUILD_TYPE MATCHES MinSizeRel)

   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os")

endif()


set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP")


set(CMAKE_C_LINK_FLAGS "${CMAKE_C_FLAGS}")

set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -T \"${CMAKE_SOURCE_DIR}/ldscripts/GD32VW55X.lds\"")

set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostartfiles")

set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--check-sections -Wl,--no-warn-rwx-segments")

set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lc -lm -Wl,--end-group")

set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--print-memory-usage")


set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics")

set(CMAKE_CXX_LINK_FLAGS "${CMAKE_C_LINK_FLAGS}  -Wl,--start-group,-lstdc++,-lc_nano,-lgcc,--end-group")

##########################################################


# Enable compile command to ease indexing with e.g. clangd

set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)


# must need

enable_language(C ASM)


# Core project settings

project(${CMAKE_PROJECT_NAME})

message("Build type: " ${CMAKE_BUILD_TYPE})


# Create an executable object type

add_executable(${CMAKE_PROJECT_NAME})


# 汇编的宏定义

# Add project symbols (macros)

target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE

   # Add user defined symbols

)


# Add linked libraries

target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE

   stm32cubemx

   # Add user defined libraries

)


##########################################################

add_library(stm32cubemx INTERFACE)


target_compile_definitions(stm32cubemx INTERFACE

# TX_INCLUDE_USER_DEFINE_FILE

)


target_include_directories(stm32cubemx INTERFACE

   Application/Include/    

   Hardware/Include/


   Firmware/GD32VW55x_standard_peripheral/

   Firmware/GD32VW55x_standard_peripheral/Include/


   Firmware/RISCV/drivers/


   # Firmware/OS/FreeRTOS/Source/include

   # Firmware/OS/FreeRTOS/Source/portable


   # Firmware/OS/ThreadX/common/inc

   # Firmware/OS/ThreadX/ports/nuclei/

)


file(GLOB SRC_LIB_0 Firmware/GD32VW55x_standard_peripheral/*.c)

file(GLOB SRC_LIB_1 Firmware/GD32VW55x_standard_peripheral/Source/*.c)

file(GLOB SRC_LIB_2 Firmware/RISCV/env_Eclipse/*.c)

file(GLOB SRC_LIB_3 Firmware/RISCV/stubs/*.c)



# file(GLOB SRC_LIB_4 Firmware/OS/FreeRTOS/Source/*.c)

# file(GLOB SRC_LIB_5 Firmware/OS/FreeRTOS/Source/portable/*.c)

# file(GLOB SRC_LIB_6 Firmware/OS/FreeRTOS/Source/portable/MemMang/*.c)

# file(GLOB SRC_LIB_7 Firmware/OS/FreeRTOS/Source/portable/GCC/portasm.S)


# file(GLOB SRC_LIB_4 Firmware/OS/ThreadX/common/src/*.c)

# file(GLOB SRC_LIB_5 Firmware/OS/ThreadX/ports/nuclei/*.c)

# file(GLOB SRC_LIB_6 Firmware/OS/ThreadX/ports/nuclei/gcc/context.S)

# file(GLOB SRC_LIB_7 Firmware/OS/ThreadX/ports/nuclei/gcc/interrupt.S)



file(GLOB SRC_APP_0 Application/Source/*.c)

file(GLOB SRC_APP_1 Hardware/Source/*.c)


target_sources(stm32cubemx INTERFACE

   ${SRC_APP_0}

   ${SRC_APP_1}


   ${SRC_LIB_0}

   ${SRC_LIB_1}

   ${SRC_LIB_2}

   ${SRC_LIB_3}

   ${SRC_LIB_4}

   ${SRC_LIB_5}

   ${SRC_LIB_6}

   ${SRC_LIB_7}


   # GLOB *.S doesn't work

   Firmware/RISCV/env_Eclipse/entry.S

   Firmware/RISCV/env_Eclipse/start.S

)

##########################################################

# For Download & Debug

set(ELF_FILE ${PROJECT_NAME}.elf)

set(HEX_FILE ${PROJECT_NAME}.hex)

set(BIN_FILE ${PROJECT_NAME}.bin)

set(DFU_FILE ${PROJECT_NAME}.dfu)


# PRE_BUILD(预构建)、PRE_LINK(链接前)和POST_BUILD(构建后)用于指定自定义命令在构建过程中的执行时机。

add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD

   COMMAND ${CMAKE_OBJCOPY} -Obinary -S ${ELF_FILE} ${BIN_FILE}

   COMMAND ${CMAKE_OBJCOPY} -Oihex  ${ELF_FILE} ${HEX_FILE}

   COMMENT "Building ${PROJECT_NAME}.bin and ${PROJECT_NAME}.hex"

)


# print size

add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD

   COMMAND ${CMAKE_SIZE} --format=berkeley ${PROJECT_NAME}.elf

   COMMENT "Invoking: Cross ARM GNU Print Size"

)


# make openocd_flash

add_custom_target(openocd_flash

COMMAND ${CMAKE_OpenOCD} -f "${CMAKE_SOURCE_DIR}/nuclei_sdk/SoC/gd32vf103/Board/gd32vf103v_rvstar/openocd_gd32vf103.cfg" -c "program gd32vf103.elf verify reset exit"

COMMENT "USE OpenOCD to make flash at ${APP_ADDR}"

)


```

3. 编译工具链配置(这里windows平台工具链下载就不多说了,下载对应工具,然后添加环境变量可以找找其他教程)

- gcc

- riscv-none-embed-gcc

- ninja

- cmake

- cacache


##  9. Timer Breath LED

1. 移植DEMO中的Timer Breath LED功能

##  10. 移植MBL和MSDK

SDK 最终生成的执行程序主要有两个:一个是 MBL(Main Bootloader),一个是 MSDK

( Main SDK ) 。它们最终都将被烧写到 FLASH 运行。 上电之后, 程序将从 MBL 的

Reset_Handler 启动,然后跳转到 MSDK 主程序运行


1. 三个配置文件

- GD32VW55x_RELEASE/config/platform_def.h 用于配置WIFI 和 BLE

- GD32VW55x_RELEASE/config/config_gdm32.h 用于设置Flahs和SRAM内存布局

- GD32VW55x_RELEASE/MSDK/app/app_cfg.h 用于配置一些无线相关的应用, 例如: ATCMD,阿里云, MQTT, COAP


注:通过修改 app_cfg.h 内的宏CONFIG_BLE_LIB 可切换BLE library。将 CONFIG_BLE_LIB 配

置为 BLE_LIB_MIN,工程编译时会选择libble.a,同时头文件会include ble_config_min.h;将CONFIG_BLE_LIB 配置为BLE_LIB_MAX, 工程编译时会选择 libble_max.a,同时头文件会include ble_config_max.h。


2. 工程配置


3. 编译工程

- Embedded Builder IDE 下编译和调试 SDK。首先下载GD32VW55x_RELEASE, 目前官网最新版本是1.0.3a.

- 将workspaces 指向 GD32VW55x_RELEASE 目录

- 然后选择 MSDK 或 MBL 工程进行导入, 路径为GD32VW55x_RELEASE/MBL/project/eclipse和GD32VW55x_RELEASE/MSDK/projects/eclipse/msdk

- 分别编译 MBL 和 MSDK 工程

- MSDK 编译完成之后, 会调用 MSDK/projects/image_afterbuild.bat 生成 image-ota.bin 和image-all.bin。并将生成的 bin 文件拷贝至/scripts/images 内, image-ota.bin是MSDK工程生成的bin文件,可用于OTA 升级, image-all.bin是MBL(mbl.bin)和 MSDK(image-ota.bin)的组合,该固件可用于生产,烧录到 FLASH 中运行


4. 编译报错

编译MSDK时候,出现了以下错误信息, 而且image没有成功生成

导致的原因是bat命令没有识别出我路径中的空格, 这里我的路径是program file, 导致脚本将空格之后和空格之前设别成了两条指令,解决办法就是将整个路径用双引号括起来

## 11. 初始化成功

## 视频链接和项目地址

1. https://github.com/1508912767/gd32vw553_test

2. https://www.bilibili.com/video/BV1MEeJzrE9u/

如果对vscode移植需求多的话,回头再弄个bootloder的移植

全部评论
暂无评论
0/144