1.存储器映射
STM32F1的系统结构
存储器映射
STM32F1的存储器的映射
存储器映射是指把芯片中或芯片外的FLASH,RAM,外设,BOOTBLOCK等进行统一编址。即用地址来表示对象。这个地址绝大多数是由厂家规定好的,用户只能用而不能改。用户只能在挂外部RAM或FLASH的情况下可进行自定义。
从系统结构图中我们可以看出,所有内部设备都是AHB System Bus上,AHB系统总线又分成两个连接的桥,APB1的操作速度限于36MHZ,APB2的操作速度是全速(最高72MHZ)可以很清晰的从图中看出每个桥连接的内部设备。
寄存器(GPIOX)组起始地址
我们以GPIOA为例子。首先我们得明确一点:GPIOA是挂载在APB2上,APB2是从AHB系统总线中分出来的。
从stm32f10x.h头文件中,我们可以得到一些程序段:
typedef unsigned int uint32_t;//说明CRL等寄存器是十六位的。
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;
首先我们明确GPIO_TypeDef是一个结构体变量。
下面的程序段最好从下往上看更好理解。
#define PERIPH_BASE((uint32_t)0x40000000)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
PERIPH_BASE 是外设基地址,为了便于我们可以把这个比作是AHB系统总线的地址,那么APB2的地址就是在外设基地址的基础上加上偏移量。由程序段看出来偏移量是0x10000,同样的理解。GPIOA的地址就是在APB2的地址的地址基础上加上一个偏移地址,由程序段中可以看出是0x800。所以我们可以得到GPIOA的起始地址地址是0x4000_0000+0x1_0000+0x0800 = 0x4001_0800。
从STM32的中文参考手册中,我们看到CRL、CHL、IDR、ODR、BSRR、BRR、LCKR的偏移量都是004H。
因为CRL、CHL、IDR、ODR、BSRR、BRR、LCKR寄存器都定义的是16位的地址,所以定义32的地址需要
这么理解:一个地址存储八位信息,(char一个字节是八位最大的整数是2^8-1)比如:0x4001_0800存储8位的信息,0x4001_0801存储8位信息......0x4001_0804存储8位信息。一共存储32位信息。GPIOx的某一位的CRL需要4个位(两个位控制模式,两个位控制速度)来控制。4*8(CRL只控制低8位)=32。
因此GPIOA各个寄存器的实际地址
寄存器 偏移地址 实际地址=基地址+偏移地址
GPIOA->CRL 0x00 0x40010800+0x00
GPIOA->CRH; 0x04 0x40010800+0x04
GPIOA->IDR; 0x08 0x40010800+0x08
GPIOA->ODR 0x0c 0x40010800+0x0c
GPIOA->BSRR 0x10 0x40010800+0x10
GPIOA->BRR 0x14 0x40010800+0x14
GPIOA->LCKR 0x18 0x40010800+0x18
2.bit-band理解
Bit Banding功能是相对于以往能够进行bit操作的单片机而言的。通过Bit Banding功能可以像51单片机的bit操作一样。MCS51可以简单的将P1口的第2位独立作:P1.2=0;P1.2=1 就是这样把P1口的第三个脚(BIT2)置0或置1了。而现在STM32的位段、位带别名区就为了实现这样的功能。只不过他是为需要操作的地址(1字节)的每一个位(共8位)起个别名,分别对应别名区的一个字(word)。也就是别名区的大小是Bit Band的32倍。这样,32MB的别名区地址的操作,就是对相应Bit Band区的位的操作。Bit Banding功能是相对于以往能够进行bit操作的单片机而言的。
和bit-bind有关的寄存器
STM32有两个Bit Band区域,分别是:
0x2000 0000——0x2010 0000:该地址是STM32的SRAM低1MB的地址区域;
0x4000 0000——0x4010 0000:该地址是STM32的Peripherals低1MB的地址区域;
另外,STM32还有两个对应的Bit Band区域的别名区,分别是:
0x2200 0000——0x23FF FFFF:共32MB的空间,对应相应1MB的每一个位;
0x4200 0000——0x43FF FFFF:共32MB的空间,对应相应1MB的每一个位;
接下来的问题是如何确定Bit Band区字节的位所对应的那个别名区的字(word)。Bit Band区和别名区是一一对应的,具体的公式为:
bit_word_addr=bit_band_base+ (byte_offset×32) + (bit_number×4);
bit_band_base:32MB别名区首地址;
byte_offset:1MB位段区偏移量,即为bit-band 区中包含目标位的字节的编号;
bit_number:位段中目标位的位位置(0-7);
举个例子(通过别名区访问地址):
1、想操作SRAM中Bit Band区地址为 0x2000 0018字节的第2位
计算别名区对应子地址:0x2200 0000 +(18*32)+(2*4) = 0x2200 0248
所以,对0x2200 0248地址的操作,就是对0x2000 0018字节的第2位进行操作;
注意:别名字的位[31:1]在 bit-band 位上不起作用。写入 0x01 与写入 0xFF 的效果相同。写入0x00 与写入0x0E 的效果相同。
好了,整理了大概有5个小时,有部分是参考:
【疑问】
可以bit-bind的区域是:0x2000_0000-0x2010_0000 和0x4000_0000-0x4010_0000。具体是哪些寄存器,在头文件怎么实现的?比如是0x40010800+0x0c是PAout(); 其他的寄存器是怎么实现的?