兆易创新GD32L233KBT6开源编译环境搭建(gcc+vscode+eide)
移植过程整体比较简单,但是最坑的就是ld文件中的RAM大小一定要填对,而不是某型号最大支持多少就是多少,比如GD32L233系列最大256KB FLASH,32KB RAM,没有用!如果你用的芯片属于这个系列,但是flash和ram都要小一些必须修改为正确的值!不然启动不了!整个过程归纳总结如下:1.eide导入mdk工程2.从armcc切换到gcc编译器3.创建ld文件并填写链接文件路径4.创建
1.准备工作
- 电脑安装vscode。
- vscode中通过插件搜索EIDE并安装。
- 下载官方GD32L233demo例程。
2.移植过程
2.1 EIDE导入例程ARM-MDK工程





2.2 切换gcc编译器
点击【构建配置】右边的双箭头,下拉菜单选择GNU Arm Embedded Toolchain GCC,如果电脑没安装会提示自动安装,等待完成即可。
2.3 导入ld文件
gcc编译器必须指定ld文件才能完成链接动作,而keil是UI界面直接配置了FLASH,RAM地址,所以这里存在差异。官方没有提供ld文件,GD32L233的ld文件内容如下,可以新建txt拷贝下面的内容然后修改文件后缀为ld即可。然后eide这里把ld文件路径填入。
注意文件中_estack的定义,必须和芯片规格完全一致,比如GD32L233KBT6的FLASH是128KB,RAM是24KB,MEMORY中就要对应修改为128K和24K,否则启动时会直接进入hardfault!这里容易忽略因为原来默认RAM的LENGTH写的32K!但是GD32L233KBT6的RAM为24K! 如果是其他型号,自行对号入座修改RAM的LENGTH即可!
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /*end of RAM 注意这里栈的起始位置为内存结束位置,一定要和具体芯片RAM大小对应上,不然会开机无法启动! */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.ARM.attributes : { *(.ARM.attributes) } > FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = .;
/* Initialized data sections goes into RAM, load LMA copy after code */
.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
heap_low = .;
. = . + _Min_Heap_Size;
heap_top = .;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}

2.4 切换启动文件startup_xxx.s
启动文件定义了中断向量,reset_handler等重要信息,是开机第一步运行的代码文件,原来工程中的startup_gd32l233xx.s是专门为keil环境编写的,不适用于gcc,需要修改,可以新建一个.s文件并拷贝如下内容,然后在eide工程中替换原来的.s即可。
/**
******************************************************************************
* @file startup_gd32l23x.s
* @author Giulio Dalla Vecchia
* @brief GD32L233C device vector table for GCC toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
******************************************************************************
* @attention
*
* Copyright (c) 2022 Giulio Dalla Vecchia
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m23
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address of the static initialization data */
.word _sidata
/* start address of the data section */
.word _sdata
/* end address of the data section */
.word _edata
/* start address of the bss section */
.word _sbss
/* end address of the bss section */
.word _ebss
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
@ Reset_Handler:
@ ldr r0, =_estack
@ mov sp, r0 /* set stack pointer */
@ /* Call the clock system initialization function.*/
@ bl SystemInit
@ /* Copy the data segment initializers from flash to SRAM */
@ ldr r0, =_sdata
@ ldr r1, =_edata
@ ldr r2, =_sidata
@ movs r3, #0
@ b LoopCopyDataInit
@ CopyDataInit:
@ ldr r4, [r2, r3]
@ str r4, [r0, r3]
@ adds r3, r3, #4
@ LoopCopyDataInit:
@ adds r4, r0, r3
@ cmp r4, r1
@ bcc CopyDataInit
@ /* Zero fill the bss segment. */
@ ldr r2, =_sbss
@ ldr r4, =_ebss
@ movs r3, #0
@ b LoopFillZerobss
@ FillZerobss:
@ str r3, [r2]
@ adds r2, r2, #4
@ LoopFillZerobss:
@ cmp r2, r4
@ bcc FillZerobss
Reset_Handler:
ldr r0, =_estack
mov sp, r0 /* set stack pointer */
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* start execution of the program */
bl main
bx lr
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
*
* @param None
* @retval : None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The STM32H725ZGTx vector table. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word 0
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* external interrupts handler */
.word WWDGT_IRQHandler /* Window Watchdog interrupt */
.word LVD_IRQHandler /* PVD through EXTI line */
.word TAMPER_STAMP_IRQHandler /* RTC tamper, timestamp */
.word RTC_WKUP_IRQHandler /* RTC Wakeup interrupt */
.word FMC_IRQHandler /* Flash memory */
.word RCU_CTC_IRQHandler /* RCC global interrupt */
.word EXTI0_IRQHandler /* EXTI Line 0 interrupt */
.word EXTI1_IRQHandler /* EXTI Line 1 interrupt */
.word EXTI2_IRQHandler /* EXTI Line 2 interrupt */
.word EXTI3_IRQHandler /* EXTI Line 3interrupt */
.word EXTI4_IRQHandler /* EXTI Line 4interrupt */
.word DMA_Channel0_IRQHandler /* DMA1 Stream0 */
.word DMA_Channel1_IRQHandler /* DMA1 Stream1 */
.word DMA_Channel2_IRQHandler /* DMA1 Stream2 */
.word DMA_Channel3_IRQHandler /* DMA1 Stream3 */
.word DMA_Channel4_IRQHandler /* DMA1 Stream4 */
.word DMA_Channel5_IRQHandler /* DMA1 Stream5 */
.word DMA_Channel6_IRQHandler /* DMA1 Stream6 */
.word ADC_IRQHandler /* ADC1 and ADC2 */
.word USBD_HP_IRQHandler /* FDCAN1 Interrupt 0 */
.word USBD_LP_IRQHandler /* FDCAN2 Interrupt 0 */
.word TIMER1_IRQHandler /* FDCAN1 Interrupt 1 */
.word TIMER2_IRQHandler /* FDCAN2 Interrupt 1 */
.word TIMER8_IRQHandler /* EXTI Line[9:5] interrupts */
.word TIMER11_IRQHandler /* TIM1 break interrupt */
.word TIMER5_IRQHandler /* TIM1 update interrupt */
.word TIMER6_IRQHandler /* TIM1 trigger and commutation */
.word USART0_IRQHandler /* TIM1 capture / compare */
.word USART1_IRQHandler /* TIM2 global interrupt */
.word UART3_IRQHandler /* TIM3 global interrupt */
.word UART4_IRQHandler /* TIM4 global interrupt */
.word I2C0_EV_IRQHandler /* I2C1 event interrupt */
.word I2C0_ER_IRQHandler /* I2C1 global error interrupt */
.word I2C1_EV_IRQHandler /* I2C2 event interrupt */
.word I2C1_ER_IRQHandler /* I2C2 global error interrupt */
.word SPI0_IRQHandler /* SPI1 global interrupt */
.word SPI1_IRQHandler /* SPI2 global interrupt */
.word DAC_IRQHandler /* USART1 global interrupt */
.word 0 /* USART2 global interrupt */
.word I2C2_EV_IRQHandler /* USART3 global interrupt */
.word I2C2_ER_IRQHandler /* EXTI Line[15:10] interrupts */
.word RTC_Alarm_IRQHandler /* RTC alarms (A and B) */
.word USBD_WKUP_IRQHandler /* Reserved */
.word EXTI5_9_IRQHandler /* TIM8 and 12 break global */
.word 0 /* TIM8 and 13 update global */
.word 0 /* TIM8 and 14 trigger /commutation and global */
.word 0 /* TIM8 capture / compare */
.word EXTI10_15_IRQHandler /* DMA1 Stream7 */
.word 0 /* FMC global interrupt */
.word 0 /* SDMMC1 global interrupt */
.word 0 /* TIM5 global interrupt */
.word 0 /* SPI3 global interrupt */
.word 0 /* UART4 global interrupt */
.word 0 /* UART5 global interrupt */
.word 0 /* TIM6 global interrupt */
.word DMAMUX_IRQHandler /* TIM7 global interrupt */
.word CMP0_IRQHandler /* DMA2 Stream0 interrupt */
.word CMP1_IRQHandler /* DMA2 Stream1 interrupt */
.word I2C0_WKUP_IRQHandler /* DMA2 Stream2 interrupt */
.word I2C2_WKUP_IRQHandler /* DMA2 Stream3 interrupt */
.word USART0_WKUP_IRQHandler /* DMA2 Stream4 interrupt */
.word LPUART_IRQHandler /* Ethernet global interrupt */
.word CAU_IRQHandler /* Ethernet wakeup through EXTI */
.word TRNG_IRQHandler /* CAN2TX interrupts */
.word SLCD_IRQHandler /* Reserved */
.word USART1_WKUP_IRQHandler /* Reserved */
.word I2C1_WKUP_IRQHandler /* Reserved */
.word LPUART_WKUP_IRQHandler /* Reserved */
.word LPTIMER_IRQHandler /* DMA2 Stream5 interrupt */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDGT_IRQHandler
.thumb_set WWDGT_IRQHandler,Default_Handler
.weak LVD_IRQHandler
.thumb_set LVD_IRQHandler,Default_Handler
.weak TAMPER_STAMP_IRQHandler
.thumb_set TAMPER_STAMP_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FMC_IRQHandler
.thumb_set FMC_IRQHandler,Default_Handler
.weak RCU_CTC_IRQHandler
.thumb_set RCU_CTC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA_Channel0_IRQHandler
.thumb_set DMA_Channel0_IRQHandler,Default_Handler
.weak DMA_Channel1_IRQHandler
.thumb_set DMA_Channel1_IRQHandler,Default_Handler
.weak DMA_Channel2_IRQHandler
.thumb_set DMA_Channel2_IRQHandler,Default_Handler
.weak DMA_Channel3_IRQHandler
.thumb_set DMA_Channel3_IRQHandler,Default_Handler
.weak DMA_Channel4_IRQHandler
.thumb_set DMA_Channel4_IRQHandler,Default_Handler
.weak DMA_Channel5_IRQHandler
.thumb_set DMA_Channel5_IRQHandler,Default_Handler
.weak DMA_Channel6_IRQHandler
.thumb_set DMA_Channel6_IRQHandler,Default_Handler
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
.weak USBD_HP_IRQHandler
.thumb_set USBD_HP_IRQHandler,Default_Handler
.weak USBD_LP_IRQHandler
.thumb_set USBD_LP_IRQHandler,Default_Handler
.weak TIMER1_IRQHandler
.thumb_set TIMER1_IRQHandler,Default_Handler
.weak TIMER2_IRQHandler
.thumb_set TIMER2_IRQHandler,Default_Handler
.weak TIMER8_IRQHandler
.thumb_set TIMER8_IRQHandler,Default_Handler
.weak TIMER11_IRQHandler
.thumb_set TIMER11_IRQHandler,Default_Handler
.weak TIMER5_IRQHandler
.thumb_set TIMER5_IRQHandler,Default_Handler
.weak TIMER6_IRQHandler
.thumb_set TIMER6_IRQHandler,Default_Handler
.weak USART0_IRQHandler
.thumb_set USART0_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak UART3_IRQHandler
.thumb_set UART3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak I2C0_EV_IRQHandler
.thumb_set I2C0_EV_IRQHandler,Default_Handler
.weak I2C0_ER_IRQHandler
.thumb_set I2C0_ER_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak SPI0_IRQHandler
.thumb_set SPI0_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak DAC_IRQHandler
.thumb_set DAC_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak USBD_WKUP_IRQHandler
.thumb_set USBD_WKUP_IRQHandler,Default_Handler
.weak EXTI5_9_IRQHandler
.thumb_set EXTI5_9_IRQHandler,Default_Handler
.weak EXTI10_15_IRQHandler
.thumb_set EXTI10_15_IRQHandler,Default_Handler
.weak DMAMUX_IRQHandler
.thumb_set DMAMUX_IRQHandler,Default_Handler
.weak CMP0_IRQHandler
.thumb_set CMP0_IRQHandler,Default_Handler
.weak CMP1_IRQHandler
.thumb_set CMP1_IRQHandler,Default_Handler
.weak I2C0_WKUP_IRQHandler
.thumb_set I2C0_WKUP_IRQHandler,Default_Handler
.weak I2C2_WKUP_IRQHandler
.thumb_set I2C2_WKUP_IRQHandler,Default_Handler
.weak USART0_WKUP_IRQHandler
.thumb_set USART0_WKUP_IRQHandler,Default_Handler
.weak LPUART_IRQHandler
.thumb_set LPUART_IRQHandler,Default_Handler
.weak CAU_IRQHandler
.thumb_set CAU_IRQHandler,Default_Handler
.weak TRNG_IRQHandler
.thumb_set TRNG_IRQHandler,Default_Handler
.weak SLCD_IRQHandler
.thumb_set SLCD_IRQHandler,Default_Handler
.weak USART1_WKUP_IRQHandler
.thumb_set USART1_WKUP_IRQHandler,Default_Handler
.weak I2C1_WKUP_IRQHandler
.thumb_set I2C1_WKUP_IRQHandler,Default_Handler
.weak LPUART_WKUP_IRQHandler
.thumb_set LPUART_WKUP_IRQHandler,Default_Handler
.weak LPTIMER_IRQHandler
.thumb_set LPTIMER_IRQHandler,Default_Handler
.weak SystemInit
/************************ (C) COPYRIGHT STMicroelectonics *****END OF FILE****/

2.5 设置芯片型号
配置JLINK的芯片名称,不然烧写固件时会报错。如果是其他烧录器,也可以点击【烧录配置】右边的双箭头修改。
2.6 编译
此时按F7编译,可能会报错:
fatal error: core_cm23.h: No such file or directory
193 | #include “core_cm23.h”
| ^~~~~~~~~~~~~
解决此问题只需要两步:
第一步:【芯片支持包】处右键,选择Install CMSIS Core Headers.
第二步:在包含目录中添加MDK-ARM目录下的.cmsis\include目录即可。

2.7 仿真调试
默认是没有仿真调试功能的,需要手动在vscode工作区添加launch.json文件,根据提示创建即可。需要完善svd文件(这个文件可以通过eide的【芯片支持包】下载并指定位置),jink调试配置信息,elf编译输出可调试文件位置信息。



通过eide插件下载芯片支持包,里面包含了svd文件。
launch.json文件内容如下(elf文件和svd文件需要根据情况指定!):
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Cortex Debug",
"cwd": "${workspaceFolder}",
"executable": "${workspaceFolder}\\build\\GD32L233K_START\\GD32L233K_START.elf",
"request": "launch",
"type": "cortex-debug",
"runToEntryPoint": "entry",
"servertype": "jlink",
"interface": "swd",
"device":"GD32L233KBT6",
"svdFile": ".pack/GigaDevice/GD32L23x_DFP.1.0.1/SVD/GD32L23x.svd",
"showDevDebugOutput": "raw",
}]
}
3.总结
移植过程整体比较简单,但是最坑的就是ld文件中的RAM大小一定要填对,而不是某型号最大支持多少就是多少,比如GD32L233系列最大256KB FLASH,32KB RAM,没有用!如果你用的芯片属于这个系列,但是flash和ram都要小一些必须修改为正确的值!不然启动不了!
整个过程归纳总结如下:
1.eide导入mdk工程
2.从armcc切换到gcc编译器
3.创建ld文件并填写链接文件路径
4.创建gcc启动文件并替换原有的startup_xxx.s
5.编译,如果报错找不到cmsis头文件,安装CMSIS头文件库,并添加对应库目录
6.如果需要仿真调试,添加launch.json文件到vscode工作区
完成工程可以到资源区下载:
gd32l233kbt6_gcc_demo
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)