[研电赛技术支持] 【GD32】启动过程-程序计数器(PC)

[复制链接]
216|0
磨砂 发表于 2025-11-7 13:11 | 显示全部楼层 |阅读模式
GD32启动文件中的Reset_Handler是芯片上电或复位后执行的第一个C语言环境初始化程序,其核心作用是为运行main函数做好准备。下面我们通过一个表格来概览其主要步骤,然后深入解析关键的汇编实现细节。

33849690d575472697.png

关键汇编指令详解
在典型的GD32启动文件(如startup_gd32f30x.s或类似)中,Reset_Handler的汇编实现通常如下所示(不同型号或固件库版本可能略有差异):

Reset_Handler   PROC                 ; 开始一个子程序
                EXPORT  Reset_Handler [WEAK]  ; 声明为全局符号,[WEAK]允许被用户自定义同名函数覆盖
                IMPORT  SystemInit             ; 声明外部符号SystemInit,告知链接器该符号在外部定义
                IMPORT  __main                 ; 声明外部符号__main
                LDR     R0, =SystemInit        ; 将SystemInit函数的地址加载到寄存器R0
                BLX     R0                     ; 跳转到R0指定的地址(执行SystemInit),并保存返回地址
                LDR     R0, =__main            ; 将__main的地址加载到寄存器R0
                BX      R0                     ; 跳转到R0指定的地址(执行__main),不返回
                ENDP                           ; 结束子程序


这段代码中关键的汇编指令含义如下:

PROC/ENDP:用于定义子程序的开始和结束。
EXPORT [WEAK]:将Reset_Handler导出为全局符号,[WEAK]弱定义意味着如果用户在别处定义了同名的Reset_Handler函数,链接器将优先使用用户定义的版本。
IMPORT:通知汇编器SystemInit和__main是在其他文件中定义的符号,需要在链接时解析。
LDR R0, =label:一个伪指令,将标签label的地址加载到寄存器R0中。
BLX R0:带链接(返回地址存入LR寄存器)且切换指令集的跳转。跳转到R0中的地址执行SystemInit函数,执行完毕后会返回到下一条指令。
BX R0:跳转到R0中的地址执行__main,不再返回。因为__main会最终调用用户的main函数,而整个嵌入式应用程序在main函数中通常是一个无限循环,不会退出。

核心操作解析
系统初始化 (SystemInit):这是一个非常重要的C语言函数,通常由芯片厂商提供。它负责配置GD32的时钟系统,例如使能内部或外部高速时钟(HSI/HSE)、配置锁相环(PLL)以提升系统时钟频率,以及设置AHB、APB总线分频器等。这是确保芯片能以正确且期望的速度运行的关键一步。
C环境初始化 (__main):__main是由C库提供的入口点,它并非用户的main函数。它的工作包括:
数据段 (.data) 初始化:将已初始化全局变量和静态变量的初始值从Flash存储器(只读)复制到RAM中(可读写)的对应位置。
BSS段 (.bss) 清零:将未初始化的全局变量和静态变量所在的内存区域清零。
完成这些初始化后,最终调用用户的main()函数。

总结
Reset_Handler的汇编实现虽然简洁,但它通过调用SystemInit和__main,精准地完成了从硬件复位到C语言应用程序执行所必需的系统时钟配置和运行时环境搭建。理解这个过程对于深入掌握GD32(以及类似ARM Cortex-M内核MCU)的启动机制和进行底层开发至关重要。
————————————————
版权声明:本文为CSDN博主「蜀黍@猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_58087444/article/details/152944938

您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

4415

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部