LPC11XX.h头文件解析
部的寄存器进行一一对映的。为了方便讨论,先看一下LPC1114内部的Memory Map(内存地图)是怎么分配的,如下图所示。
从内存地图中可以看出,由于LPC1114是32位结构的,所以其寻址空间达到了4GB(从0x00000000~0xFFFFFFFF),且不管是什么模块,都统一编址在其中,而并不像51单片机那样,程序存储和数据存储是各自独立编址的。通过观察内存地图会发现,地址分配是分类的,即:从0x00000000~0x10002000的区域是内存区(包含了FLASH ROM和SRAM);从0x1FFF0000~0x1FFF4000的区域是引导区(即BOOT ROM区);从0x40000000~0x40080000的区域是APB设备区,它包含了除IO端口以外的所有外围设备资源;从0x50000000~0x50200000的区域是AHB设备区,它包含了所有的IO端口资源;从0xE0000000~0xE0100000区域是私有外围设备总线区;其它剩余区域为保留区,便于将来升级扩展。
刚才定义的结构体“SYSCON”所对映的设备,就是在内存地图中位于APB区内的system control模块部分(地址为0x40048000~0x4004C000)。为了便于讨论,下面把这部分的内容单独剔出来进行说明。下图给出了system control模块内所有寄存器的分布情况。
从上表中可以看出,因为system control模块的起始地址是0x40048000,所以它的基址就是0x40048000。这样它内部各寄存器的地址就可以以基址为参考点,用相对于基址的偏移量来进行描述。比如,在前面讨论时钟配置时用到的寄存器SYSPLLCLKSEL、MAINCLKSEL等,它们相对于基址的偏移地址就是0x040和0x070(查上表中的Address offset一列),而其绝对地址则是0x40048040和0x40048070(分别加上基址的值)。
我们知道,要访问CPU内部的硬件,最终只能通过它的地址进行访问,而我们对其进行的命名(如刚才的SYSPLLCLKSEL、MAINCLKSEL等)都要通过一种对映关系把它们联系起来。因为CPU不知道SYSPLLCLKSEL、MAINCLKSEL是什么,但它知道地址0x40048040、0x40048070的单元。而在高级语言中,直接使用地址不仅不直观,开发者还要费力去记住每个地址的寄存器功能,很不合适。为了适应高级语言的特点,我们就通过这种给寄存器命名,并让该名称对映到寄存器的实际地址的方式来处理。经过这样处理后,开发者就可以在程序中直接引用寄存器名称了,大大提高了程序的可读性,方便了开发。
从内存地图中可以看出,由于各设备的编址是分类的,所以使用高级语言中的“结构体”来处理这种名称与地址的对映关系是十分合适的。每一个结构体可对应一个分类,而分类中的寄存器就可以定义为这个结构体内的成员变量,各成员变量又严格对映到寄存器的实际地址。在前面示例部分的程序中,已经在头文件部分引入了这种结构体并进行了地址对映。
接下来再回到刚才定义的结构体“SYSCON”的讨论上来。从该结构体定义中可以看到,它内部定义的成员变量其实就是system control模块内的所有寄存器(见上表)。但是还没完,因为定义了“SYSCON”这个结构体只相当于对system control模块进行了“封装”(即进行了寄存器的按顺序命名),还没有对它进行地址的对映。
下面给出预定义部分中第三部分的内容,代码如下:
#define LPC_APB0_BASE(0x40000000UL)
#define LPC_AHB_BASE(0x50000000UL)
#define LPC_IOCON_BASE(LPC_APB0_BASE + 0x44000)
#define LPC_SYSCON_BASE(LPC_APB0_BASE + 0x48000)
#define SCS_BASE(0xE000E000UL)
#define LPC_SYSCON((LPC_SYSCON_TypeDef *) LPC_SYSCON_BASE)
#define LPC_IOCON((LPC_IOCON_TypeDef*) LPC_IOCON_BASE )
#define LPC_GPIO0_BASE(LPC_AHB_BASE+ 0x00000)
#define LPC_GPIO1_BASE(LPC_AHB_BASE+ 0x10000)
#define LPC_GPIO2_BASE(LPC_AHB_BASE+ 0x20000)
#define LPC_GPIO3_BASE(LPC_AHB_BASE+ 0x30000)
#define SysTick_BASE(SCS_BASE +0x0010UL)
#define LPC_GPIO0((LPC_GPIO_TypeDef*) LPC_GPIO0_BASE )
#define LPC_GPIO1((LPC_GPIO_TypeDef*) LPC_GPIO1_BASE )
#define LPC_GPIO2((LPC_GPIO_TypeDef*) LPC_GPIO2_BASE )
#define LPC_GPIO3((LPC_GPIO_TypeDef*) LPC_GPIO3_BASE )
#define SysTick((SysTick_Type*)SysTick_BASE)
可见,这部分又全是用define进行的宏定义。因这里只讨论与“SYSCON”结构体相关的内容,所以只需看第一、四、六行,其它部分暂时不作说明。前面说过,system control模块位于APB设备区,所以第一行先进行了APB设备区的基址定义,第四行又进行了SYSCON(即system control模块区)的基址定义。而真正进
- LWIP程序OPT.h头文件的各种定义(11-30)
- STM8单片机工程师之路三-.C和.H头文件的区别(11-29)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)