地址映射就是将芯片上的存储器甚至I/O等资源与地址建立一一对应的关系。cortex-m3有32根地址线,所以它的寻址空间为4GB。ARM公司在设计这块芯片时,规定了把0x4000,0000至0x5FFF,FFFF(共512mb)的地址分配给了片上外设。也就是说我们通过读写这些地址就能够操纵外设的工作状态。
在stm32f10x.h这个头文件里面完成的最重要的功能之一就是把STM32的所有寄存器进行了地址映射,也就说这个文件存在大量的宏定义,这些宏定义将晦涩难记的地址变成了利于记忆的标识符。比如说下面这一段:
#define GPIOC_BASE (APB2PERIPH_BASE+0X1000)
#define APB2PERIPH_BASE (PERIPH_BASE+0X10000)
#define PERIPH_BASE ((uint32_t) 0x40000000)
对于我们这里的代码而言,PERIPH_BASE就是片上外设映射地址的起始位置。其中APB2PERIPH_BASE就是APB2总线外设基地址。APB2?是这样的,在STM32芯片中,它有AHB总线,APB2总线,APB1总线,STM32上不同的外设是挂载在不同的总线上的。对于GPIO,串口1,ADC以及部分定时器来说他们是挂载在APB2总线上的。至于哪些片上外设挂载的总线是哪个,这取决于芯片设计,可以根据芯片文档来查看,比如我们这篇文章的文首处的图片即指明了stm32各外设与总线的关系。
这里碎片化的介绍某些知识点,看下面的代码:
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;
#define _O volatile
#define _IO volatile
这段代码给GPIO的配置寄存器对象抽象为了一个struct,在C语言中,结构体内变量的存储空间是连续的。也就是说,如果我们假如定义了一个GPIO_TypeDef对象a,它的首地址是0x4001,1000的话,那么这个对象中CRH成员的首地址就是0x4001,1000+0x04。
在stm32f1ox.h头文件中,GPIOA-GPIOG就是利用GPIO_TypeDef结构体定义的。如下代码所示:
#define GPIOA ((GPIO_TypeDef*) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef*) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef*) GPIOC_BASE)