STM32启动流程详解

news2025/5/25 9:52:09

STM32启动流程详解

本文档详细介绍STM32微控制器从上电到main函数执行的完整启动流程。

1. 上电与复位过程

当STM32芯片上电或复位时,硬件会执行以下步骤:

  1. 上电复位(POR)/低电平复位(PDR): 芯片接通电源或NRST引脚置低时触发
  2. 初始PC值设置: 程序计数器(PC)被设置为0x00000000
  3. 首地址读取: CPU从地址0x00000000读取栈顶指针(MSP)的值
  4. 向量表读取: CPU从地址0x00000004读取复位向量(Reset_Handler的地址),并跳转执行

2. 启动文件执行流程

启动文件(startup_stm32f103xb.s)是STM32启动过程的关键部分,主要执行以下操作:

Reset_Handler:
  ldr   r0, =_estack      ; 加载栈顶指针到r0寄存器
  mov   sp, r0            ; 设置栈指针
  
  ; 初始化数据段
  ldr r0, =_sdata         ; 加载数据段目标起始地址
  ldr r1, =_edata         ; 加载数据段目标结束地址
  ldr r2, =_sidata        ; 加载数据段源起始地址(Flash中)
  movs r3, #0
  b LoopCopyDataInit
  
  ; ... 数据段复制循环 ...
  
  ; 初始化BSS段(清零)
  ldr r2, =_sbss          ; 加载BSS段起始地址
  ldr r4, =_ebss          ; 加载BSS段结束地址
  movs r3, #0
  b LoopFillZerobss
  
  ; ... BSS段清零循环 ...
  
  bl SystemInit           ; 调用SystemInit函数初始化系统时钟
  bl __libc_init_array    ; 调用C库初始化函数
  bl main                 ; 调用main函数
  bx lr                   ; 返回(实际上main函数不会返回)

3. 向量表

向量表定义在启动文件中,存储在Flash起始位置,包含:

  1. 栈顶指针(MSP): 向量表第一项是主栈指针初始值
  2. 复位向量: Reset_Handler函数地址
  3. 异常向量: 各种异常处理函数的地址(NMI、HardFault等)
  4. 中断向量: 外设中断处理函数的地址
__Vectors:
  .word _estack           ; 栈顶指针
  .word Reset_Handler     ; 复位处理函数
  .word NMI_Handler       ; NMI处理函数
  .word HardFault_Handler ; 硬件错误处理函数
  ; ... 其他异常和中断向量 ...

4. SystemInit函数详解

SystemInit函数定义在system_stm32f1xx.c文件中,主要负责系统时钟配置:

void SystemInit(void)
{
  /* 重置RCC时钟配置为默认复位状态 */
  /* 设置HSION位 */
  RCC->CR |= 0x00000001U;

  /* 复位SW、HPRE、PPRE1、PPRE2、ADCPRE和MCO位 */
  RCC->CFGR &= 0xF8FF0000U;
  
  /* 复位HSEON, CSSON和PLLON位 */
  RCC->CR &= 0xFEF6FFFFU;

  /* 复位HSEBYP位 */
  RCC->CR &= 0xFFFBFFFFU;

  /* 复位PLLSRC, PLLXTPRE, PLLMUL和USBPRE位 */
  RCC->CFGR &= 0xFF80FFFFU;

  /* 禁用所有中断 */
  RCC->CIR = 0x00000000U;

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* 若向量表在SRAM中 */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* 向量表在Flash中 */
#endif
}

主要功能:

  1. 配置系统时钟回到默认状态(通常使用内部RC振荡器HSI,8MHz)
  2. 设置向量表偏移地址(VTOR寄存器)

5. C库初始化

__libc_init_array()函数负责调用所有构造函数并初始化C/C++运行环境:

  1. 调用.preinit_array段中的所有函数
  2. 调用.init_array段中的所有函数
  3. 初始化全局变量和静态变量
    在这里插入图片描述
    我找了一下,在这里。反汇编代码如下。
    在这里插入图片描述
    这是__libc_init_array函数的ARM汇编代码:
    这个函数负责在main函数执行前初始化C/C++运行时环境,具体执行两个主要任务:

第一部分(处理.preinit_array段)

0-14:   保存寄存器并加载.preinit_array段的起始和结束地址
18-1c:  初始化循环计数器,计算数组元素数量(将字节差除以4)
24-38:  循环遍历.preinit_array中的每个函数指针并调用:
        - 加载函数指针到r3
        - 更新计数器
        - 通过bx指令调用函数
        - 比较是否已处理完所有函数

中间调用_init函数

3c:     bl _init  // 调用标准的初始化函数

第二部分(处理.init_array段)

40-54:  加载.init_array段的起始和结束地址,计算元素数量
58-74:  循环遍历.init_array中的每个函数指针并调用,过程与第一部分类似

结束处理

78-7c:  恢复保存的寄存器并返回

这个函数的主要作用是:

  1. 调用所有注册在.preinit_array段的预初始化函数
  2. 调用系统的_init函数
  3. 调用所有注册在.init_array段的初始化函数(包括全局C++对象的构造函数)

这样确保了在main函数开始执行前,所有必要的全局对象和C/C++运行时环境都已正确初始化。

6. main函数执行

在完成上述所有初始化步骤后,启动代码通过bl main指令跳转到用户定义的main函数,开始执行应用程序代码。

7. 数据段和BSS段

  • 数据段(.data): 已初始化的全局变量和静态变量,从Flash复制到RAM
  • BSS段(.bss): 未初始化的全局变量和静态变量,在RAM中清零

8. 启动流程总结

上电/复位 → 加载MSP → 跳转到Reset_Handler → 初始化栈指针 → 
复制.data段 → 清零.bss段 → SystemInit() → __libc_init_array() → main()

9. STM32启动流程的优化与自定义

在实际项目中,可以通过以下方式优化或自定义启动流程:

  1. 修改启动文件以支持特定的内存布局
  2. 自定义SystemInit函数实现特定的时钟配置
  3. 在main函数之前添加自定义的初始化代码

通过理解这一完整的启动过程,开发者可以更好地控制STM32应用程序的初始化行为,优化系统性能,并解决启动相关的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2336557.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Langchain + Gemini API调用基本操作

本文参考Langchain中ChatGoogleGenerativeAI的官方文档,在本地的jupyter notebook中运行。 关于API的细节在官方文档最开头给出: 我们在使用时,可以选择model"gemini-2.0-flash-001"或者生成图片的ChatGoogleGenerativeAI(model“…

【数据结构】4.单链表实现通讯录

在上一篇文章我们学会了用单链表来实现各种方法,在这一篇文章我们将在单链表的基础上实现通讯录。 0、准备工作 实现通讯录之前,我们还需要在单链表的基础上添加2个文件,头文件Contact.h和源文件Contact.c。Contact.c来实现通讯录方法的声明…

接口自动化测试(一)

一、HTTP请求的核心概念及原理详解 HTML:超文本标记语言-----通过<标记符>内容</标记符>格式-------页面 URL:统一资源定位符 返回数据有很多&#xff1a;页面、图片、视频&#xff0c;都可以进行返回---统称为&#xff1a;资源HTTP:超文本传输协议(请求-响应的协…

【JavaEE】Spring AOP的注解实现

目录 一、AOP 与 Spring AOP二、Spring AOP简单实现三、详解Spring AOP3.1 Spring AOP 核心概念3.1.1 切点&#xff08;Pointcut&#xff09;3.1.2 连接点&#xff08;Join Point&#xff09;3.1.3 通知&#xff08;Advice&#xff09;3.1.4 切面&#xff08;Aspect&#xff09…

揭秘大数据 | 22、软件定义存储

揭秘大数据 | 19、软件定义的世界-CSDN博客 揭秘大数据 | 20、软件定义数据中心-CSDN博客 揭秘大数据 | 21、软件定义计算-CSDN博客 老规矩&#xff0c;先把这个小系列的前三篇奉上。今天书接上文&#xff0c;接着叙软件定义存储的那些事儿。 软件定义存储源于VMware公司于…

OpenCV 图形API(37)图像滤波-----分离过滤器函数sepFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 应用一个可分离的线性滤波器到一个矩阵&#xff08;图像&#xff09;。 该函数对矩阵应用一个可分离的线性滤波器。也就是说&#xff0c;首先&a…

flutter下载SDK环境配置步骤详解

目录 1.Flutter官网地址、SDK下载地址? 1.1 选择你电脑的系统​ 2.配置环境 3.解决环境报错 zsh:command not found:flutter 1.Flutter官网地址、SDK下载地址? flutter官网地址: URL 1.1 选择你电脑的系统 下载解压动目录就OK了 2.配置环境 1、打开命令行&#xf…

数据结构与算法入门 Day 0:程序世界的基石与密码

&#x1f31f;数据结构与算法入门 Day 0&#xff1a;程序世界的基石与密码&#x1f511; ps&#xff1a;接受到了不少的私信反馈&#xff0c;说应该先把前置的知识内容做一个梳理&#xff0c;所以把昨天的文章删除了&#xff0c;重新开启今天的博文写作 Hey 小伙伴们&#xff…

vscode终端运行windows服务器的conda出错

远程windows服务器可以运行&#xff0c;本地vscode不能。 打开vscode settings.json文件 添加conda所在路径

“大湾区珠宝艺境花园”璀璨绽放第五届消博会

2025年4月13日&#xff0c;第五届中国国际消费品博览会&#xff08;以下简称"消博会"&#xff09;重要主题活动——《大湾区珠宝艺境花园》启动仪式在海南国际会展中心2号馆隆重举行。由广东省金银珠宝玉器业厂商会组织带领粤港澳大湾区优秀珠宝品牌&#xff0c;以“…

十、自动化函数+实战

Maven环境配置 1.设计测试用例 2.创建空项目 1&#xff09;添加需要的依赖pom.xml <dependencies> <!-- 截图配置--><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</…

Day09【基于jieba分词和RNN实现的简单中文分词】

基于jieba分词和RNN实现的中文分词 目标数据准备主程序预测效果 目标 本文基于给定的中文词表&#xff0c;将输入的文本基于jieba分词分割为若干个词&#xff0c;词的末尾对应的标签为1&#xff0c;中间部分对应的标签为0&#xff0c;同时将分词后的单词基于中文词表做初步序列…

自动化测试——selenium

简介 Selenium 是一个广泛使用的自动化测试工具&#xff0c;主要用于 Web 应用程序的自动化测试。它能实现的功能是网页的自动化操作&#xff0c;例如自动抢票刷课等。同时你应该也见到过有些网站在打开之后并没有直接加载出网站的所有内容&#xff0c;比如一些图片等等&#x…

Linux——进程通信

我们知道&#xff0c;进程具有独立性&#xff0c;各进程之间互不干扰&#xff0c;但我们为什么还要让其联系&#xff0c;建立通信呢&#xff1f;比如&#xff1a;数据传输&#xff0c;资源共享&#xff0c;通知某个事件&#xff0c;或控制某个进程。因此&#xff0c;让进程间建…

【免费参会合集】2025年生物制药行业展会会议表格整理

全文精心整理, 建议今年参会前都好好收藏着&#xff0c;记得点赞&#xff01; 医药人非常吃资源&#xff0c;资源从何而来&#xff1f;作为一名从事医药行业的工作者&#xff0c;可以很负责任的告诉诸位&#xff0c;其中非常重要的一个渠道就是会议会展&#xff01; 建议所有医…

腾讯云开发+MCP:旅游规划攻略

1.登录注册好之后进入腾讯云开发 2.创建环境 4.创建好环境之后点击去开发 5.进入控制台后&#xff0c;选择AI&#xff0c;找到MCP 6.点击创建MCP Server 使用腾讯云开发创建MCP目前需要云开发入门版99/月&#xff0c;我没开通&#xff0c;所以没办法往下进行。

Sklearn入门之数据预处理preprocessing

、 Sklearn全称:Scipy-toolkit Learn是 一个基于scipy实现的的开源机器学习库。它提供了大量的算法和工具&#xff0c;用于数据挖掘和数据分析&#xff0c;包括分类、回归、聚类等多种任务。本文我将带你了解并入门Sklearn下的preprocessing在机器学习中的基本用法。 获取方式…

家用打印机性价比排名及推荐

文章目录 品牌性价比一、核心参数对比与场景适配二、技术类型深度解析三、不同场景选择 相关文章 品牌 性价比 一、核心参数对比与场景适配 兄弟T436W 优势&#xff1a; 微压电技术&#xff0c;打印头寿命长&#xff0c;堵头率低。 支持A4无边距和5G WiFi&#xff0c;适合照片…

数字电子技术基础(四十七)——使用Mutlisim软件来模拟74LS85芯片

目录 1 使用74LS85N芯片完成四位二进制数的比较 1.1原理介绍 1.2 器件选择 1.3 运行电路 2 使用74LS85N完成更多位的二进制比较 1 使用74LS85N芯片完成四位二进制数的比较 1.1原理介绍 对于74LS85 是一款 4 位数值比较器集成电路&#xff0c;用于比较两个 4 位二进制数&…

关于STM32创建工程文件启动文件选择

注意启动文件只要选择这几个 而不是要把所有都选上