一、存储器结构
1.1 STM32内存结构
型号说明
以STM32F103RBT6这个型号的芯片为例,该型号的组成为7个部分,其命名规则如下:
ST 是公司名,意法半导体。M 代表Cortex-M内核。32 代表32位微控制器。
F103 是芯片系列。
R 代表引脚数。B 代表内嵌FLASH容量。128K字节的内嵌FLASH。
T 代表封装方式。6 代表工作温度范围。
内存空间
以STM32F103RBT6为例,内部存储空间包括128KB的FLASH,20KB的SRAM。
由于FLASH每次写入前都要擦除,适合存放代码和只读数据。SRAM读写快速,但是断电丢失,适合存放临时数据。
KEIL的target设置界面-F103RB
KEIL的target设置界面-F429IGT6
通过 Keil 的 target 设置界面,可以看到内部FLASH和内部RAM的起始映射地址和大小设置,这里一般选择了芯片型号会有默认值。
关于下载地址,在IAP使用BootLoader程序,跳转到APP程序的方式下,比如用户自设BootLoader的代码大小为0x4000,那么就应该把BootLoader放在内部Flash起始地址0x0800 0000的位置,大小设置为0x4000(可以给大);对应的把APP程序放在起始地址0x0800 4000的位置,大小设置为对应程序大小。
FLASH用来存储编译好的程序文件,SRAM用来存储程序运行所需的临时数据。
0x0000 0000 ~ 0x0007 FFFF,也就是代码区的这512KB的字节启动内存空间,是预留的。
STM32有三种启动方式,
FLASH启动,代码存放在0x0800 0000
系统存储器启动,代码存放在0x1FFF F000
SRAM启动,代码存放在0x2000 0000
可以通过BOOT引脚设置。
Boot引脚决定了字节启动内存空间被映射到哪一块区域。
不管是FLASH启动、系统存储区启动还是RAM启动,代码第一步都是去0x0000 0000去找MSP指针,去0x0000 0004去找PC指针。
根据映射关系,实际找的位置可以是FLASH的0x0800 0000,系统存储区的0x1FFF F000,SRAM的0x2000 0000。
另外,系统自带的BootLoader程序,是放在0x1FFF F000的,固定大小,禁止修改。
内存映射
STM32的内存和外设的地址,不管内部还是外部,都被映射在一个4GB的虚拟地址空间内。
可访问的存储器空间被分为 8个主要块,每个块为512MB。
分别作为 代码区 、SRAM区 、片上外设 、1G的外部存储器扩展、1G的片外外设 、不同厂商的专用外设总线(包括NVIC、调试组件等)。
其中1G的外部存储器扩展,拿来给FSMC1、FMSC2使用。1G的片外外设,高位拿了512M给FSMC使用。
CCM RAM:
CCM RAM,核心耦合内存,是给F4系列专用的全速 64KB RAM,官方文档指出芯片的SRAM大小为128K+64K,后面的64K就是指CCM RAM。
CCM RAM 大小为 0x1000_0000 ~ 0x1000_FFFF,不经过总线矩阵,直接与内核相连,仅供内核访问。其地址位于代码区,与常规SRAM区不连续,DMA与外设也无法直接使用它们。可以用编译器指令去写链接脚本文件(.icf),把数据定义在CCM RAM中,extern出来使用。
以F429系列为例,典型的存储器映射布局:
代码区的 0x0800 0000 ~0x080F FFFF (1MB),存储程序代码
SRAM区的 0x20000 0000~0x2003 FFFF (256KB),作为堆栈
片上外设的 0x4000 0000~0x4000 FFFF,用于APB1上的外设;
0x4001 0000~0x400F FFFF,用于APB2上的外设。
关于 FSMC 和 FMC:
FMC是STM32F429/439专有的,因为驱动SDRAM时需要定时刷新 ,而FSMC存在于F1和F4中我们常用的芯片中。FMC 支持 8/16/32位数据宽度,LCD一般是16位宽度的,
FMC 将外部存储器划分为 6 个固定大小为 256M 字节的存储块 ,也就是总共管理 1.5GB 空间。每个块又被分为 4 个存储区,一个区 64 M。
FSMC 只支持 BANK1~4。
0x6000 0000~0x6FFF FFFF BANK1 SRAM使用
0x7000 0000~0x7FFF FFFF BANK2
0x8000 0000~0x8FFF FFFF BANK3 FLASH使用
0x9000 0000~0x9FFF FFFF BANK4 PC卡使用
0xC000 0000~0xCFFF FFFF BANK5
0xD000 0000~0xDFFF FFFF BANK6 SDRAM使用
1.2 STM32启动过程
概括
.s启动文件,汇编程序,系统上电复位后首先执行。
1、初始化主堆栈指针MSP,指向栈顶
2、初始化 PC 指针,指向下一条要执行的指令地址
3、初始化中断向量表(复位中断服务函数中初始化中断向量表)
4、调用SystemInit函数初始化系统时钟
5、调用 C 库函数 _main 初始化用户堆栈,调用main函数
ResetHandler是弱定义,用户可以自己实现。
如果KEIL勾选了使用微库,则.s文件的__MICROLIB宏被定义,由_main初始化堆栈。如果没有定义 __MICROLIB,则才用双段存储器模式,且声明标号 __user_initial_stackheap 具有全局属性,让用户自己来初始化堆栈。
STM32片上SRAM结构
C语言内存管理分为:代码段、数据段、BSS段、堆、栈、mmap映射
_main初始化用户堆栈,片上SRAM区作为 数据段、BSS段、堆、栈、mmap映射 的区域。
mmap是linux系统编程涉及的映射文件
系统ISP启动流程
正常情况下,程序从Flash启动时的流程如下:
程序从Flash启动,根据中断向量表找到复位中断处理函数的地址。(0x0800 0004处是中断向量表的起始地址,也是中断向量表的起始,记录了复位中断处理函数的地址)。配置系统时钟 。执行**_main**,完成堆栈的初始化。
执行复位中断处理函数,初始化系统环境后跳转到main函数。
在main函数的死循环中运行,直到有中断发生。
中断发生时,跳转到中断向量表起始处,根据中断信号源跳找到相应的中断处理函数。
中断处理函数执行完后返回到main函数继续运行。
系统IAP启动流程
在Flash中存储了两套程序:
Bootloader程序:自举程序。负责接收数据(APP应用程序代码)并将其存储到Flash中。
APP应用程序:我们真正的应用程序。
程序从Flash启动,根据中断向量表 找到复位中断处理函数的地址。
执行复位中断处理函数后,跳转到Bootloader的main函数。该函数检查并保存新的APP程序到Flash,然后跳转到第二套程序运行。
一旦进入新的APP程序,根据中断向量表找到复位中断处理函数,进入App程序的main函数运行。
为确保中断能正确跳转到APP程序的中断处理函数,需要在APP程序中修改中断向量表的偏移,确保中断发生时能正确执行APP程序的中断处理函数。
SCB->VTOR寄存器存放中断向量表的偏移量
二、 系统架构
STM32主系统由AHB总线矩阵构成。
AHB总线矩阵 ,可以实现主控总线到被控总线的访问。
2.1 主控和被控总线
八条主控总线包括:
Cotex内核的 I、D、S 总线。也就是指令、数据、系统总线。
DMA-存储器 总线。 DMA-存储器总线有2条。
DMA-外设总线。
以太网-DMA总线。
USB-DMA总线。
七条被控总线包括:
内部FLASH ICode总线
内部FLASH DCode总线
主要内部 SRAM1 (112KB)
辅助内部 SRAM2 (16KB)
辅助内部 SRAM3 (64KB) (仅适用于F42x和F43x)
AHB总线
FSMC总线
主控总线通过总线矩阵来连接被控总线, 总线矩阵用于主控总线之间的访问仲裁管理,仲裁采用循环调度算法。 其实就是外设请求先来后到。
通过指令总线获取程序指令。访问对象是内部FLASH/SRAM。
通过数据总线获取常量和调试访问。访问对象是内部FLASH。
通过系统总线获取内部SRAM和片上外设,访问对象是内部SRAM和AHB/APB的外设数据。
通过DMA-存储器总线(1、2) 访问内部SRAM和FSMC。通过DMA-外设总线 访问AHB/APB外设 ,内部SRAM和FSMC。
通过以太网-DMA总线 访问内部SRAM和FSMC。
通过USB-DMA总线 访问内部SRAM和FSMC。
SRAM可放程序缓存,因此 I 总线可访问内部FLASH和SRAM。
I、D、S总线都能依靠依靠FSMC访问外部存储器*。I、D、S总线各自都有自己的地址线、数据线、控制线。*
立即数不放在存储器或内存中,一般是常数。
FLASH放程序和指令。SRAM只可能放指令的缓存。
外部存储器可能放代码也可能放指令,因此 I、D、S总线均可依靠FSMC访问外部存储器。
2.2 AHB/APB 总线桥和时钟源
外设分为高速外设和低速外设。
1、高速外设
由于高速外设实在是太多了,一个总线不够,所以分了三个,分别是 AHB1/AHB2/AHB3,所有"高速外设"寄存器组分批挂接在 AHB1/AHB2/AHB3 上。
2、低速外设
"低速外设"的速度比较低,不能直接挂在"总线矩阵"上,所以先经过"桥"后再引出"低速总线",挂在低速总线上。由于"低速外设"比较多,所以就分了两个低速总线,分别是 APB1/APB2,所有的"低速外设"分批挂接在 APB1/APB2 上。
AHB-APB总线桥,
将系统时钟分频后,传递到APB1、APB2两条总线,再传递到挂载的外设上。
APB1总线 、APB2总线
负责外设时钟使能,并为外设提供时钟信号。
MCU 的系统时钟可以选择 HSI、LSI、HSE、LSE 四种时钟源,
一般设置为16M、32K、8M、32.768K,单位(HZ)
系统时钟F1一般是72MHZ,
F429的SYSCLK根据板子功率有
SYSCLK 180MHZ,AHB是1分频,180MHZ,APB2是90MHZ,APB1是45MHZ
SYSCLK 168MHZ,AHB是1分频,168MHZ,APB2是84MHZ,APB1是42MHZ
HSE和HSI经过 /M 分频之后传递到锁相环,
锁相环会使晶振走过*N倍频器,
之后如果再走过/P分频则可以直接作为系统时钟SYSCLC,
如果走过/Q分频则可以作为其他外设的时钟。
系统时钟之后会去到AHB总线的时钟
AHB时钟经过总线桥会去到APB1和APB2(这俩实际上是由AHB1桥接过来的)