嵌入式软件开发必备知识—存储器和寄存器器映射(重要)

 一、存储器映射

        存储器映射是一种计算机内存管理技术,它将计算机存储器的一部分映射到处理器的地址空间。这样,处理器就可以直接访问内存中映射的地址,而不需要进行复杂的寻址计算。存储器映射可以用于访问计算机的物理内存、设备寄存器、硬件设备等。在存储器映射中,不同的地址被映射到不同的实际内存位置或硬件设备,这样可以简化对内存的管理和操作。

        存储器是可以存储数据的设备,本身是没有地址信息的,对存储器分配地址的过程称为存储器映射。

先复习一点知识:

        1  Byte  =  8  bit(位)
        1  Kilobyte  (KB)  =  1,024  Bytes
        1  Megabyte  (MB)  =  1,024  KB
        1  Gigabyte  (GB)  =  1,024  M
        1  Terabyte  (TB)  =  1,024  G

我们所说的单片机的的内存大小是说的是字节,而不是位。

        假设一个某个芯片有19根地址线:A0-A18,数据线是:D0-D15(16位,两个字节),他所能访问的地址的标号数就是2^19字节,512 KB个地址,512K*2 = 1024bit = 1M.接下来,我们对其存储器进行映射。

地址范围 0-512K
映射1 0-512K(0x0-0x80000)
映射2 1-512K(0x0-0x80000)
映射3 100k-612K
映射3 512K-1024K

存储器功能的划分(F1为例)

ST将4GB(2^32)地址空间分成8个块

ST的4GB的地址空间可以分成8个块,每个块为512MB。

具体分配如下:

1. 块0(Code(FLASH)):    0x00000000 ~ 0x1FFFFFFF(主要用于存储代码)
2. 块1(SRAM):                      0x20000000 ~ 0x3FFFFFFF
3. 块2(片上外设):                  0x40000000 ~ 0x5FFFFFFF(最重要)
4. 块3(FSMC Bank1&2): 0x60000000 ~ 0x7FFFFFFF
5. 块4(FSMC Bank3&4):      0x80000000 ~ 0x9FFFFFFF
6. 块5(FSMC寄存器):            0xA0000000 ~ 0xBFFFFFFF
7. 块6(没用到):                  0xC0000000 ~ 0xDFFFFFFF
8. 块7(Cortex M3内部外设):0xE0000000 ~ 0xFFFFFFFF

每个块都有512MB的地址空间,可以用来存放不同的程序、数据以及内核代码等。这种分块的方式方便操作系统和应用程序进行内存管理,提高系统的稳定性与性能。

二、寄存器映射(重要)

        寄存器是单片机内部一种特殊的内存,可以实现对单片机各个功能的控制。 

        简单来说:寄存器就是单片机内部的控制机构。

什么叫做寄存器映射?

        寄存器是特殊的存储器,给寄存器地址命名的过程,就叫做寄存器映射。

例如我们一个寄存器的地址是0x4001080C,我们给寄存器命名叫做GPIOA_ODR(寄存器名字),这个过程就叫做寄存器映射。

如何直接操作寄存器

*(unsigned int*)(0x4001080C) = 0XFFFF;

即GPIOA_ODR所有的位都是1,即PA0-PA15都是1。

定义一个名字后再操作

# define GPIO_ODR *(unsigned int *)(0X4001080C)

GPIO_ODR = 0XFFFF;

三、寄存器映射计算

问题一:寄存器地址怎么寻找并计算呢?

问题二:如何映射?

解决一

        为了方便编写代码及使用,我们寄存器地址分为三个部分:

1、总线基地址(BUS_BASE_ADDR)

2、外设基于总线基地址的偏移量(PERIPH_OFFSET)

3、寄存器相对与外设基地址的偏移量(REG_OFFSET)

寄存器地址=BUS_BASE_ADDR+PERIPH_OFFSET+REG_OFFSET

以F1为例,我们的总线基地址如下

总线 基地址 偏移量
APB1 0X4000 0000 0
APB2 0X4001 0000 0X1 0000
AHB 0X4001 8000

0X1 8000

APB1总线的基地址,也叫做外设的基地址(PERIPH_BASE)

此表的偏移量:是相对外设的基地址。

GPIO外设基地址及偏移量

所属总线 外设 基地址 偏移量

APB2

0X4001 0000

GPIOA 0X4001 0800 0X0800
GPIOB 0X4001 0C00 0X0C00
GPIOC 0X4001 1000 0X1000
GPIOD 0X4001 1400 0X1400
GPIOE 0X4001 1800 0X1800
GPIOF 0X4001 1C00 0X1C00
GPIOG 0X4001 2000 0X2000

此表的偏移量:是相对APB2外设基地址(APB2 PERIPH_OFFSET)偏移量

GPIO外设基地址及偏移量

所属总线 所属外设 寄存器 地址 偏移量

APB2

0X4001 0000

GPIO

0X4001 0800

GPIOA_CRL 0X4001 0800 0X00
GPIOA_CRH 0X4001 0804 0X04
GPIOA_IDR 0X4001 0808 0X08
GPIOA_ODR 0X4001 080C 0X0C
GPIOA_BSRR 0X4001 0810 0X10
GPIO_BRR 0X4001 0814 0X14
GPIO_LCKR 0X4001 0818 0X18

GPIO_ODR寄存器地址计算过程:

1.获取外设挂在哪个总线上面?查:系统结构图

2.获取总线的基地址,APB2总线基地址是:0X4001 0000

3.获取外设地址偏移量,GPIOA相对APB2总线偏移量是:0X800

4.获取寄存器地址偏移量,ODR相对GPIOA外设基地址的偏移量是0X0C。

寄存器地址=BUS_BASE_ADDR+PERIPH_OFFSET+REG_OFFSET

GPIO_ODR = 0X4001 0000+0X800+0X0C=0X4001 080C

解决二:

使用结构体可以很方便的实现对寄存器的映射

typdef struct

{

        _IO uint32_t CRL;

        _IO uint32_t CRH;

        _IO uint32_t IDR;

        _IO uint32_t ODR;

        _IO uint32_t BSRR;

        _IO uint32_t LCKR;

}GPIO_TypeDef;

整体映射:

# define GPIOA ((GPIO_TypeDef*)GPIOA_BASE)

取里边的地址:

&GPIOA->CRL:  0X4001 0800

&GPIOA->CRH:0X4001 0804

&GPIOA->IDR:  0x40010808

&GPIOA->ODR:0X4001 080C

实际应用:

GPIO->ODR= 0XFFFF;

猜你喜欢

转载自blog.csdn.net/zywcxz/article/details/131035001