Linux驱动入门(二)操作硬件

Linux驱动入门系列

Linux驱动入门(一)字符设备驱动基础

Linux驱动入门(二)操作硬件

Linux驱动入门(三)Led驱动

Linux驱动入门(四)非阻塞方式实现按键驱动

Linux驱动入门(五)阻塞方式实现按键驱动

Linux驱动入门(六)poll机制实现按键驱动

Linux驱动入门(七)使用定时器消除按键抖动

Linux驱动入门(二)操作硬件

一、通用做法

玩过单片机的朋友应该懂得如何操作寄存器

举个例子,例如现在想往寄存器地址0xFF223440写数据,在单片机编程中的做法如下

volatile unsigned int *reg = (unsigned int*)0xFF223440;
*reg = val;

在Linux中做法也是类似,只不过Linux不可以直接访问寄存器地址,而要经过映射后才能访问,下面开始介绍

ioremap

映射地址

/*
 * cookie:表示要映射的地址
 * size:表示要映射的地址范围
 */
ioremap(cookie,size)

例如上面要操作寄存器0xFF223440,在Linux的做法如下

volatile unsigned int *reg = ioremap(0xFF223440, 4);
*reg = val;

当然在映射前要先申请request_region(start,n,name)地址空间,不过这不是必须的

在映射完地址后,当驱动程序退出时,不再使用此地址,需要使用iounmap取消映射

iounmap

取消地址映射

/*
 * cookie:映射后的地址
 */
iounmap(cookie)

例如上面的例子中,在驱动程序退出时,需要调用

iounmap(reg);

在取消映射后,如果先前有申请地址空间,那么就需要释放申请的地址空间release_region(start,n)

寄存器读写

在上面的例子中,读写寄存器通过直接访问指针,而内核中提供了一套宏定义来读写寄存器

readb(c) //读8位
readw(c) //读16位
readl(c) ///读32位
writeb(v,c) //写8位
writew(v,c) //写16位
writel(v,c) //写32位

二、gpiolib

上面介绍的是通用的做法,可以访问和设置任意的寄存器

内核中对于gpio的设置,提供了更加简便的方法-gpiolib

gpiolib是一套对gpio的操作函数,有了这些函数,就可以简化对gpio进行操作,而不需要直接通过寄存器来操作

当然gpiolib仅限于操作gpio,如果要操作非gpio相关的寄存器(例如lcd控制器,摄像头控制器等),那么还是要使用上面讲的通用方法,下面开始介绍gpiolib

gpio.h

对于每一款芯片,大多在移植的时候都有对应一个gpio.h文件

对于每一款芯片,大多在移植的时候都有对应一个gpio.h文件

以三星平台的S5PV210为例,gpio.h位于arch\arm\mach-s5pv210\include\mach\gpio.h

其中定义了一系列的gpio相关的宏

S5PV210_GPA0(_nr)
S5PV210_GPA1(_nr)
S5PV210_GPB(_nr)
...

​ 可以使用这些宏定义,通过gpiolib提供的函数来操作gpio

gpiolib.c

gpiolib.c位于drivers\gpio\gpiolib.c,其中定义了一系列的gpio操作函数,gpio的操作函数需要搭配gpio.h中的宏定义使用

int gpio_request(unsigned gpio, const char *label)
void gpio_free(unsigned gpio)
int gpio_direction_input(unsigned gpio)
int gpio_direction_output(unsigned gpio, int value)
int gpio_get_value(unsigned gpio)
void gpio_set_value(unsigned gpio, int value)
int gpio_to_irq(unsigned gpio)
  • gpio_request

    申请gpio,在使用gpio前,应该先申请gpio,当然这并不是必须的

  • gpio_free

    释放gpio,用于释放被申请了的gpio

  • gpio_direction_input

    设置gpio为输入

  • gpio_direction_output

    设置gpio为输出,并设置gpio高低电平

  • gpio_get_value

    获取gpio的高低电平

  • gpio_set_value

    设置gpio的高低电平

  • gpio_to_irq

    获取gpio对应的外部中断

如果我们设置S5PV210的GPIOA0的第四个引脚为高电平,我可以这样做

/* 申请 */
gpio_request(S5PV210_GPA0(3), "m_gpio");

/* 设置 */
gpio_direction_output(S5PV210_GPA0(3), 1);

/* 不需要时释放 */
gpio_free(S5PV210_GPA0(3));

从上面的操作函数中,可以看到,gpio-lib仅支持设置gpio为输入或者输出,但要知道,有些gpio是可以复用成其他功能的(例如摄像头接口的gpio等),下面是从S5PV210的datasheet中截图的

在这里插入图片描述

可以看到GPE0-0不仅可以设置为Input(输入模式)和Output(输出模式),还可以复用为CAM_A_PCLK(摄像头接口A的像素时钟引脚)

那么如果没有其他的支持,我们就需要使用通用的方式来配置寄存器,为此,三星平台再提供了一套操作gpio的函数

三星平台提供的gpio-cfg

文件位于arch\arm\plat-samsung\include\plat\gpio-cfg.h

其中的操作函数分为三类,第一类配置gpio,第二类设置gpio引脚状态,第三类设置gpio的驱动强度

配置gpio

#define S3C_GPIO_INPUT	(S3C_GPIO_SPECIAL(0)) //输入
#define S3C_GPIO_OUTPUT	(S3C_GPIO_SPECIAL(1)) //输出
#define S3C_GPIO_SFN(x)	(S3C_GPIO_SPECIAL(x)) //复用功能

int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); //配置
unsigned s3c_gpio_getcfg(unsigned int pin); //获取配置

例如上述例子,如果要设置GPE0-0为摄像头接口A的像素时钟引脚,那么就这么配置

s3c_gpio_cfgpin(S5PV210_GPE0(0), S3C_GPIO_SFN(2));

设置引脚状态

#define S3C_GPIO_PULL_NONE	((__force s3c_gpio_pull_t)0x00) //悬空
#define S3C_GPIO_PULL_DOWN	((__force s3c_gpio_pull_t)0x01) //下拉
#define S3C_GPIO_PULL_UP	((__force s3c_gpio_pull_t)0x02) //上拉

int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);

设置引脚驱动强度

#define S5P_GPIO_DRVSTR_LV1	((__force s5p_gpio_drvstr_t)0x00)
#define S5P_GPIO_DRVSTR_LV2	((__force s5p_gpio_drvstr_t)0x01)
#define S5P_GPIO_DRVSTR_LV3	((__force s5p_gpio_drvstr_t)0x10)
#define S5P_GPIO_DRVSTR_LV4	((__force s5p_gpio_drvstr_t)0x11)

s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin);
s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);

三、总结

  • 使用通用的方法可以设置任意寄存器,只是比较麻烦
  • 使用gpiolib可以较为方便地配置gpio,但仅限于gpio,如果需要设置非gpio,还是需要使用通用地方法
  • 内核提供的gpiolib只能配置gpio为输入或者输出,其他功能(例如复用引脚,设置上下拉等)无法通过gpiolib设置,三星平台提供了另一套函数设置
  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值