STM32启动文件初探之startup_stm32f10x_hd.s(Reset_Handler函数)

本文详细解析了STM32微控制器的启动过程,包括设置初始寄存器值、初始化系统时钟至72MHz、调用SystemInit函数以及跳转至C程序入口等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该文件主要实现目的:

  • 设置初始SP
  • 设置初始PC=Reset_Handler
  • 设置向量表入口地址,并初始化向量表
  • 调用SystemInit,把系统时钟配制成72M,SystemInit在库文件system_stm32f10.c定义
  • 调转到标号_main,最终来到C程序文件
; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                ENDP

第一行是程序注释,在汇编里面注释用的是“;”。

第二行是定义了一个子程序:Reset_Handler。

PROC 是子程序定义伪指令。一般用法为:
1 子程序名PROC NEAR ( 或FAR )
2 ……
3 ret
4子程序名ENDP
其中NEAR 和FAR 是属性词。 NEAR属性(段内近调用):
调用程序和子程序在同一代码段中,只能被相同代码段的其他程序调用。
FAR属性(段间远调用):调用程序和子程序不在同一代码段中,可以被相同或不同代码段的程序调用。

第三行EXPORT 表示Reset_Handler 这个子程序可供其他模块调用。

关键字[WEAK]
表示弱定义,如果编译器发现在别处定义了同名的函数,则在链接时用别处的地址进行链接,如果其它地方没有定义,编译器也不报错,以此处地址进行链接。

第四行和第五行IMPORT 说明SystemInit 和__main 这两个标号在其他文件,在链接的时候需要到其他文件去寻找。

SystemInit在库文件system_stm32f10x.c 实现,用来初始化STM32的一系列时钟,把系统时钟设置为72MHZ。STM32的时钟比51 单片机复杂,需要经过一系列的配置才能达到稳定运行的状态。
__main 其实不是我们定义的,当编译器编译时,只要遇到这个标号就会定义这个函数,该函数的主要功能是:负责初始化栈、堆,配置系统境,并在最后跳转到用户自定义的main函数,从此来到C的世界。

第六行把SystemInit 的地址加载到寄存器R0。

第七行程序跳转到R0 中的地址执行程序,之后系统的时钟就被设置成72MHZ。

第八行把_main 的地址加载到寄存器R0。

第九行程序跳转到R0 中的地址执行程序,执行完毕之后就去到我们熟知的C 世界。

第十行表示子程序的结束。

<think>好的,我现在需要帮助用户解决如何正确导入STM32F10x系列的启动文件startup_stm32f10x_hd.s的问题。首先,我需要回忆一下STM32开发中的启动文件相关知识。根据引用[2]的内容,启动文件根据Flash容量分为ld、md、hd三种,分别对应小容量、中等容量和大容量产品。用户提到的是hd.s文件,所以对应的应该是大容量芯片,即Flash≥256KB的型号,比如STM32F103ZE等。 接下来,用户的问题是如何导入这个启动文件到项目中。我需要分步骤说明,可能包括创建项目结构、添加启动文件到工程、配置编译器选项、检查链接脚本以及验证配置是否正确。同时,需要确保用户正确选择启动文件,否则可能会出现卡死在启动文件的B处的问题,如引用[1]所述。 首先,项目结构方面,用户应该在工程目录下有一个专门的文件夹存放启动文件,比如Libraries/CMSIS/startup。然后,在IDE中(比如Keil MDK)添加该文件到项目的启动文件组中。这里需要提醒用户注意选择正确的启动文件,避免使用错误的容量版本导致问题。 然后,配置编译器选项。需要确保定义了STM32F10X_HD宏,这样在编译时预处理会根据宏选择正确的启动文件。这一步很关键,如果没定义宏,可能导致编译时使用了错误的代码路径,进而引发错误。 接下来是链接脚本的设置,确保链接器使用的脚本与芯片型号匹配。例如,大容量芯片可能需要使用stm32f10x_hd.ld文件。如果链接脚本不正确,程序可能无法正确分配内存,导致启动失败。 最后,验证配置是否正确。编译并调试程序,观察是否还会卡死在B处。如果仍然有问题,需要检查启动文件是否正确,宏定义是否设置,以及芯片型号是否选对。此外,启动文件中的栈大小设置也需要检查,根据引用[3],栈的大小在启动文件中定义,如果栈太小可能导致栈溢出,程序运行异常。 可能还需要提醒用户注意启动文件的来源,确保是从官方获取的,避免使用第三方修改过的版本。同时,不同开发环境(如IAR、GCC)的配置步骤可能有所不同,但总体思路类似。 在生成相关问题时,需要考虑用户可能遇到的后续问题,比如如何选择正确的启动文件,如何解决启动失败的问题,以及启动文件中栈和堆的配置等。这些问题都是用户在导入启动文件后可能会遇到的,因此提前列出有助于他们进一步排查问题。</think>### 如何正确导入 `startup_stm32f10x_hd.s` 到 STM32F10x 项目 #### 1. **确认芯片容量和启动文件匹配** - **启动文件分类**: - `startup_stm32f10x_ld.s`:小容量(Flash ≤32KB) - `startup_stm32f10x_md.s`:中容量(64KB ≤ Flash ≤128KB) - `startup_stm32f10x_hd.s`:大容量(Flash ≥256KB)[^2] - 需通过芯片型号(如 STM32F103ZET6)确认 Flash 容量,选择对应文件。若选错可能导致程序卡死在启动文件(如 `B .` 指令处)[^1]。 #### 2. **项目配置步骤(以 Keil MDK 为例)** - **步骤 1:添加启动文件到工程** 1. 在项目目录创建 `Libraries/CMSIS/startup` 文件夹,将 `startup_stm32f10x_hd.s` 放入。 2. 在 Keil 中右键点击项目 → 选择 `Add Existing Files...` → 添加该文件启动文件组。 ```plaintext 项目结构示例: ├── Core ├── Drivers └── Libraries └── CMSIS └── startup └── startup_stm32f10x_hd.s ``` - **步骤 2:设置编译宏定义** 1. 右键项目 → `Options for Target` → `C/C++` 标签页。 2. 在 `Define` 中添加 `STM32F10X_HD`(必须与启动文件后缀匹配)。 - **步骤 3:配置链接脚本** 1. 确保链接脚本(如 `stm32f10x_flash.ld`)与芯片 Flash 容量一致。 2. 若使用标准,需包含对应内存映射定义(如 `STM32F10X_HD` 对应的向量表)。 #### 3. **验证配置** - **编译检查**:无报错且生成 `.axf` 文件。 - **调试验证**:下载程序后单步执行,观察是否跳过 `B .` 指令(卡死通常因初始化失败或堆栈溢出)[^3]。 #### 4. **常见问题解决** - **问题 1:卡死在 `B .` 指令** - 检查启动文件是否与芯片容量匹配。 - 确认 `STM32F10X_HD` 宏已定义。 - **问题 2:栈溢出** - 修改启动文件中 `Stack_Size`(默认 1024 字节),增大后重新编译。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值