【嵌入式学习笔记】嵌入式基础9——STM32启动过程

文章详细介绍了MDK编译后生成的MAP文件,包括其包含的程序段交叉引用、内存分布、符号表等信息,以及MAP文件在代码优化中的作用。同时,文章阐述了STM32的启动模式和启动过程,从复位后的堆栈和程序计数器初始化,到Reset_Handler函数的执行,以及__main()函数在系统启动中的角色。

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

1.MAP文件浅析

1.1.MDK编译后生成的中间过程文件

在这里插入图片描述

1.2.Map文件构成:

  1. 程序段交叉引用关系(Section Cross References):描述各文件之间函数调用关系
  2. 删除映像未使用的程序段(Removing Unused input sections from the image):描述工程中未用到被删除的冗余程序段(函数/数据)
  3. 映像符号表(Image Symbol Table):描述各符号(程序段/数据)在存储器中的地址、类型、大小等
  4. 映像内存分布图(Memory Map of the image):描述各个程序段(函数)在存储器中的地址及占用大小
  5. 映像组件大小(Image component sizes):给出整个映像代码(.o)占用空间汇总信息

1.3.与MAP相关的概念

名词别称解释内存
Section/程序段/
RO(Read Only) data.constdata只读数据Flash(ROM)
RO(Read Only) code.text只读代码Flash(ROM)
RW(Read Write).data可写数据(定义了且初始化不为0)Flash(ROM)/SRAM
ZI(Zero initialized).bss定义了但没初始化(初始化为0)SRAM

总结:MAP文件是MDK编译代码后,产生的集程序、数据及IO空间的一种映射列表文件,简单说就是包括了:各种.c文件、函数、符号等的地址、大小、引用关系等信息。MAP的主要作用是分析各.c文件占用FLASH 和 RAM的大小,方便优化代码

2.STM32启动过程

2.1.STM32STM32启动模式(自举模式)

M3/M4/M7等内核复位后,做的第一件事:

  1. 从地址 0x0000 0000 处取出堆栈指针 MSP 的初始值,该值就是栈顶地址
  2. 从地址 0x0000 0004 处取出程序计数器指针 PC 的初始值,该值是复位向量
  3. 芯片厂商可以会把0x0000 0000和0x0000 0004地址映射到其它的地址(如0x0800 0000和0x0800 0004
    在这里插入图片描述
    启动模式选择表(STM32F1)
    (F4与其类似,FSMC可重映射到外部SRAM,F7/H7只有一个BOOT)
    在这里插入图片描述

2.2.STM32启动过程(以Flash为例)

  • 初始化MSP,从0x0800 0000获取堆栈指针 MSP,此时会设置堆(Heap_Size)和栈(Stack_Size)的大小
  • 初始化PC,从0x0800 0004获取程序计数器指针PC,此时PC指向中断向量表(Reset Vector,既__Vector),在中断向量表中,第一条指令即是Reset_Handler
  • 在Reset_Handler函数中,会调用SystemInit函数(可选),并调用标准C库函数__mian()执行一系列设置,调用main函数
  • __main()函数的细节
    __scatterload():把RW/RO输出段从装载域地址复制到运行域地址,并完成了ZI运行域的初始化工作
    __rt_entry():完成库函数的初始化
    __user_setup_stackheap():初始化堆栈

请添加图片描述

栈(Stack):编译器自动分配和释放,存放函数参数、函数调用、局部变量等
堆(Heap):程序分配和释放,如malloc、calloc、realloc等
函数局部变量较多,嵌套关系复杂时,需加大栈大小(Stack_Size)

Reset_Handler函数如下:

Reset_Handler   PROC								//PROC:定义子程序
													//WEAK:弱定义
                EXPORT  Reset_Handler   [WEAK]		//EXPORT:标明全局属性,可被外部调用
                IMPORT  __main						//IMPORT:申明来自外部文件,类extern
                IMPORT  SystemInit
                LDR   R0, =SystemInit
                BLX   R0               
                LDR   R0, =__main
                BX      R0
                ENDP								//ENDP:表示子程序结束

【注】Reset_Handler的作用:外部存储器配置;中断向量表地址配置。

在这里插入图片描述

__main()参考链接:
【1】STM32 启动解析__main main
【2】MDK __main()代码执行过程分析
【3】【stm32】stm32深入思考(1) 之 系统启动流程 main之前的过程,__main作用,start.s作用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值