linux内核中GPIO的使用(一)--IO内存

一、相关概念
使用IO内存将物理地址映射为虚拟地址,再通过对虚拟地址的操作来控制硬件。所谓的IO内存是指一种编址方式,不同cpu平台使用的编址方式不同,一种是“IO内存”方式,也叫统一编址方式,是指内存和外设的地址是在同一个地址空间上的,如:ARM、powerpc 、MIPS等平台;另一种是“IO端口”方式,也叫独立编址方式,是指内存的地址空间和外设的地址空间是分开的,如x86平台。在嵌入式系统中,可以通过查看两个文件中的内容来确认是哪一种编址方式:/proc/iomem/proc/ioports,哪一个文件有内容就表示该平台使用哪一种编址方式。

二、程序设计思路
驱动安装—>申请IO内存资源—>物理地址的映射—>得到虚拟地址—>访问虚拟地址—>控制外设硬件
驱动卸载—>解除地址映射—>释放IO内存资源
用到的函数有:
request_mem_region()、ioremap()、release_mem_region()、iounmap()

三、程序设计与分析
1)申请IO内存资源

        struct resource * request_mem_region( resource_size_t start, resource_size_t n, const char *name)
        参数分析:
        resource_size_t start:IO内存的开始地址,该地址是物理地址;
        resource_size_t n:要申请的IO内存资源的大小,单位为字节;
        const char *name:给所申请的IP内存资源取一个名字;
        返回值:
            申请成功,返回一个struct resource类型的指针;
            申请失败,返回NULL

2)释放IO内存资源

        void release_mem_region(resource_size_t start, resource_size_t n)
        参数分析:
        resource_size_t start:IO内存的开始地址,该地址是物理地址;
        resource_size_t n:要申请的IO内存资源的大小,单位为字节;

3)IO内存映射(物理地址—>虚拟地址)

        void __iomem *ioremap(phys_addr_t offset, unsigned long size)
        参数分析:
        phys_addr_t offset:准备映射的物理地址空间的开始地址            
        unsigned long size:要映射的物理地址空间的大小,单位为字节
        返回值:
            映射成功,返回一个虚拟地址
            映射失败,返回NULL

4)IO内存映射的解除

        void iounmap(volatile void __iomem *addr);
        参数分析:
            volatile void __iomem *addr:前面映射得到的虚拟地址

四、简单的实例
简单的LED驱动,实现对基于S5PV210平台的LED灯控制,所用寄存器:GPJ2CON(0xe0200280)、GPJ2DAT(0xe0200284),主要代码如下:

static int * GPJ2CON_VA;    /*定义全局变量*/
static int * GPJ2DAT_VA;
static struct resource * gpio_led_source; 
.....

在驱动的初始化函数static int __init leddev_init(void)中添加相关代码:

        gpio_led_source = request_mem_region(0xe0200280, 8, “GPIO_LED”);
        if(gpio_led_source == NULL)     
        {
            printk("led_request_mem_region error!\n");
            goto err_led_request_mem_region;   /*出错处理*/
        }
        GPJ2CON_VA = ioremap(0xe0200280, 8);  
        if(GPJ2CON_VA == NULL)
        {
            printk("led ioremap error!\n");
            goto err_led_ioremap;             /*出错处理*/
        }
        GPJ2DAT_VA = GPJ2CON_VA + 1;          /* GPJ2CON和GPJ2DAT的地址刚好相邻*/

        *GPJ2CON_VA &= ~0xffff;           /*initial led GPIO*/
        *GPJ2CON_VA |= 0x1111;
        *GPJ2DAT_VA |= 0xf;
        printk("GPIO initial success!\n");

在驱动的退出函数static int __exit leddev_exit(void)中:

        iounmap(GPJ2CON_VA);               /*解除IO映射*/
        release_mem_region(0xe0200280, 8); /*释放IO内存资源*/
        unregister_chrdev_region(MKDEV(leddev_Major, leddev_Minor), 1);             /*注销设备号*/
        cdev_del(&ledodev);                /*从内核中删除设备 */
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值