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

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

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

在文章随笔–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);

...
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值