STM32学习——单片机启动和程序的运行
·
一、单片机程序运行的本质
1.程序代码放在哪
2.变量放在哪
3.cpu上电后先执行谁
对mcu来说:
- Flash:掉电不丢,存程序代码和常量
- RAM:掉电丢失,存运行时变量
- CPU:从一个固定入口开始执行指令
程序运行的本质就是:
把“该放 Flash 的东西”放到 Flash,
把“该放 RAM 的东西”安排好,
然后 CPU 从复位入口开始跑,先做初始化,再跳进main()
二、从源代码到单片机可执行文件的流程
一、编译阶段
输入:main.c、led.c、uart.c、startup.s等源代码文件
预处理:编译器首先处理源代码中的宏定义、头文件包含和条件编译指令,生成预处理后的代码文件(通常以
.i为后缀)。
此阶段会将所有宏展开、嵌入头文件内容、清除注释编译:将预处理后的代码转换为汇编语言(通常以
.s为后缀)。
此阶段进行语法分析、语义检查、中间表示生成和优化。汇编:将汇编代码转换为目标文件(通常以
.o为后缀)。
目标文件包含二进制机器码、符号表和重定位信息
输出:main.o、led.o、uart.o、startup.o等目标文件
二、链接阶段
输入:所有目标文件(.o文件)和链接脚本(.ld文件)
.ld 链接文件:内存分配总规划图
合并段:链接器将所有目标文件中的相同段合并,如所有
.text段(代码)合并成一个大的.text段,所有.data段(已初始化数据)合并成一个.data段符号解析:链接器查看所有目标文件的符号表,将引用与定义关联起来。
- 例如:
printf函数的引用会被链接到标准库中的实现地址重定位:根据链接脚本(
.ld文件)为每个符号分配最终的内存地址,并修正所有"浮动"的地址引用。
- 链接脚本定义了单片机内存布局
MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1M RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K } SECTIONS { .vector_table : { KEEP(*(.vector_table)) } > FLASH .text : { *(.text) *(.rodata) } > FLASH .data : { *(.data) } > RAM AT > FLASH .bss : { *(.bss) } > RAM }
输出:.elf文件、.map文件、.bin或.hex文件
.elf文件:包含完整的代码、数据和调试信息的可执行文件.map文件:内存映射文件,显示程序的内存布局和符号地址
- 包含段交叉引用表(Section Cross References),显示"谁调用了谁"的关系
.bin或.hex文件:通过格式转换工具生成的二进制文件,用于烧录
三、烧录
将二进制文件.bin或.hex文件烧录到单片机的Flash当中
三、单片机上电的启动流程
1.完整的启动流程

1.硬件自动做的事情
- 确定从哪里启动
- 读取向量表
- 设置 MSP
- 跳转到
Reset_Handler2.startup.s里的启动代码做的
- 提供向量表
- 提供
Reset_Handler- 初始化 C 运行环境
- 最终调用
main()3.
SystemInit()做的
- 配置时钟树
- 初始化 PLL
- 配置 FPU
- 设置向量表偏移寄存器
VTOR(某些工程)- 芯片底层系统配置
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)