Linux GPIO驱动 - 硬件及硬件抽象层

原创 2015年11月17日 18:30:58

在很多的SOC芯片里,GPIO硬件接口都是和其它硬件接口共用Pin脚,然后通过特定的寄存器去设置Pin使用时的类型。比如目前手上的项目使用的是Marvell的SOC芯片,该芯片上有50个多功能Pin脚(MPP:Multi-Purpose Pins),每个Pin都可以配置成不同的功能。SOC提供了7个32位的寄存器用来配置MPP Pin的类型,寄存器的每4位对应一个Pin,一个寄存器控制可以8个Pin.当MPP Pin被设置成GPIO Pin后,就可以按照GPIO Pin的方式来使用该Pin脚,比如input/output和high/low的设置。

硬件抽象层负责把GPIO控制器注册到GPIO通用层,通过调用gpiochip_add()把表示GPIO控制器的gpio_chip注册到gpiolib中。所以在注册gpio_chip之前,要对该结构体进行初始化。在mv_gpio.c中可以看到,label用来标识GPIO控制器,direction_input/direction_output用来设置GPIO Pin的方向,get/set用来读写GPIO Pin的值,而request用来获取一个空闲的GPIO Pin,base和ngpio分别标识该控制器的起始Pin和Pin的总数量。

  static struct gpio_chip mv_gpiochip = {
.label = "mv_gpio",
.direction_input= mv_gpio_direction_input,
.get = mv_gpio_get_value,
.direction_output= mv_gpio_direction_output,
.set = mv_gpio_set_value,
.request = mv_gpio_request,
.base = 0,
.ngpio = MV_GPP_MAX_PINS,
.can_sleep = 0,
};

mv_gpio_direction_input用来设置GPIO Pin为input模式,函数的调用路径为mv_gpio_direction_input()->_set_direction()->mvGppTypeSet()->gppRegSet()。在_set_directon里面,会先对要设置的Pin Num做一些处理,因为总共有50个GPIO Pin可用,所以需要2组32位的寄存器来控制,所以pin>>5就是算出该Pin是属于第一组,还是属于第二组。mask的值就是算出该Pin属于寄存器的第几个bit。然后通过mvGppTypeSet函数里面的gppRegSet把对应的值写到特定的寄存器中。

static inline void __set_direction(unsigned pin, int input)
{
u32 grp = pin >> 5;
u32 mask = (1 << (pin & 0x1F));

if (input)
mvGppTypeSet(grp, mask, MV_GPP_IN & mask);
else
mvGppTypeSet(grp, mask, MV_GPP_OUT & mask);
}

mv_gpio_direction_output用来设置GPIO Pin为output模式,因为GPIO Pin在output模式下可以设置该Pin脚的值,所以该函数在设置Pin脚方向的同时可以设置输出的值。函数调用路径为mv_gpio_direction_output->_set_level()->mvGppValueSet()->_set_direction()->mvGppTypeSet()。从函数执行的路径可以看出,是先设置GPIO的值,然后再设置GPIO的方向。这个顺序比较重要,因为在不知道默认值得情况下,先设置GPIO为输出模式,默认的值可能会引起异常,在之前的项目上就碰到过这种问题。

      static void __set_level(unsigned pin, int high)
{

u32 grp = pin >> 5;
u32 mask = (1 << (pin & 0x1F));

if (high)
mvGppValueSet (grp, mask, mask);
else
mvGppValueSet (grp, mask, 0);
  

}

mv_gpio_set_value用来设置GPIO输出的值,所以该函数直接调用_set_level()把值写到GPIO的输出寄存器里面。而对于mv_gpio_get_value,读取的值分两种情况,即输出模式的值和输入模式的值。对于输出模式,直接读取对应寄存器的值就可以了。而对于输入模式,由输入寄存器和一个极性寄存器共同表示该Pin脚的值,当极性寄存器对应的Pin脚位为1时,该Pin实际的值跟输入寄存器里面的值相反,当极性寄存器对应的Pin脚位为0时,该Pin实际的值与输入寄存器里面的值一致。
  static int mv_gpio_get_value(struct gpio_chip *chip, unsigned pin)
{
u32 val;
u32 grp = pin >> 5;
u32 mask = (1 << (pin & 0x1F));

if (MV_REG_READ(GPP_DATA_OUT_EN_REG(grp)) & mask)
val = mvGppValueGet(grp, mask) ^ mvGppPolarityGet(grp, mask);
else
val = MV_REG_READ(GPP_DATA_OUT_REG(grp));

return (val >> (pin & 31)) & 1;
}

mv_gpio_request用来申请一个空闲的GPIO Pin,在该项目的平台上直接返回一个0值,具体的申请功能由gpio通用层实现。

理解和使用Linux的硬件抽象层HAL

理解和使用Linux的硬件抽象层HAL 作者:刘旭晖 Raymond转载请注明出处Email:colorant@163.com BLOG:http://blog.csdn.net/colorant/主...
  • colorant
  • colorant
  • 2008年07月04日 14:47
  • 15387

Linux GPIO驱动结构

GPIO驱动结构 根据上图,在Linux中,会在gpiolib.c中定义一个 ARCH_NR_GPIOS 大小的数组static struct gpio_desc gpio_desc[ARCH_NR...
  • encourage2011
  • encourage2011
  • 2016年12月31日 15:30
  • 4636

linux驱动开发(一)—GPIO驱动框架

前言          GPIO驱动是Linux驱动开发中最基础、但却是很常用、很重要的驱动。比如你要点亮一个LED灯、键盘扫描、输出高低电平等等。而Linux内核的强大之处在于对最底层的GPIO硬...
  • zengxianyang
  • zengxianyang
  • 2016年01月26日 20:18
  • 5509

<9>编写硬件抽象层模块接口

转载来自:http://book.2cto.com/201210/6727.html 每一个硬件抽象层模块在内核中都对应有一个驱动程序,硬件抽象层模块就是通过这些驱动程序来访问硬件设...
  • qq_20678703
  • qq_20678703
  • 2015年11月26日 16:27
  • 388

linux 标准GPIO 驱动模型—version1

学习培训中
  • xuefeng_apple
  • xuefeng_apple
  • 2015年09月05日 22:28
  • 1562

LinuxGPIO驱动使用其实很简单

Author:DriverMonkey Mail:bookworepeng@Hotmail.com Phone:13410905075 QQ:196568501 本文资料主要来自互联网,并通...
  • peng654321
  • peng654321
  • 2014年02月28日 13:53
  • 6432

GPIO的驱动模型——linux

一、概述 GPIO是嵌入式系统最简单、最常用的资源了,比如点亮LED,控制蜂鸣器,输出高低电平,检测按键,等等。GPIO分输入和输出,在davinci linux中,有关GPIO的最底层的寄存器...
  • bytxl
  • bytxl
  • 2015年12月17日 08:52
  • 701

LINUX之GPIO驱动及接口使用

打算跟着友善之臂的《mini2440 Linux移植开发指南》 见 http://www.linuxidc.com/Linux/2011-06/37904.htm 来做个LED驱动,虽然LED的原...
  • s762888517
  • s762888517
  • 2013年06月21日 10:59
  • 5545

嵌入式项目代码结构的分层——HAL(硬件抽象层)、FML(功能模块层)、APL(应用程序层)

http://www.cnblogs.com/hustlzp/ http://hustlzp.com/ 一、遇到的问题   在“Zigbee之旅”系列博文中,每写一篇笔者都会编写...
  • wzk456
  • wzk456
  • 2015年05月13日 10:02
  • 932

例说Android 硬件抽象层

Android系统从宏观上可以看成一个图形系统,类似于QT,迷你GUI等开源的图形用户界面系统。但是android作为手机软件包,它还具有很多的其他功能是QT、MINIGUI不具备的,比如电话、定位、...
  • seek_0380
  • seek_0380
  • 2016年01月05日 12:50
  • 1580
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux GPIO驱动 - 硬件及硬件抽象层
举报原因:
原因补充:

(最多只允许输入30个字)