STM32存储结构& 存储器映射

本文参考《CM3权威指南》第五章 存储器系统
              《STM32_参考手册》2.4 启动配置
               《STM32F103xCDE_数据手册》第四章 memory mapping

一、STM32存储结构

Cortex-M3内核将0x0000_0000——0xFFFF_FFFF这块4G大小的空间分成8大块:代码、SRAM、外设、外部RAM、外部设备、专用外设总线-内部、专用外设总线-外部、特定厂商等。
Cortex-M3支持4GB的存储空间,它的存储系统采用统一编址的方式,程序存储器、数据存储器、寄存器被组织在4GB的线性地址空间内,以小端格式(little-endian)存放。由于Cortex-M3是32位的内核,因此其PC指针可以指向2^32=4G的地址空间,也就是0x0000_0000——0xFFFF_FFFF这一大块空间。
Cortex m3内核规定的存储器映射如下图所示。就好像ARM公司打造了一个柜子,从上到下有这几个抽屉,它规定了每个抽屉放的东西的种类,具体放什么放多少它不管(只要不超过抽屉的大小),由每个芯片厂商自己决定。
Cortex m3内核
STM32内核(Cortex-M3)的存储器映射
STM32内核(Cortex-M3)的存储器映射
可以这样理解Cortex-M3是一个内核,自身定义了一个存储器结构4G,ST公司按照Cortex-M3的这个存储器定义,设计出了自己的存储器结构;但是ST公司的STM32的存储器结构必须按照Cortex-M3这个定义的存储器结构来进行设计。

二、存储器映射

存储器映射是指把芯片中或芯片外的FLASH,RAM,外设,BOOT,BLOCK等进行统一编址。即用地址来表示对象。
以STM32F103F1C8T6为例介绍存储映射:
该系列芯片将寄存器、输入输出端口、程序存储器、数据存储器映射在4GB的空间当中(0x0000 0000 - 0xFFFF FFFF)2^32Bytes

顺序如下:
0x0000 0000 — 0x0800 0000 根据Boot引脚配置映射到Flash /Sysmem/SRAM 当中 128MB 空间

0x0800 0000 — 0x0801 FFFF Flash Memory 闪存存储空间 128KB 空间

0x1FFF F800 — 0x1FFF F7FE System Memory 系统存储空间 2KB 空间

0x2000 0000 — up SRAM 存储区

0x4000 0000 — up Peripherials外设映射段每个外设约获得1KB

0xE000 0000 — 0xe01 0000
Cotex-M3 Internal Peripherial Contex内部外设1MB 空间
详细介绍:
Peripherals:外设的存储器映射,对该区域操作,就是对相应的外设进行操作;

SRAM:运行时临时存放代码的地方;

Flash:存放代码的地方;

System Memory:STM32出厂时自带的你只能使用,不能写或擦除;存储ISP-bootloader

Option Bytes:可以按照用户的需要进行配置(如配置看门狗为硬件实现还是软件实现);
今后,编写代码、程序运行、寄存器设置、ICP、IAP都依靠这些东西。
+==================================================
STM32的Flash,严格说,应该是Flash模块。三个分区的称呼与datasheet保持一致。该Flash模块包括:

Flash主存储区(Main memory)Flash存放代码的地方,128KB(0x08000000~0x0801ffff)(不同容量的Flash终止地址不同);

Flash信息区(Information block),该区域又可以分为Option BytesSystem Memory区域;System Memory:STM32在出厂时,已经固化了一段程序在System memory(medium-density devices的地址为:0x1FFF_F000,大小为2KB)存储器中。这段程序就是一个固定好的,并且没法修改的Boot Loader。Option Bytes:可以按照用户的需要进行配置(如配置看门狗为硬件实现还是软件实现);

Flash存储接口寄存器区(Flash memory interface)用于片上外设。是图2中从0x40000000开始的PERIPHERALS区域。也称作外设存储器映射,对该区域操作,就是对相应的外设进行操作。
+==================================================
STM32 的外设地址映射:

  1. 总线基地址
    片上外设区分为三条总线,根据外设速度的不同,不同总线挂载着不同的外设,APB1挂载低速外设,APB2 和AHB 挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。
#define FLASH_BASE            ((uint32_t)0x08000000) /*!< FLASH base address in the alias region */
#define SRAM_BASE             ((uint32_t)0x20000000) /*!< SRAM base address in the alias region */
#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */

#define SRAM_BB_BASE          ((uint32_t)0x22000000) /*!< SRAM base address in the bit-band region */
#define PERIPH_BB_BASE        ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */

#define FSMC_R_BASE           ((uint32_t)0xA0000000) /*!< FSMC registers base address */

/*!< Peripheral memory map */
#define APB1PERIPH_BASE       PERIPH_BASE
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)
  1. 外设基地址
    总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的首个地址称为“XX 外设基地址”,也叫XX 外设的边界地址。
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)

总结:封装总线和外设基地址
“片上外设”基地址PERIPH_BASE,接着在PERIPH_BASE 上加入各个总线的地址偏移, 得到APB1 、APB2 总线的地址APB1PERIPH_BASE 、APB2PERIPH_BASE,在其之上加入外设地址的偏移,得到GPIOA-G的外设地址,最后在外设地址上加入各寄存器的地址偏移,得到特定寄存器的地址。一旦有了具体地址,就可以用指针读写。
 3. 封装寄存器列表
 用上面的方法去定义地址,还是稍显繁琐,例如GPIOA-GPIOE 都各有一组功能相同的寄存器,如GPIOA_ODR/GPIOB_ODR/GPIOC_ODR 等等,它们只是地址不一样,但却要为每个寄存器都定义它的地址。为了更方便地访问寄存器,我们引入C 语言中的结构体语法对寄存器进行封装。

typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

这段代码用typedef 关键字声明了名为GPIO_TypeDef 的结构体类型,结构体内有7 个成员变量,变量名正好对应寄存器的名字。C 语言的语法规定,结构体内变量的存储空间是连续的,其中32 位的变量占用4 个字节,16 位的变量占用2 个字节。
GPIO_TypeDef
也就是说,我们定义的这个GPIO_TypeDef ,假如这个结构体的首地址为0x40010C00(这也是第一个成员变量CRL 的地址), 那么结构体中第二个成员变量CRH 的地址即为0x4001 0C00 +0x04 ,加上的这个0x04 ,正是代表CRL 所占用的4 个字节地址的偏移量,其它成员变量相对于结构体首地址的偏移。
这样的地址偏移与STM32 GPIO 外设定义的寄存器地址偏移一一对应,只要给结构体设置好首地址,就能把结构体内成员的地址确定下来,然后就能以结构体的形式访问寄存器。

参考:  STM32F1(Cortex M3内核)存储器映射
           STM32的存储器映射详解
           单片机STM32学习笔记之寄存器映射详解
           stm32存储结构& 存储器映射(整理)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值