兆易创新 GD32 系列(一) 启动过程分析
起始和STM32的启动过程是一样的
EQU:给数字常量取一个符号名,相当于C语言中的define
AREA:指示汇编程序汇编新的代码或数据段。
SPACE:分配内存空间
PRESERVE8:当前文件堆栈需按照8字节对齐
EXPORT:声明一个标号具有全局属性,可被外部的文件使用
DCD:以字为单位分配内存,要求4字节对齐,并要求初始化这些内存
PROC:定义子程序,与ENDP成对使用,表示子程序结束
MSR:Move to Special register from Register. 恢复到特殊寄存器
WEAK:弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不出错。要注意的是:这个不是ARM的指令,是编译器的,这里放在一起只是为了方便。
IMPORT:声明标号来自外部文件,跟C语言中的EXTERN关键字类似
B:跳转到一个标号ALIGN编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示4字节对齐。要注意的是:这个不是ARM的指令,是编译器的,这里放在一起只是为了方便。
END:到达文件的末尾,文件结束
IF,ELSE,ENDIF:汇编条件分支语句,跟C语言的if else类似
Stack_Size EQU 0x00000400AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
EQU 类似C语言的define
Stack_Size EQU 0x800,表示Stack_Size 为0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
用AREA指令定义一个段,代码节或数据节。说明所定义段的相关属性。(说明段的名字,段的属性)
NOINIT 不初始化
READWRITE 可读写
ALIGN=3 按照8*2^3 =64字节对齐
Stack_Mem SPACE Stack_Size
Stack_Mem 分配内存空间大小为 0x00000400
__initial_sp 表示Stack_Mem 空间的结束地址。栈顶地址,栈是由高向低生长的
Heap_Size EQU 0x00000400AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
同理heap空间的申请也是一样的,__heap_base表示起始地址,__heap_limit表示结束地址
在编译后mmp文件中有记录内存地址
HEAP 0x20012e10 Section 1024 startup_gd32f450_470.o(HEAP)Heap_Mem 0x20012e10 Data 1024 startup_gd32f450_470.o(HEAP)STACK 0x20013210 Section 1024 startup_gd32f450_470.o(STACK)Stack_Mem 0x20013210 Data 1024 startup_gd32f450_470.o(STACK)__initial_sp 0x20013610 Data 0 startup_gd32f450_470.o(STACK)
0x20013210 - 0x20012e10 = 0x400
0x20013610 - 0x20013210 = 0x400
/* reset Vector Mapped to at Address 0 */AREA RESET, DATA, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size
一样的做法申请一块区域 RESET 数据段,只读。内存是可读可写的,所以只读指的是FLASH上的空间,原本指的是ROM。
EXPORT:声明一个标号具有全局属性,可被外部的文件使用
三个声明部分不占用空间
下面接着是 RESET 空间向量,按照顺序排列
DCD:以字为单位分配内存,要求4字节对齐,并要求初始化这些内存
AREA RESET, DATA, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size__Vectors DCD __initial_sp ; Top of StackDCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI HandlerDCD HardFault_Handler ; Hard Fault HandlerDCD MemManage_Handler ; MPU Fault HandlerDCD BusFault_Handler ; Bus Fault HandlerDCD UsageFault_Handler ; Usage Fault HandlerDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD SVC_Handler ; SVCall HandlerDCD DebugMon_Handler ; Debug Monitor HandlerDCD 0 ; ReservedDCD PendSV_Handler ; PendSV HandlerDCD SysTick_Handler ; SysTick Handler; /* external interrupts handler */DCD WWDGT_IRQHandler ; 16:Window Watchdog TimerDCD LVD_IRQHandler ; 17:LVD through EXTI Line detectDCD TAMPER_STAMP_IRQHandler ; 18:Tamper and TimeStamp through EXTI Line detectDCD RTC_WKUP_IRQHandler ; 19:RTC Wakeup through EXTI LineDCD FMC_IRQHandler ; 20:FMCDCD RCU_CTC_IRQHandler ; 21:RCU and CTCDCD EXTI0_IRQHandler ; 22:EXTI Line 0
DCD __initial_sp ; Top of Stack 排在第一位
DCD Reset_Handler ; Reset Handler 排在第二位
一次排列成一张表
__initial_sp ,Reset_Handler 这些标号都是地址。
__Vectors 开头 以__Vectors_End 结尾
__Vectors_Size EQU __Vectors_End - __Vectors
接着是 申请一块空间
AREA |.text|, CODE, READONLY;/* reset Handler */
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT SystemInitIMPORT __mainLDR R0, =SystemInitBLX R0LDR R0, =__mainBX R0ENDP
PROC:定义子程序,与ENDP成对使用,表示子程序结束
同样是定义了只读FLASH空间,标号为Reset_Handler ,并且可以被外部引用
IMPORT:声明标号来自外部文件,跟C语言中的EXTERN关键字类似
然后依次执行 外部函数 SystemInit,__main(由MDK环境自动生成)
SystemInit 一般做时钟配置
__main 一般是配置C语言运行环境,堆栈的初始化
;/* dummy Exception Handlers */
NMI_Handler PROCEXPORT NMI_Handler [WEAK]B .ENDP
HardFault_Handler\PROCEXPORT HardFault_Handler [WEAK]B .ENDP
MemManage_Handler\PROCEXPORT MemManage_Handler [WEAK]B .ENDP
BusFault_Handler\PROCEXPORT BusFault_Handler [WEAK]B .ENDP
UsageFault_Handler\
上面的意思是定义Vectors对应处理函数地址。[WEAK]表示如果外部有定义则优先链接外部的函数。
B .是循环的意思,如果没有定义就会无限循环。
可以看到在Default_Handler PROC 之前都是会无限循环的,也就是说如果没写对应的函数就会卡在循环中。
;/* reset Handler */
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT SystemInitIMPORT __mainLDR R0, =SystemInitBLX R0LDR R0, =__mainBX R0ENDP;/* dummy Exception Handlers */
NMI_Handler PROCEXPORT NMI_Handler [WEAK]B .ENDP
HardFault_Handler\PROCEXPORT HardFault_Handler [WEAK]B .ENDP
MemManage_Handler\PROCEXPORT MemManage_Handler [WEAK]B .ENDP
BusFault_Handler\PROCEXPORT BusFault_Handler [WEAK]B .ENDP
UsageFault_Handler\PROCEXPORT UsageFault_Handler [WEAK]B .ENDP
SVC_Handler PROCEXPORT SVC_Handler [WEAK]B .ENDP
DebugMon_Handler\PROCEXPORT DebugMon_Handler [WEAK]B .ENDP
PendSV_Handler\PROCEXPORT PendSV_Handler [WEAK]B .ENDP
SysTick_Handler\PROCEXPORT SysTick_Handler [WEAK]B .ENDPDefault_Handler PROC
; /* external interrupts handler */EXPORT WWDGT_IRQHandler [WEAK]EXPORT LVD_IRQHandler [WEAK] EXPORT TAMPER_STAMP_IRQHandler [WEAK] EXPORT RTC_WKUP_IRQHandler [WEAK] EXPORT FMC_IRQHandler [WEAK] EXPORT RCU_CTC_IRQHandler [WEAK] EXPORT EXTI0_IRQHandler [WEAK] EXPORT EXTI1_IRQHandler [WEAK] EXPORT EXTI2_IRQHandler [WEAK] EXPORT EXTI3_IRQHandler [WEAK] EXPORT EXTI4_IRQHandler [WEAK] EXPORT DMA0_Channel0_IRQHandler [WEAK] EXPORT DMA0_Channel1_IRQHandler [WEAK] EXPORT DMA0_Channel2_IRQHandler [WEAK] EXPORT DMA0_Channel3_IRQHandler [WEAK] EXPORT DMA0_Channel4_IRQHandler [WEAK] EXPORT DMA0_Channel5_IRQHandler [WEAK] EXPORT DMA0_Channel6_IRQHandler [WEAK] EXPORT ADC_IRQHandler [WEAK] EXPORT CAN0_TX_IRQHandler [WEAK] EXPORT CAN0_RX0_IRQHandler [WEAK] EXPORT CAN0_RX1_IRQHandler [WEAK] EXPORT CAN0_EWMC_IRQHandler [WEAK] EXPORT EXTI5_9_IRQHandler [WEAK] EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK]EXPORT TIMER0_Channel_IRQHandler [WEAK] EXPORT TIMER1_IRQHandler [WEAK] EXPORT TIMER2_IRQHandler [WEAK] EXPORT TIMER3_IRQHandler [WEAK] EXPORT I2C0_EV_IRQHandler [WEAK] EXPORT I2C0_ER_IRQHandler [WEAK] EXPORT I2C1_EV_IRQHandler [WEAK] EXPORT I2C1_ER_IRQHandler [WEAK] EXPORT SPI0_IRQHandler [WEAK] EXPORT SPI1_IRQHandler [WEAK] EXPORT USART0_IRQHandler [WEAK] EXPORT USART1_IRQHandler [WEAK] EXPORT USART2_IRQHandler [WEAK] EXPORT EXTI10_15_IRQHandler [WEAK] EXPORT RTC_Alarm_IRQHandler [WEAK] EXPORT USBFS_WKUP_IRQHandler [WEAK] EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK]EXPORT TIMER7_Channel_IRQHandler [WEAK] EXPORT DMA0_Channel7_IRQHandler [WEAK] EXPORT EXMC_IRQHandler [WEAK] EXPORT SDIO_IRQHandler [WEAK] EXPORT TIMER4_IRQHandler [WEAK] EXPORT SPI2_IRQHandler [WEAK] EXPORT UART3_IRQHandler [WEAK] EXPORT UART4_IRQHandler [WEAK] EXPORT TIMER5_DAC_IRQHandler [WEAK] EXPORT TIMER6_IRQHandler [WEAK] EXPORT DMA1_Channel0_IRQHandler [WEAK] EXPORT DMA1_Channel1_IRQHandler [WEAK] EXPORT DMA1_Channel2_IRQHandler [WEAK] EXPORT DMA1_Channel3_IRQHandler [WEAK] EXPORT DMA1_Channel4_IRQHandler [WEAK] EXPORT ENET_IRQHandler [WEAK] EXPORT ENET_WKUP_IRQHandler [WEAK] EXPORT CAN1_TX_IRQHandler [WEAK] EXPORT CAN1_RX0_IRQHandler [WEAK] EXPORT CAN1_RX1_IRQHandler [WEAK] EXPORT CAN1_EWMC_IRQHandler [WEAK] EXPORT USBFS_IRQHandler [WEAK] EXPORT DMA1_Channel5_IRQHandler [WEAK] EXPORT DMA1_Channel6_IRQHandler [WEAK] EXPORT DMA1_Channel7_IRQHandler [WEAK] EXPORT USART5_IRQHandler [WEAK] EXPORT I2C2_EV_IRQHandler [WEAK] EXPORT I2C2_ER_IRQHandler [WEAK] EXPORT USBHS_EP1_Out_IRQHandler [WEAK] EXPORT USBHS_EP1_In_IRQHandler [WEAK] EXPORT USBHS_WKUP_IRQHandler [WEAK] EXPORT USBHS_IRQHandler [WEAK] EXPORT DCI_IRQHandler [WEAK] EXPORT TRNG_IRQHandler [WEAK] EXPORT FPU_IRQHandler [WEAK] EXPORT UART6_IRQHandler [WEAK] EXPORT UART7_IRQHandler [WEAK] EXPORT SPI3_IRQHandler [WEAK] EXPORT SPI4_IRQHandler [WEAK] EXPORT SPI5_IRQHandler [WEAK] EXPORT TLI_IRQHandler [WEAK] EXPORT TLI_ER_IRQHandler [WEAK] EXPORT IPA_IRQHandler [WEAK]
最后初始化堆栈
IF :DEF:__MICROLIBEXPORT __initial_spEXPORT __heap_baseEXPORT __heap_limitELSEIMPORT __use_two_region_memoryEXPORT __user_initial_stackheap__user_initial_stackheap PROCLDR R0, = Heap_MemLDR R1, =(Stack_Mem + Stack_Size)LDR R2, = (Heap_Mem + Heap_Size)LDR R3, = Stack_MemBX LRENDPALIGNENDIFEND
GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c
一下是GD32标准库中包含的SystemInit函数
void SystemInit (void)
{/* FPU settings */
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif/* Reset the RCU clock configuration to the default reset state *//* Set IRC16MEN bit */RCU_CTL |= RCU_CTL_IRC16MEN;while(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){}RCU_MODIFY(0x50);RCU_CFG0 &= ~RCU_CFG0_SCS;/* Reset HXTALEN, CKMEN and PLLEN bits */RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);/* Reset HSEBYP bit */RCU_CTL &= ~(RCU_CTL_HXTALBPS);/* Reset CFG0 register */RCU_CFG0 = 0x00000000U;/* wait until IRC16M is selected as system clock */while(0 != (RCU_CFG0 & RCU_SCSS_IRC16M)){}/* Reset PLLCFGR register */RCU_PLL = 0x24003010U;/* Disable all interrupts */RCU_INT = 0x00000000U;/* Configure the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings */system_clock_config();
}
执行外SystemInit 后跳转到__main(),然后跳转到用户执行的主函数中。
兆易创新 GD32 系列(一) 启动过程分析相关推荐
- 兆易创新GD32 (四)FreeRTOS 移植 与 CMSIS OS2
可以完全参考STM32系列的方法 FreeRTOS 逛网下载 FreeRTOS源码 https://www.freertos.org/a00104.html GitHub地址 https://gith ...
- 「免费申请」基于Arm Cortex-M4的兆易创新GD32F427高性能开发板试用活动
申请链接:「免费申请」基于Arm Cortex-M4的兆易创新GD32F427高性能开发板试用活动 基于Arm® Cortex®-M4的兆易创新GD32F427开发板免费试用活动 近期兆易创新发布了全 ...
- STM32CUBEIDE(15)----移植兆易创新SPI Nor Flash之GD25Q64Flash
spi概述 SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的 ...
- STM32CUBEMX开发GD32F303(16)----移植兆易创新SPI Nor Flash之GD25Q64Flash
spi概述 SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的 ...
- GD32F303固件库开发(16)----移植兆易创新SPI Nor Flash之GD25Q64Flash
spi概述 SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的 ...
- 芯片|兆易创新逾7300万股限售股下周一上市流通 占总股本23%
[TechWeb]8月13日消息,上交所上市公司.芯片设计公司兆易创新昨晚发布公告称,逾7300万股限售股下周一上市流通,占总股本23%. 本次限售股上市类型 经中国证券监督管理委员会证监许可[201 ...
- 瑞萨e2studio(22)----移植兆易创新SPI Nor Flash之GD25Q64Flash
瑞萨e2studio.22--移植兆易创新SPI Nor Flash之GD25Q64Flash spi概述 视频教学 csdn课程 样品申请 完整代码下载 硬件准备 新建工程 工程模板 保存工程路径 ...
- GD32F405RGT6单片机芯片GigaDevice兆易创新ARM Cortex-M4微控制器
描述 GD32F405系列互联型产品采用全新工艺制程设计,整合了强大的运算效能和丰富的外设接口.处理器主频可达168MHz,并提供了完整的DSP指令集,并行计算能力和专用浮点运算单元(FPU). GD ...
- 【GD32】从0开始学GD32单片机栏目目录 | 兆易创新32位微处理器
目录 前言 为什么写这个教程 GD32与STM32的区别 教程 入门教程(基于GD32F103C8T6单片机) 进阶教程 高级教程 前言 为什么写这个教程 作为一名物联网专业的在读大学生,与单片机打交 ...
最新文章
- 如何利用遗传算法进行自变量降维
- 扑克牌图片一张一张_Python 制作一副扑克牌,有趣的案例
- Python你必须知道的十个库
- matlab拟合未定义函数或变量,关于matlab的未定义函数或变量的问题
- 浅析如何让企业网站实现精准营销?
- C语言函数到.h文件,求助C语言大佬 , 只会写到一个.c文件里 ,不会用.h头文件...
- 没有眼睛的街头卖艺人
- 进程间通信之管道通信
- Linux内核品读 /基础组件/ 模块机制快速入门
- 收藏 | Python数据分析必备速查表
- SQL Server中的报表–如何使用数据透视表和日期计算来获取有价值的报表
- 用过http api 发送邮件
- html文件能放病毒吗,建立一个防病毒/防复制/任何程序都无法删除的文件或文件夹...
- 3ds max制作宋惠乔的教程----作者: 火星时代 来源: 火星时代
- STM32 低功耗STOP模式,RTC唤醒
- 如何在PPT中制作动态图表,学会这种方法实在太简单
- 实时渲染入门:静态光照和动态光照
- 基于mindwave脑电波进行疲劳检测算法的设计(3)
- 微信多订单合并付款_拼多多只能微信支付吗?拼多多合并支付有什么优势?
- EAS7.5服务器文件夹备份,ORACLE+EAS数据备份与恢复参考