STM32学习:存储器组织

一、存储结构

STM32ç³»ç»ç»æ

  STM32F1有四种存储单元,依次是SRAM、Flash、FSMC和AHB到APB桥(挂载各种外设)。

二、存储组织
程序存储器、数据存储器、寄存器和输入输出端口被组织在同一个4GB的线性地址空间内。数据字节以小端格式存放在存储器中。一个字里的最低地址字节被认为是该字的最低有效字节,而最高地址字节是最高有效字节。
  可访问的存储器空间被分成8个主要块,每个块为512MB。其他所有没有分配给片上存储器和外设的存储器空间都是保留的地址空间。

STM32å­å¨ç»ç»

  其详细存储分配如下,

Cortex-M3详ç»å­å¨åé

  以上存储器映射的对应地址,用户不可更改。用户的外设、扩展Flash和扩展RAM只能挂在外部设备区和外部RAM区。

1.片内Flash

大容éSTM32F1ççä¸Flashå­å¨ç»æ

  虽然存储器逻辑地址分配时,Code区地址是从0x0000 0000到0x1FFF FFFF,但实际片上Flash的起始地址是0x0800 0000。这是因为ARM给出的Cortex-M3内核标准中,上电后CPU必须从0地址开始执行,ST在设计STM32时,为实现不同的启动模式设计了一个启动映射的过程,即系统上电后会根据BOOT0和BOOT1的引脚电平将启动位置地址(主闪存存储器启动:0x0800 0000;系统存储器启动:0x1FFF F000;内置SRAM启动:0x2000 0000)映射到0地址,所以Code区的0x0000 0000到0x07FF FFFF地址,不与任何物理存储器相关联,只是用作启动映射空间。
STM32的Flash包括:Flash主存储区(Main memory)、系统存储器(System memory),以及操作(选择)字节(Opetio Bytes)。如图所示:
  Flash主存储区从0x0800 0000地址开始,不同系列器件有不同大小,这里存放为用户烧入的代码(CODE)、常量(RO)和已经初始化的全局变量的值(RW)。
  系统存储器地址0x1FFF F000 – 0x1FFF F71F,这是厂商出厂之前烧入的一段程序,用来使用串口下载程序,实现IAP。该处你只能使用,不能写或擦除。
  操作字节:可以按照用户的需要进行配置(如配置看门狗为硬件实现还是软件实现)。

Flash存储段划分
  Code指存储到Flash【ROM】中的程序代码。
  ZI英语是Zero Initial,就是程序中用到的变量并且被系统初始化为0的变量的字节数,keil编译器默认是把你没有初始化的变量都赋值一个0,这些变量在程序运行时是保存在RAM中的。
   RW是可读可写变量,就是初始化时候就已经赋值了的,RW + ZI就是你的程序总共使用的RAM字节数。
   RO是程序中的指令和常量,这些值是被保存到Flash【ROM】中的。
   Total ROM Size (Code + RO Data + RW Data)这样所写的程序占用的Flash【ROM】的字节总数,也就是说程序所下载到Flash【ROM】中的大小。为什么Flash【ROM】中还要存RW,因为掉电后RAM中所有数据都丢失了,每次上电RAM中的数据是被重新赋值的,每次这些固定的值就是存储在Flash【ROM】中的,为什么不包含ZI段呢,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。
  实际上,Flash【ROM】中的指令至少应该有这样的功能:
   1. 将RW从Flash【ROM】中搬到RAM中,因为RW是变量,变量不能存在Flash【ROM】中。
   2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在Flash【ROM】中。

2.片内RAM
STM32F10xxx内置64K字节的静态SRAM。它可以以字节、半字(16位)或全字(32位)访问。SRAM的起始地址是0x2000 0000。
  SRAM就是单片机的内存空间,内部非堆即栈。堆由低地址向上增长,地址从0x2000 0000开始,栈由高地址向下增长。堆中包括静态区和用户分配空间(malloc分配的空间),静态区包括全局变量(ZI、RW) 和静态变量,栈中存储局部变量。

; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp
                                                  
; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

                PRESERVE8
                THUMB


从启动文件startup_stm32f10x_hd.s的定义中可以看出,这里定义了堆栈各自大小,堆:512bytes ,栈:1k。

2.1 RAM中的数据存放
上面提到,STM32程序在MDK中编译完成后,会生成几个段Code、RO-data、RW-data、ZI-data,其中RW和ZI段保存的是可读写的数据变量。程序启动后,STM32会将可读写变量从ZI、RW数据段中搬到RAM中,为了区分管理内存数据,RAM也分了几个区(段)来存储不同类型的变量。
一个经典的例子如下:

main.cpp 
int a = 0;    //全局初始化区 
char *p1;    //全局未初始化区 
main() 
{ 
    int b;//栈 
    char s[] = "abc";//栈 
    char * p2;//栈 
    char * p3 = "123456";//123456\0在常量区,p3在栈上。 
    static int c =0;//全局(静态)初始化区 
    p1 = (char *)malloc(10);//堆 
    p2 = (char *)malloc(20);//堆 
}



2.2 RAM分区
不同于冯·诺依曼架构的PC机,Cortex-M3内核的STM32采用的是哈佛架构,也就是程序和数据分开存储。在主闪存存储器启动模式下,内核直接从Flash中取指令,而无需将Flash中的程序挪到RAM中执行,所以,该模式下,RAM从低地址到高地址依次分为静态存储区、堆区、栈区。
  全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序启动时,STM32根据Flash中写入的RW、ZI区信息,在RAM中创建相应变量,程序结束后由系统自动释放。
  栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似于数据结构中的栈。
  堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配方式类似于数据结构中的链表。
 

展开阅读全文

没有更多推荐了,返回首页