当前位置: 首页 > ai >正文

STM32F103之存储/启动流程

一、存储器介绍

根据掉电留存特性,分为易失性存储器非易失性存

易失性存储器(RAM):

<1>动态随机存储(DRAM):依靠电容存储电荷记录数据,需定期刷新维持电荷,避免数据丢失。因集成度高、成本低,是计算机主存核心
①SDRAM:同步工作模式,与系统时钟同步读写,提升数据传输效率
②DDR 系列:沿 “双倍数据速率” 演进,频率、带宽逐步提升,像 DDR4 比初代 DDR 传输速度、能效比大幅优化,为游戏、高性能计算等场景提供高速内存支持。
<2>静态随机存储(SRAM):用触发器电路存储数据,无需刷新,速度远快于 DRAM ,但集成度低、成本高。多作为CPU 高速缓存(Cache) ,让 CPU 快速调取高频数据 / 指令,减少主存等待时间,提升整机运算效率

 非易失性存储器(ROM):

<1>ROM(只读存储器)
①MASK ROM:出厂时数据由厂商掩膜工艺固化,不可修改,常用于存储固定程序(如早期主板 BIOS基础代码 )。
②PROM(可编程 ROM):用户可一次性编程写入数据,写入后不可更改。
③OTPROM(一次性可编程):用户可自行写入一次数据,写入后无法更改,适合定制化、无需更新的简单程序存储。
④EPROM:通过紫外线照射擦除数据,可多次编程,但擦写需专用设备、操作复杂,渐被替代。

      ⑤EEPROM:电擦除特性,支持在线改写,像早期手机、U 盘 里的小容量存储,用于保存配置信息
<2>Flash(闪存)
基于 EEPROM 技术优化,按存储架构分:
①NOR FLASH:随机读写性能好,可像内存一样按字节 / 字访问,适合存储程序代码(如嵌入式系统固件 ),能快速执行指令。
②NAND FLASH:侧重大容量、高写入速度,以页 / 块为单位读写,成本低,是固态硬盘(SSD)、U盘、存储卡的核心存储介质,满足海量数据存储与读写需求

二、STM32存储简介 

2.1 STM32的FLASH

STM32单片机内部的FLASH为 NOR FLASH。Flash 相对容量大,掉电数据不丢失,主要用来存储代码,以及一些掉电不丢失的用户数据;内部的 RAM 为 SRAM。无需刷新,功耗较低,RAM相对容量小,速度快,掉电数据丢失,其作用是用来存取各种动态的输入输出数据、中间计算结果以及与外部存储器交换的数据和暂存数据。

STM32大容量flash

 2.2 STM32的RAM

特点:易失性存储(掉电数据丢失),读写速度快,用于临时存储运行时数据。
功能:
① 存储程序运行时的变量、堆栈(函数调用时的临时数据)。
② 作为数据缓冲区(如 ADC 采样数据、DMA 传输缓存)。
③ 部分场景下可将代码映射到 RAM 中运行(如需要高速执行的关键代码)。
分类:
①SRAM(静态 RAM):STM32 内部主要使用 SRAM,无需刷新,功耗较低。
②DRAM(动态 RAM):部分高端型号(如 STM32H7)可能集成少量 DRAM,用于高速缓存。
示例:STM32F10xxx内置64K字节的静态SRAM。它可以以字节、半字(16位)或全字(32位)访问。SRAM的起始地址是0x2000 0000

 2.3 STM32系统存储:0x1FFF F000

内嵌的自举程序(BootLoader)存放在系统存储区,由ST在生产线上写入,用于通过可用的串行接口对闪存存储器进行重新编程

ICP:通过芯片标准的硬件调试接口(通常是 SWDJTAG)对芯片进行编程。编程工具(如 ST-LINK, J-Link, U-Link 等调试器/编程器)直接连接到这些接口引脚
ISP:利用芯片内部固化的 Bootloader(引导加载程序)通过标准的通信接口(如 USART, USB, CAN, I2C, SPI 等)对芯片进行编程
IAP:用户应用程序(正在运行的程序)自身通过软件方法对 Flash 存储器(主要是包含自身或其他区域的用户 Flash)进行修改、擦除和重新编程

标题

三、存储属性 

 STM32的RAM上有RW和ZI两个属性区,里边包含了data,bss,堆(heap),栈(stack)这几个数据段。这里是程序运行的所在。Flash中有RO区,包含了text、constdata和data三个段,这里则是程序本体所在

四、 存储变化

 4.1 下载阶段

程序编译后生成可执行文件(如 bin、hex 格式 ),通过下载器(J - Link、ST - Link 等 ),将文件内容(包含Code(代码指令)、RO-data(只读数据,像常量 )、RW-data(已初始化的全局 / 静态变量 ))烧录到 STM32 内部 Flash 中 。因 ZI - data(未初始化 / 初始化为 0 的全局 / 静态变量 )全为 0,无需占用 Flash 空间,故下载时 Flash 存储 Code + RO-data + RW-data

4.2 上电阶段

Flash 数据:程序运行中,Flash 存储的 Code(CPU 执行的指令代码,直接从 Flash 读取执行)、RO - data(只读,持续存于 Flash )、RW - data(仅作为初始值来源,运行时会被拷贝到 RAM ),Flash 自身数据除程序更新外,运行中一般不改变(若程序有主动擦写 Flash 操作除外,比如存储掉电需保存的数据 )
RAM 数据:上电后,启动代码(startup 文件 )会执行
①搬运 Flash 里的 RW - data 到 RAM 对应区域(因 RAM 掉电丢数据,需从 Flash 取初始值 )
②把 RAM 中 ZI - data 对应区域清零(初始化未赋值 / 赋 0 的全局、静态变量 )
③程序运行时,RAM 动态存储 栈数据(函数调用、局部变量 )、堆数据(动态内存分配,如malloc 申请 ),以及被修改的全局 / 静态变量 ,随程序执行实时变化


简单说,下载时 Flash 存 “代码 + 只读数据 + 变量初始值”;上电后,Flash 保留代码和只读数据, RAM 则载入变量初始值、清零未初始化区域,再动态存运行时数据

程序占用 Flash = Code + RO data + RW data
程序运行时候占用 RAM = RW data + ZI data
Code + RO data + RW data 的大小也是生成的 bin 文件的大小

五、启动模式 

<1> 主闪存存储器(Main Flash)启动:从STM32内置的Flash启动(0x0800 0000-0x0807 FFFF),一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。以0x08000000对应的内存为例,则该块内存既可以通过0x00000000 操作也可以通过0x08000000 操作,且都是操作的同一块内存

 <2> 系统存储器(System Memory)启动:从系统存储器启动(0x1FFFF000 - 0x1FFF F7FF),这种模式启动的程序功能是由厂家设置的。一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的ISP程序中,提供了串口下载程序的固件,可以通过这个ISP程序将用户程序下载到系统的Flash中。以0x1FFFF000对应的内存为例,则该块内存既可以通过0x00000000 操作也可以通过0x1FFFF000操作,且都是操作的同一块内存

<3> 片上SRAM启动:从内置SRAM启动(0x2000 0000-0x3FFFFFFF),既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。SRAM 只能通过0x20000000进行操作,与上述两者不同。从SRAM 启动时,需要在应用程序初始化代码中重新设置向量表的位置

启动模式只决定程序烧录的位置,加载完程序之后会有一个重映射(映射到0x00000000地址位置);真正产生复位信号的时候,CPU还是从开始位置执行。

六、起动流程

Cortex-M3内核规定,起始地址必须存放堆顶指针,而第二个地址则必须存放复位中断入口向量地址,这样在Cortex-M3内核复位后,会自动从起始地址的下一个32位空间取出复位中断入口向量,跳转执行复位中断服务程序。

在离开复位状态后,CM3 做的第一件事就是读取下列两个 32 位整数的值
从地址 0x00000000 [0x08000000]处取出 MSP [栈顶指针]的初始值
从地址 0x00000004 [0x08000004]取出 PC 的初始值——这个值是复位向量,LSB 必须是 1。然后从这个值所对应的地址处取指

<1>初始化堆栈指针[设置栈顶指针的地址]
<2>初始化PC[程序执行的第一个函数Reset_Handler]
<3>跳转到Reset_Handler
在Reset_Handler中执行:
     ① 初始化.data段(复制Flash中的初始值到RAM)
清零.bss段(未初始化的全局变量)
③调用SystemInit()(时钟配置)
④重定位中断向量表(VTOR寄存器)
⑤跳转到C库的__main
__main中
初始化堆栈(用户堆/栈指针)
②调用运行时初始化
③跳转到用户main()函数

对于启动文件

1、堆栈初始化
2、中断向量表初始化,这是一个元素类型为word的数组,保存所有中断服务函数的地址
3、上电执行的第一个函数:复位中断服务函数,不需要用户重新定义,因为已经写好了
4、用户堆栈初始化

 

http://www.xdnf.cn/news/15092.html

相关文章:

  • HarmonyOS基础概念
  • 【TCP/IP】17. 移动 IP
  • Swift 解 LeetCode 324:一步步实现摆动排序 II,掌握数组重排的节奏感
  • 雷达遥感星座微波射频组件抗辐照MCU的选型与实践
  • 【JMeter】接口加密
  • 【JMeter】调试方法
  • 学弟让我帮忙写一个学生管理系统的后端,我直接上科技
  • [大模型问数]实现大模型调用MYSQL(03)【MCP笔记】
  • Webview 中可用的 VS Code 方法
  • Playwright Python 教程:网页自动化
  • 飞算JavaAI:新一代智能编码引擎,革新Java研发范式
  • Linux进程间通信--命名管道
  • 深度学习入门教程(三)- 线性代数教程
  • react打包发到线上报错Minified React error #130
  • 如何快速掌握WeNet:从零到一的端到端语音识别学习指南
  • spring-ai RAG(Retrieval-Augmented Generation)
  • 上位机知识篇---网络通信端口
  • 线程邮箱(线程间通信的异步缓存机制)
  • OBB旋转框检测配置与训练全流程(基于 DOTA8 数据集)
  • 云原生周刊:镜像兼容性
  • 十、MyBatis的逆向工程
  • 美颜SDK贴纸引擎设计指南:动画、识别与适配的实现逻辑
  • 华为数据通信网络基础
  • 香港站群服务器8C/4C/2C/1C有什么区别
  • 使用you-get命令下载视频/音频/图像
  • 北京-4年功能测试2年空窗-报培训班学测开-第四十八天
  • 【世纪龙科技】几何G6新能源汽车结构原理教学软件
  • 60 美元玩转 Li-Fi —— 开源 OpenVLC 平台入门(附 BeagleBone Black 驱动简单解析)
  • 飞算Java AI:专为 Java 开发者打造的智能开发引擎
  • uniapp制作一个个人页面