本书实例都是基于三星的S3C6410X处理器。由于S3C6410X有部分架构继承于S3C24XX系列,所以部分代码也能看到S3C24XX的影子。S3C6410X支持32位物理地址空间,这些地址空间分成两部分,一部分用于存储,另一部分用于外设。
S3C6410X处理器通过SPINE总线访问主存区,主存区的地址范围是0x0000_0000~0x6FFF_FFFF,分为四个区域,见表6-2。
表6-2 S3C6410X处理器的地址映射
外设区域通过PERI总线被访问,它的地址范围是0x7000_0000~0x7FFF_FFFF。这个地址范围的所有的特殊功能寄存器(SFR)都能被访问。S3C6410X处理器的主要外设如图6-3所示。
图6-3 S3C6410X处理器的主要外设
S3C6410X的外设地址在/arch/arm/mach-s3c64xx/include/mach/map.h中定义。
在Linux中必须将外设的物理地址映射成虚拟地址才能访问。地址映射方式可以采用固定地址映射方式,下面是几个固定地址映射的宏:
#define S3C_ADDR_BASE(0xF4000000)
#define S3C_ADDR(x)(S3C_ADDR_BASE+(x))
#define S3C_ADDR_CPU(x)S3C_ADDR(0x00500000+(x))
下面是一些S3C6410X内部控制器的地址映射定义:
#define S3C_VA_IRQ S3C_ADDR(0x00000000) /*irq控制器*/
#define S3C_VA_SYS S3C_ADDR(0x00100000) /*系统控制器*/
#define S3C_VA_MEM S3C_ADDR(0x00200000) /*内存控制器*/(www.xing528.com)
#define S3C_VA_TIMER S3C_ADDR(0x00300000) /*时钟单元*/
#define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /*看门狗*/
#define S3C_VA_UART S3C_ADDR(0x01000000) /*串口*/
另一种地址映射方式就是采用ioremap函数,具体见第4章。
当I/O寄存器与内存统一编址时,I/O寄存器也称为I/O内存。当I/O寄存器与内存分开编址时,I/O寄存器也称为I/O端口。S3C6410X采用I/O内存方式。在I/O内存资源的物理地址映射成核心虚拟地址后,理论上讲就可以像读写RAM那样直接读写I/O内存资源了。为了保证驱动程序的跨平台的可移植性,应该使用Linux中特定的函数来访问I/O内存资源,而不应该通过指向核心虚拟地址的指针来访问。例如在ARM平台上,读写I/O的函数,参见/arch/arm/include/asm/io.h以及/include/asm-generic/io.h。
原始的I/O内存读写函数如下:
void__raw_writew(u16 val,volatile void__iomem*addr);
u16__raw_readw(const volatile void__iomem*addr);
void__raw_writeb(u8 val,volatile void__iomem*addr);
u8__raw_readb(const volatile void__iomem*addr);
void__raw_writel(u32 val,volatile void__iomem*addr);
u32__raw_readl(const volatile void__iomem*addr);
下面的I/O内存函数在__raw_readl与__raw_writel函数基础上增加了内存屏障处理,以确保读写的安全性。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。