TongxinV / oneBook

记录自己的知识框架,有时写写BLOG CSDN博客地址

Home Page:https://blog.csdn.net/TongxinV

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

内核提供读写寄存器接口实现可移植

TongxinV opened this issue · comments

内核提供的读写寄存器接口实现可移植性

arm是IO与内存统一编址,其他平台如x86是IO与内存独立编址访问方式不一样,使用内核提供的寄存器读写接口具有可移植性

在文章随笔--Linux字符设备驱动开发基础前面写的驱动在静态映射操作寄存器,都用#define rGPJ0CON *((volatile unsigned int *)GPJ0CON)的方式来访问寄存器,这样的做法在驱动中并不是很好,因为这样的做法在不同平台的情况下不具有可移植性。现在写的驱动是在ARM平台下去写的,ARM属于内存和IO统一编址的,在读写寄存器的时候即为进行IO操作,进行IO操作是和读写内存是一样的(IO也有个地址),这就叫统一编址。但是还有另外一些CPU(像x86)是非统一编址的,这种CPU在进行IO操作时的方法跟进行内存的读写的方法是不一样的。那么在这种情况下就有一种问题,如果写的驱动不仅要求在ARM下能够运行,还要求在X86下也要能够运行,如果还用#define rGPJ0CON *((volatile unsigned int *)GPJ0CON)的方式显然是不合适的,需要进行比较大的修改。我们要怎样才能够使他能够具有很强的移植性呢?——内核已经帮我们想好了办法,即内核提供访问寄存器的读写接口(函数),使用这些函数具有可移植性。其实现的原理就是用条件编译,如下比较:

blog007

代码示例(静态映射):

...
#include <mach/regs-gpio.h>		//虚拟地址映射表
#include <mach/gpio-bank.h>	
#include <linux/io.h>
#include <linux/ioport.h>

#define GPJ0CON		S5PV210_GPJ0CON
#define GPJ0DAT		S5PV210_GPJ0DAT
...
    ...
    writel(0x11111111, GPJ0CON);
    writel(((0<<3) | (0<<4) | (0<<5)), GPJ0DAT);

...

代码示例(动态映射):

#include <linux/io.h>
#include <linux/ioport.h>
...
#define GPJ0CON_PA	0xe0200240

#define S5P_GPJ0REG(x)		(x)
#define S5P_GPJ0CON		S5P_GPJ0REG(0)
#define S5P_GPJ0DAT	        S5P_GPJ0REG(4)

static void __iomem *baseaddr;	// 寄存器的虚拟地址的基地址,用来保存 ioremap的返回值
...
    ...
    if (!request_mem_region(GPJ0CON_PA, 8, "GPJ0BASE"))
	return -EINVAL;
    baseaddr = ioremap(GPJ0CON_PA, 8);
	
    writel(0x11111111, baseaddr + S5P_GPJ0CON);
    writel(((0<<3) | (0<<4) | (0<<5)), baseaddr + S5P_GPJ0DAT);

...