中电港萤火工场推出的GD32VW553-IOT开发板基于兆易创新(GigaDevice)GD32VW553系列MCU。这款MCU的CPU主频最高160MHZ,IP是基于芯来Nuclei N307处理器的riscv32位通用cpu IP,指令集支持I(整数指令)、M(整数乘除法指令)、A(原子指令)、F(单精度浮点指令)、D(双精度浮点指令)、C(压缩指令)。MCU配备4MB Flash, 320KB SRAM。无线通信方面支持WiFi6和BLE5.2。这规格应该和友商的ESP32-C6有一拼,所以笔者挺有兴趣的。
Linux下开发环境搭建
开发环境主要解决编译工具链、源码工程组织和烧录/调试。笔者的编译工具链没使用Nuclei的,而是用的通用xpack-riscv-none-elf-gcc工具链,笔者不太喜欢一个MCU就要搞一套工具链。源码工程组织笔者用cmake结合手写CMakeLists.txt。烧录调试笔者原来准备用openocd,但拿到板子那刻改主意了--板子的jtag引脚都没有,只是测量点,还是用串口烧录工具吧。
下载xpack-riscv-none-elf-gcc工具链
去xpack官网下载此工具链,笔者因以前下载过,所以直接沿用。
下载GD32VW553 Firmware Libraray
如果不开发WiFI/BT相关的,可以只下载Firmware Libraray,从https://www.gd32mcu.com/cn/download/7?kw=GD32VW5这里找到Firmware Libraray下载即可
点灯测试代码编写
因为板子无软件可控LED,所以笔者用串口打印模拟LED开和关。要打印么所以需要初始化串口,这个可参考官方Firmware Libraray中的Examples/USART/Printf/目录下代码。要延时么所以需要初始化MTIME,这相当于arm cortex-m下的systick,代码可参考官方Firmware Libraray中的Examples/GPIO/Running_led/。笔者的最终代码如下:
static void com_usart_init(void)
{
/* enable COM GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);
/* connect port to USART TX */
gpio_af_set(GPIOB, GPIO_AF_8, GPIO_PIN_15);
/* connect port to USART RX */
gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_8);
/* configure USART Tx as alternate function push-pull */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_15);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_15);
/* configure USART Rx as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_8);
/* USART configuration */
usart_deinit(USART0);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_baudrate_set(USART0, 115200U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}
int main(void)
{
com_usart_init();
systick_config();
printf("\r\nHello GD32VW553\r\n");
while(1) {
printf("Led on\r\n");
delay_1ms(500);
printf("Led off\r\n");
delay_1ms(500);
}
}
CMakeLists.txt编写
注意下gcc的一些CFLAGS参数。例如因cpu是rv32imafdc,所以传递"-march=rv32imafdc -mabi=ilp32d"等等,然后把Firmware Libraray源码和头文件都添加好即可。笔者最终的CMakeLists.txt如下所示:
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
cmake_minimum_required(VERSION 3.20)
set(CMAKE_C_COMPILER riscv-none-elf-gcc)
set(CMAKE_CXX_COMPILER riscv-none-elf-g++)
set(CMAKE_ASM_COMPILER riscv-none-elf-gcc)
set(CMAKE_AR riscv-none-elf-ar)
set(CMAKE_OBJCOPY riscv-none-elf-objcopy)
set(CMAKE_OBJDUMP riscv-none-elf-objdump)
set(SIZE riscv-none-elf-size)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
add_compile_options(-march=rv32imafdc -mabi=ilp32d -mcmodel=medany -msmall-data-limit=8)
add_compile_options(-Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common)
project(gd32vw553 C ASM)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 99)
include_directories(Firmware/GD32VW55x_standard_peripheral/Include
Firmware/GD32VW55x_standard_peripheral
Firmware/RISCV/drivers
Examples/demo
Utilities
)
add_definitions(-DAT32F437ZMT7 -DAT_START_F437_V1)
file(GLOB_RECURSE SOURCES
"Firmware/GD32VW55x_standard_peripheral/Source/*.c"
"Firmware/GD32VW55x_standard_peripheral/system_gd32vw55x.c"
"Firmware/RISCV/env_Eclipse/*.c"
"Firmware/RISCV/env_Eclipse/*.S"
"Firmware/RISCV/stubs/*.c"
"Examples/demo/*.c"
)
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/Firmware/RISCV/env_Eclipse/GD32VW553xM.lds)
add_link_options(
-march=rv32imafdc -mabi=ilp32d -nostartfiles
-Wl,--gc-sections,--print-memory-usage,--no-warn-rwx-segments,-Map,${PROJECT_NAME}.map
--specs=nano.specs
--specs=nosys.specs)
add_link_options(-T ${LINKER_SCRIPT})
add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})
# target_link_libraries(${PROJECT_NAME}.elf printfloat)
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
set(LST_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.lst)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
COMMAND ${CMAKE_OBJDUMP} --all-headers --demangle --disassemble $<TARGET_FILE:${PROJECT_NAME}.elf> > ${LST_FILE
}
COMMAND ${SIZE} --format=berkeley $<TARGET_FILE:${PROJECT_NAME}.elf>
)
编译
bcmake -B /tmp/build
cmake --build /tmp/build -j8
编译完毕以后在/tmp/build目录下有一个名为gd32vw553.bin的文件,此文件烧录进板子即可
固件烧录
这是笔者唯一未在linux下成功做到的步骤,所以最后是在windows下用官方烧录工具烧录的,具体步骤其它网友文章都都有,在此略过不提。
运行截图
启动minicom连/dev/ttyUSB0, 波特率115200bps,8n1。运行截图如下所示:
编译测试视频如下
https://www.bilibili.com/video/BV1YoZ8YbE7U/

