前言
? ? ? 最近調試一塊?GD32F407VET6(168Mhz,8Mhz晶振) 板子時,踩了一些“啟動失敗”的坑。本以為是時鐘配置有誤,最后發現是鏈接腳本(.ld 文件)沒有配置好,導致程序根本沒能正常執行 main() 函數。
? ? ? 順著這個調試過程,我認真梳理了一遍裸機開發中幾個關鍵文件的作用,也對兆易官方的工程模板、工具鏈支持以及主流開發方式有了更深理解。
? ? ?這篇文章記錄下踩坑的點:
-
GD32F407 是什么
-
.ld、啟動文件 .s、gd32f4xx.h、system_gd32f4xx.c 各自做什么
-
為什么 Keil 用戶往往感知不到這些文件
-
用 VS Code + GCC 為什么必須掌握這些底層配置
-
順帶了解 RT-Thread 軟件包在裸機開發中的角色
具體的構建燒錄可以參考我前陣寫的關于STM32板子的文章:
真.從“零”搞 VSCode+STM32CubeMx+C <1>構建
真.從“零”搞 VSCode+STM32CubeMx+C <2>調試+燒錄
GD32F407 是什么?
? ? ? ?GD32F407 是 兆易創新(GigaDevice) 出品的一款高性能、Cortex-M4F 內核的國產 MCU,很多方面與 STM32F407 十分接近,甚至寄存器定義、引腳排列都保持高度兼容。
它的核心特性包括:
-
Cortex-M4 @168MHz,支持 FPU、DSP
-
Flash:最多 1MB,SRAM:最多 192KB(我這個Flash512k,Ram192k)
-
豐富外設:ADC、DAC、CAN、USB OTG、ETH、FSMC、USART、SPI、I2C 等
-
多種封裝:LQFP100、LQFP144、BGA 等
-
支持 SWD/JTAG 在線調試
? ? ? ?兆易推出 GD32 系列,就是想打破 STM32 在中高端 MCU 的壟斷,性價比很高,受到不少國產項目的青睞。許多資料表示是可以完全平替的,但是經試用,還是有一些門檻的,尤其是在遷移上。
程序是如何啟動的?
? ? ? ?我們以“點亮一個 LED 燈”為例,要讓一個空白的 GD32F407 板子成功運行 main() 函數,中間需要經歷一系列復雜的初始化:
涉及的關鍵文件:
文件 | 作用 |
---|---|
startup_gd32f407xx.s | 啟動匯編文件,設置棧、跳轉到 main() |
system_gd32f4xx.c | 初始化系統時鐘、PLL 等 |
gd32f4xx.h | 寄存器定義頭文件 |
.ld 文件 | GCC 鏈接腳本,決定各段如何映射到內存 |
這些文件具體做了什么?
1. 啟動文件?.s(startup_gd32f407xx.s)
啟動匯編是程序真正的起點。其主要工作包括:
-
設置 MSP(主棧指針)初始值
-
定義中斷向量表(.isr_vector 段)
-
運行 C 程序前的初始化(拷貝 .data 段、清零 .bss 段)
-
調用 SystemInit() 初始化系統時鐘
-
最后跳轉到 main()
注意:官方只提供了Keil版,一般例程都是Keil版的,是沒有.s和.ld文件的,github上的例程大多是帶兩種版本的:
- ARMCC/Keil 版(語法更偏匯編,.asm)
- GCC 版(.s,符合 GNU 匯編語法)
- 如果你用的是 GCC,需要選對文件,否則編譯會報錯。
2.?system_gd32f4xx.c
這是一個用 C 語言寫的底層初始化文件,主要負責:
-
啟用外部晶振 HSE
-
配置 PLL、AHB/APB 分頻
-
設置 FLASH 加速參數
-
更新全局變量 SystemCoreClock
? ? ? SystemInit() 是由啟動文件在最開始調用的,它決定了你的程序到底是跑在 16MHz(HSI)還是 168MHz(PLL)上,如下圖,我選擇的是168Mhz和8M晶振
3.?gd32f4xx.h
這個頭文件包含了所有外設的寄存器定義和映射,宏非常多,比如:
#define GPIOA_BASE (0x40020000UL)
#define GPIOA ((gpio_reg_struct *) GPIOA_BASE)
你能像下面這樣控制 GPIO 燈,就是因為這些定義:
GPIOA->ODCTL |= GPIO_PIN_0;
也就是說,這個文件相當于裸機程序的“控制面板”。注意這里也有個配晶振的地方。
4.?.ld鏈接腳本文件(GCC 專屬)
.ld 是 GCC 編譯時才需要的文件,決定了:
-
哪些代碼段放在 Flash,哪些放在 RAM
-
main() 的入口在哪(通常由 .isr_vector 決定)
-
棧、堆、全局變量的布局是否合理
-
.data 是否正確從 Flash 拷貝到 RAM
MEMORY {FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024KRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}
沒有正確的 .ld 文件,哪怕你 main() 寫得再好,程序也跑不起來。
Keil 用戶為何“感覺不到”這些文件?
GD32 官方對 Keil 的支持非常完善,可以說是“官方首選工具鏈”:
-
提供完整的 Keil 工程模板
-
不需要 .ld 文件,Keil 使用內部 scatter 文件自動配置
-
啟動文件、系統文件全都配置好,一鍵編譯運行
-
集成調試、仿真、燒錄工具鏈非常成熟
也正因為如此,很多初學者用 Keil 上手時,往往不需要關注 .s 和 .ld 這些底層配置文件。
這也導致了一種錯覺:“只要寫代碼就能跑”,一旦換到 GCC 環境就懵了。
VS Code + GCC?
如果你像我一樣用的是:
-
VS Code + GCC + CMake 或 Makefile
-
OpenOCD 進行燒錄調試
那么你必須親自處理:
任務 | 所需文件 |
---|---|
指定入口地址 | .ld 腳本 |
啟動中斷向量表 | 啟動匯編 .s |
系統時鐘配置 | system_gd32f4xx.c |
外設控制宏定義 | gd32f4xx.h |
這是一條“裸機開發 + 自定義構建系統”的路線,更接近真實嵌入式底層工程師的工作方式。
RT-Thread 軟件包的角色
很多 GD32 工程也會用到 RT-Thread 軟件包。它的作用:
-
提供輕量級的實時操作系統內核(調度器、線程、定時器、信號量等)
-
統一驅動框架(設備樹、HAL 層)
-
配合 BSP 提供板級初始化、外設驅動
在裸機開發中,也常常只用它的 BSP 初始化和驅動部分,比如:
rt_hw_board_init(); // 初始化引腳、時鐘、串口等
? ? ? ?你可以只用它的初始化和驅動部分,不一定用內核調度。我也下載安裝了,本以為會向資料表示的可以像STM32CubeMx那樣生成代碼,再和VSCode聯動,沒想到連BSP都沒下載成功,就放棄了。
總結
工具鏈 | 是否需要關注 .ld / .s |
---|---|
Keil / MDK | 否,自動配置,官方模板支持 |
VS Code + GCC | 是,必須手動配置 |
理解 .ld 和 .s 是裸機開發的必經之路。
如果你:
-
用 GCC 編譯工具鏈
-
用 OpenOCD 燒錄
那么早點掌握這些啟動流程、鏈接布局、外設定義,絕對會讓你少踩很多坑。
附1:VSCode EIED配置圖
附2:.s、.ld代碼
/** linker script for GD32F4xx with GNU ld* BruceOu 2021-12-14*//* Program Entry, set to mark it as "used" and avoid gc */
MEMORY
{CODE (rx) : ORIGIN = 0x08000000, LENGTH = 512k /* 512KB flash */DATA (rw) : ORIGIN = 0x20000000, LENGTH = 128k /* 128KB sram ,0x1000 0000 - 0x1000 FFFF TCMSRAM(64KB)*/
}
ENTRY(Reset_Handler)
_system_stack_size = 0x200;SECTIONS
{.text :{. = ALIGN(4);_stext = .;KEEP(*(.isr_vector)) /* Startup code */. = ALIGN(4);*(.text) /* remaining code */*(.text.*) /* remaining code */*(.rodata) /* read-only data (constants) */*(.rodata*)*(.glue_7)*(.glue_7t)*(.gnu.linkonce.t*)/* section information for finsh shell */. = ALIGN(4);__fsymtab_start = .;KEEP(*(FSymTab))__fsymtab_end = .;. = ALIGN(4);__vsymtab_start = .;KEEP(*(VSymTab))__vsymtab_end = .;. = ALIGN(4);/* section information for initial. */. = ALIGN(4);__rt_init_start = .;KEEP(*(SORT(.rti_fn*)))__rt_init_end = .;. = ALIGN(4);. = ALIGN(4);_etext = .;} > CODE = 0/* .ARM.exidx is sorted, so has to go in its own output section. */__exidx_start = .;.ARM.exidx :{*(.ARM.exidx* .gnu.linkonce.armexidx.*)/* This is used by the startup in order to initialize the .data secion */_sidata = .;} > CODE__exidx_end = .;/* .data section which is used for initialized data */.data : AT (_sidata){. = ALIGN(4);/* This is used by the startup in order to initialize the .data secion */_sdata = . ;*(.data)*(.data.*)*(.gnu.linkonce.d*). = ALIGN(4);/* This is used by the startup in order to initialize the .data secion */_edata = . ;} >DATA.stack : {. = . + _system_stack_size;. = ALIGN(4);_estack = .;} >DATA__bss_start = .;.bss :{. = ALIGN(4);/* This is used by the startup in order to initialize the .bss secion */_sbss = .;*(.bss)*(.bss.*)*(COMMON). = ALIGN(4);/* This is used by the startup in order to initialize the .bss secion */_ebss = . ;*(.bss.init)} > DATA__bss_end = .;_end = .;/* Stabs debugging sections. */.stab 0 : { *(.stab) }.stabstr 0 : { *(.stabstr) }.stab.excl 0 : { *(.stab.excl) }.stab.exclstr 0 : { *(.stab.exclstr) }.stab.index 0 : { *(.stab.index) }.stab.indexstr 0 : { *(.stab.indexstr) }.comment 0 : { *(.comment) }/* DWARF debug sections.* Symbols in the DWARF debugging sections are relative to the beginning* of the section so we begin them at 0. *//* DWARF 1 */.debug 0 : { *(.debug) }.line 0 : { *(.line) }/* GNU DWARF 1 extensions */.debug_srcinfo 0 : { *(.debug_srcinfo) }.debug_sfnames 0 : { *(.debug_sfnames) }/* DWARF 1.1 and DWARF 2 */.debug_aranges 0 : { *(.debug_aranges) }.debug_pubnames 0 : { *(.debug_pubnames) }/* DWARF 2 */.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }.debug_abbrev 0 : { *(.debug_abbrev) }.debug_line 0 : { *(.debug_line) }.debug_frame 0 : { *(.debug_frame) }.debug_str 0 : { *(.debug_str) }.debug_loc 0 : { *(.debug_loc) }.debug_macinfo 0 : { *(.debug_macinfo) }/* SGI/MIPS DWARF 2 extensions */.debug_weaknames 0 : { *(.debug_weaknames) }.debug_funcnames 0 : { *(.debug_funcnames) }.debug_typenames 0 : { *(.debug_typenames) }.debug_varnames 0 : { *(.debug_varnames) }
}
.syntax unified.cpu cortex-m4.fpu softvfp.thumb.global g_pfnVectors
.global Default_Handler/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss.section .text.Reset_Handler.weak Reset_Handler.type Reset_Handler, %function
Reset_Handler: /* Copy the data segment initializers from flash to SRAM */ movs r1, #0b LoopCopyDataInitCopyDataInit:ldr r3, =_sidataldr r3, [r3, r1]str r3, [r0, r1]adds r1, r1, #4LoopCopyDataInit:ldr r0, =_sdataldr r3, =_edataadds r2, r0, r1cmp r2, r3bcc CopyDataInitldr r2, =_sbssb LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:movs r3, #0str r3, [r2]adds r2, r2, #4LoopFillZerobss:ldr r3, = _ebsscmp r2, r3bcc FillZerobss/* Call the clock system initialization function.*/bl SystemInit
/* Call into static constructors (C++) */bl __libc_init_array
/* Call the application's entry point.*/bl mainbx lr
.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 minimal vector table for a Cortex M4. 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_pfnVectorsg_pfnVectors:.word _estack /* Top of Stack */.word Reset_Handler /* Reset Handler */.word NMI_Handler /* NMI Handler */.word HardFault_Handler /* Hard Fault Handler */.word MemManage_Handler /* MPU Fault Handler */.word BusFault_Handler /* Bus Fault Handler */.word UsageFault_Handler /* Usage Fault Handler */.word 0 /* Reserved */.word 0 /* Reserved */.word 0 /* Reserved */.word 0 /* Reserved */.word SVC_Handler /* SVCall Handler */.word DebugMon_Handler /* Debug Monitor Handler */.word 0 /* Reserved */.word PendSV_Handler /* PendSV Handler */.word SysTick_Handler /* SysTick Handler */.word WWDGT_IRQHandler /* 16:Window Watchdog Timer */.word LVD_IRQHandler /* 17:LVD through EXTI Line detect */.word TAMPER_STAMP_IRQHandler /* 18:Tamper and TimeStamp through EXTI Line detect */.word RTC_WKUP_IRQHandler /* 19:RTC Wakeup through EXTI Line */.word FMC_IRQHandler /* 20:FMC */.word RCU_CTC_IRQHandler /* 21:RCU and CTC */.word EXTI0_IRQHandler /* 22:EXTI Line 0 */.word EXTI1_IRQHandler /* 23:EXTI Line 1 */.word EXTI2_IRQHandler /* 24:EXTI Line 2 */.word EXTI3_IRQHandler /* 25:EXTI Line 3 */.word EXTI4_IRQHandler /* 26:EXTI Line 4 */.word DMA0_Channel0_IRQHandler /* 27:DMA0 Channel0 */.word DMA0_Channel1_IRQHandler /* 28:DMA0 Channel1 */.word DMA0_Channel2_IRQHandler /* 29:DMA0 Channel2 */.word DMA0_Channel3_IRQHandler /* 30:DMA0 Channel3 */.word DMA0_Channel4_IRQHandler /* 31:DMA0 Channel4 */.word DMA0_Channel5_IRQHandler /* 32:DMA0 Channel5 */.word DMA0_Channel6_IRQHandler /* 33:DMA0 Channel6 */.word ADC_IRQHandler /* 34:ADC */.word CAN0_TX_IRQHandler /* 35:CAN0 TX */.word CAN0_RX0_IRQHandler /* 36:CAN0 RX0 */.word CAN0_RX1_IRQHandler /* 37:CAN0 RX1 */.word CAN0_EWMC_IRQHandler /* 38:CAN0 EWMC */.word EXTI5_9_IRQHandler /* 39:EXTI5 to EXTI9 */.word TIMER0_BRK_TIMER8_IRQHandler /* 40:TIMER0 Break and TIMER8 */.word TIMER0_UP_TIMER9_IRQHandler /* 41:TIMER0 Update and TIMER9 */.word TIMER0_TRG_CMT_TIMER10_IRQHandler /* 42:TIMER0 Trigger and Commutation and TIMER10 */.word TIMER0_Channel_IRQHandler /* 43:TIMER0 Channel Capture Compare */.word TIMER1_IRQHandler /* 44:TIMER1 */.word TIMER2_IRQHandler /* 45:TIMER2 */.word TIMER3_IRQHandler /* 46:TIMER3 */.word I2C0_EV_IRQHandler /* 47:I2C0 Event */.word I2C0_ER_IRQHandler /* 48:I2C0 Error */.word I2C1_EV_IRQHandler /* 49:I2C1 Event */.word I2C1_ER_IRQHandler /* 50:I2C1 Error */.word SPI0_IRQHandler /* 51:SPI0 */.word SPI1_IRQHandler /* 52:SPI1 */.word USART0_IRQHandler /* 53:USART0 */.word USART1_IRQHandler /* 54:USART1 */.word USART2_IRQHandler /* 55:USART2 */.word EXTI10_15_IRQHandler /* 56:EXTI10 to EXTI15 */.word RTC_Alarm_IRQHandler /* 57:RTC Alarm */.word USBFS_WKUP_IRQHandler /* 58:USBFS Wakeup */.word TIMER7_BRK_TIMER11_IRQHandler /* 59:TIMER7 Break and TIMER11 */.word TIMER7_UP_TIMER12_IRQHandler /* 60:TIMER7 Update and TIMER12 */.word TIMER7_TRG_CMT_TIMER13_IRQHandler /* 61:TIMER7 Trigger and Commutation and TIMER13 */.word TIMER7_Channel_IRQHandler /* 62:TIMER7 Capture Compare */.word DMA0_Channel7_IRQHandler /* 63:DMA0 Channel7 */.word EXMC_IRQHandler /* 64:EXMC */.word SDIO_IRQHandler /* 65:SDIO */.word TIMER4_IRQHandler /* 66:TIMER4 */.word SPI2_IRQHandler /* 67:SPI2 */.word UART3_IRQHandler /* 68:UART3 */.word UART4_IRQHandler /* 69:UART4 */.word TIMER5_DAC_IRQHandler /* 70:TIMER5 and DAC0 DAC1 Underrun error */.word TIMER6_IRQHandler /* 71:TIMER6 */.word DMA1_Channel0_IRQHandler /* 72:DMA1 Channel0 */.word DMA1_Channel1_IRQHandler /* 73:DMA1 Channel1 */.word DMA1_Channel2_IRQHandler /* 74:DMA1 Channel2 */.word DMA1_Channel3_IRQHandler /* 75:DMA1 Channel3 */.word DMA1_Channel4_IRQHandler /* 76:DMA1 Channel4 */.word ENET_IRQHandler /* 77:Ethernet */.word ENET_WKUP_IRQHandler /* 78:Ethernet Wakeup through EXTI Line */.word CAN1_TX_IRQHandler /* 79:CAN1 TX */.word CAN1_RX0_IRQHandler /* 80:CAN1 RX0 */.word CAN1_RX1_IRQHandler /* 81:CAN1 RX1 */.word CAN1_EWMC_IRQHandler /* 82:CAN1 EWMC */.word USBFS_IRQHandler /* 83:USBFS */.word DMA1_Channel5_IRQHandler /* 84:DMA1 Channel5 */.word DMA1_Channel6_IRQHandler /* 85:DMA1 Channel6 */.word DMA1_Channel7_IRQHandler /* 86:DMA1 Channel7 */.word USART5_IRQHandler /* 87:USART5 */.word I2C2_EV_IRQHandler /* 88:I2C2 Event */.word I2C2_ER_IRQHandler /* 89:I2C2 Error */.word USBHS_EP1_Out_IRQHandler /* 90:USBHS Endpoint 1 Out */.word USBHS_EP1_In_IRQHandler /* 91:USBHS Endpoint 1 in */.word USBHS_WKUP_IRQHandler /* 92:USBHS Wakeup through EXTI Line */.word USBHS_IRQHandler /* 93:USBHS */.word DCI_IRQHandler /* 94:DCI */.word 0 /* 95:Reserved */.word TRNG_IRQHandler /* 96:TRNG */.word FPU_IRQHandler /* 97:FPU *//*******************************************************************************
*
* 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 MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler.weak DebugMon_Handler
.thumb_set DebugMon_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 DMA0_Channel0_IRQHandler
.thumb_set DMA0_Channel0_IRQHandler,Default_Handler.weak DMA0_Channel1_IRQHandler
.thumb_set DMA0_Channel1_IRQHandler,Default_Handler.weak DMA0_Channel2_IRQHandler
.thumb_set DMA0_Channel2_IRQHandler,Default_Handler.weak DMA0_Channel3_IRQHandler
.thumb_set DMA0_Channel3_IRQHandler,Default_Handler.weak DMA0_Channel4_IRQHandler
.thumb_set DMA0_Channel4_IRQHandler,Default_Handler.weak DMA0_Channel5_IRQHandler
.thumb_set DMA0_Channel5_IRQHandler,Default_Handler.weak DMA0_Channel6_IRQHandler
.thumb_set DMA0_Channel6_IRQHandler,Default_Handler.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler.weak CAN0_TX_IRQHandler
.thumb_set CAN0_TX_IRQHandler,Default_Handler.weak CAN0_RX0_IRQHandler
.thumb_set CAN0_RX0_IRQHandler,Default_Handler.weak CAN0_RX1_IRQHandler
.thumb_set CAN0_RX1_IRQHandler,Default_Handler.weak CAN0_EWMC_IRQHandler
.thumb_set CAN0_EWMC_IRQHandler,Default_Handler.weak EXTI5_9_IRQHandler
.thumb_set EXTI5_9_IRQHandler,Default_Handler.weak TIMER0_BRK_TIMER8_IRQHandler
.thumb_set TIMER0_BRK_TIMER8_IRQHandler,Default_Handler.weak TIMER0_UP_TIMER9_IRQHandler
.thumb_set TIMER0_UP_TIMER9_IRQHandler,Default_Handler.weak TIMER0_TRG_CMT_TIMER10_IRQHandler
.thumb_set TIMER0_TRG_CMT_TIMER10_IRQHandler,Default_Handler.weak TIMER0_Channel_IRQHandler
.thumb_set TIMER0_Channel_IRQHandler,Default_Handler.weak TIMER1_IRQHandler
.thumb_set TIMER1_IRQHandler,Default_Handler.weak TIMER2_IRQHandler
.thumb_set TIMER2_IRQHandler,Default_Handler.weak TIMER3_IRQHandler
.thumb_set TIMER3_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 USART0_IRQHandler
.thumb_set USART0_IRQHandler,Default_Handler.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler.weak EXTI10_15_IRQHandler
.thumb_set EXTI10_15_IRQHandler,Default_Handler.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler.weak USBFS_WKUP_IRQHandler
.thumb_set USBFS_WKUP_IRQHandler,Default_Handler.weak TIMER7_BRK_TIMER11_IRQHandler
.thumb_set TIMER7_BRK_TIMER11_IRQHandler,Default_Handler.weak TIMER7_UP_TIMER12_IRQHandler
.thumb_set TIMER7_UP_TIMER12_IRQHandler,Default_Handler.weak TIMER7_TRG_CMT_TIMER13_IRQHandler
.thumb_set TIMER7_TRG_CMT_TIMER13_IRQHandler,Default_Handler.weak TIMER7_Channel_IRQHandler
.thumb_set TIMER7_Channel_IRQHandler,Default_Handler.weak DMA0_Channel7_IRQHandler
.thumb_set DMA0_Channel7_IRQHandler,Default_Handler.weak EXMC_IRQHandler
.thumb_set EXMC_IRQHandler,Default_Handler.weak SDIO_IRQHandler
.thumb_set SDIO_IRQHandler,Default_Handler.weak TIMER4_IRQHandler
.thumb_set TIMER4_IRQHandler,Default_Handler.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler.weak UART3_IRQHandler
.thumb_set UART3_IRQHandler,Default_Handler.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler.weak TIMER5_DAC_IRQHandler
.thumb_set TIMER5_DAC_IRQHandler,Default_Handler.weak TIMER6_IRQHandler
.thumb_set TIMER6_IRQHandler,Default_Handler.weak DMA1_Channel0_IRQHandler
.thumb_set DMA1_Channel0_IRQHandler,Default_Handler.weak DMA1_Channel1_IRQHandler
.thumb_set DMA1_Channel1_IRQHandler,Default_Handler.weak DMA1_Channel2_IRQHandler
.thumb_set DMA1_Channel2_IRQHandler,Default_Handler.weak DMA1_Channel3_IRQHandler
.thumb_set DMA1_Channel3_IRQHandler,Default_Handler.weak DMA1_Channel4_IRQHandler
.thumb_set DMA1_Channel4_IRQHandler,Default_Handler.weak ENET_IRQHandler
.thumb_set ENET_IRQHandler,Default_Handler.weak ENET_WKUP_IRQHandler
.thumb_set ENET_WKUP_IRQHandler,Default_Handler.weak CAN1_TX_IRQHandler
.thumb_set CAN1_TX_IRQHandler,Default_Handler.weak CAN1_RX0_IRQHandler
.thumb_set CAN1_RX0_IRQHandler,Default_Handler.weak CAN1_RX1_IRQHandler
.thumb_set CAN1_RX1_IRQHandler,Default_Handler.weak CAN1_EWMC_IRQHandler
.thumb_set CAN1_EWMC_IRQHandler,Default_Handler.weak USBFS_IRQHandler
.thumb_set USBFS_IRQHandler,Default_Handler.weak DMA1_Channel5_IRQHandler
.thumb_set DMA1_Channel5_IRQHandler,Default_Handler.weak DMA1_Channel6_IRQHandler
.thumb_set DMA1_Channel6_IRQHandler,Default_Handler.weak DMA1_Channel7_IRQHandler
.thumb_set DMA1_Channel7_IRQHandler,Default_Handler.weak USART5_IRQHandler
.thumb_set USART5_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 USBHS_EP1_Out_IRQHandler
.thumb_set USBHS_EP1_Out_IRQHandler,Default_Handler.weak USBHS_EP1_In_IRQHandler
.thumb_set USBHS_EP1_In_IRQHandler,Default_Handler.weak USBHS_WKUP_IRQHandler
.thumb_set USBHS_WKUP_IRQHandler,Default_Handler.weak USBHS_IRQHandler
.thumb_set USBHS_IRQHandler,Default_Handler.weak DCI_IRQHandler
.thumb_set DCI_IRQHandler,Default_Handler.weak TRNG_IRQHandler
.thumb_set TRNG_IRQHandler,Default_Handler.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler