linux 标准GPIO 驱动模型—version1

来源:互联网 发布:怪物猎人x数据库多玩 编辑:程序博客网 时间:2024/05/16 05:06

转载地址:http://blog.csdn.net/xuefeng_apple/article/details/48230885

前言:本文主要介绍gpio driver实现基本方法,具体实例在后续的文章中继续介绍

Index:

1、bus 概念介绍

2、Device driver匹配过

3、GPIO driver 实现标准框架图

4、GPIO driver 细化实现

5、GPIO 上层应用


1、bus 概念介绍




Busplatform总线):总线是CPU和一个或多个设备之间信息交互的通道。而为了方便模型的抽象,所有的设备都应连接到总线上

Devicegpio设备):抽象系统中所有的硬件设备,描述它的名字、属性、从属的Bus

Device Drivergpio驱动):Linux设备模型用Driver抽象硬件设备的驱动程序,它包含设备初始化、ops相关的接口实现。


2、Device driver匹配过程


系统启动Bus initkernel_init()à do_basic_setup()à driver_init()àplatform_bus_init()


设备注册到内核:platform_device_registeràplatform_device_add挂在platform bus

驱动注册到内核:platform_driver_registeràdriver_register-àbus_add_driverà

driver_attachàbus_for_each_dev(drv->bus,NULL,drv,__driver_attach)à__driver_attach

àdriver_match_device--àdrv->bus->match==platform_match()->

strncmp(pdev->name,drv->name, BUS_ID_SIZE)


如果相符就调用platform_drv_probe()->driver->probe(),如果probe成功则绑定该设备到该驱动

其实注册dev 时候也会prove driver.


[html] view plain copy
  1. static int platform_match(struct device *dev, struct device_driver *drv)  
  2. {     
  3.     struct platform_device *pdev = to_platform_device(dev);  
  4.     struct platform_driver *pdrv = to_platform_driver(drv);  
  5.     ……  
  6.         printk ("platform_match--driver_match_device-pdev->name=%s,drv->name=%s;\n", pdev->name, drv->name);  
  7.     return (strcmp(pdev->name, drv->name) == 0);  
  8. }  

实际举例:

[html] view plain copy
  1. static struct platform_device codec_device_test0 = {  
  2.     .name       = "test-codec-test0",  
  3.     .id     = 0,          
  4. };  
  5. static struct platform_device *alsa_devices_test[] __initdata =  
  6. {  
  7. &codec_device_test0,  
  8. };  
  9. platform_device_register (alsa_devices_test);  
[html] view plain copy
  1. static struct platform_driver mdp_codec_driver = {  
  2.     .driver     = {  
  3.         .name       = “test-codec-test0",   
  4.         .owner      = THIS_MODULE,  
  5.         .of_match_table = of_match_ptr(mdp_audio_codec_dt_match),  
  6.     },  
  7.     .probe      = mdp_codec_device_probe,  
  8.     .remove     = mdp_codec_device_remove,  
  9. };  
  10. platform_driver_register(&mdp_codec_driver);  

注:经过上面的dev,drvregister platform就可以match


3、GPIO driver 实现标准框架图

GPIOLIB:

Driver 具体实现call pinctrl_request_gpio(/3.10.23/drivers/gpio/gpio-pl061.c)

gpiochip_add_pin_rangeàpinctrl_find_and_add_gpio_range


Device Tree:

/3.10.23/drivers/of/souce files

/3.10.23/arch/arm/boot/dts/格式组织reg

/3.10.23/Documentation/devicetree/bindings/gpio/gpio.txt


Machine driverpin ctrl下级控制,具体没有查看


4、GPIO 细化实现

    在LINUX里实现了对GPIO操作的统一接口,这个接口实则上就是GPIO驱动的框架,具体的实现文件为gpiolib.c


 编译配置:

//THEALE/RedLion/3.10.23/drivers/gpio/Kconfig

//THEALE/RedLion/3.10.23/.config

[html] view plain copy
  1. CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y  
  2. CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y  
  3. CONFIG_GPIO_DEVRES=y  
  4. CONFIG_GPIOLIB=y  
  5. CONFIG_GPIO_SYSFS=y  


[html] view plain copy
  1. menuconfig GPIOLIB  
  2.         bool "GPIO Support"  
  3.         depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB  
  4.         help  
  5. config OF_GPIO  
  6.         def_bool y  
  7.         depends on OF  //device tree  
  8. config GPIO_SYSFS  
  9.         bool "/sys/class/gpio/... (sysfs interface)"  
  10.         depends on SYSFS  
  11.         help  




gpio_desc结构体中:

gpio_chip指向硬件层的GPIO

flags为一标志位,用来指示当前GPIO是否已经占用

label是一个字符串指针,用来作说明

gpio_chip结构体:

ngpio指定个数

base为起始的GPIO

gpiochip_add注册一个gpio_chip对应的gpio_desc到全局数组gpio描述符中。一个描述符对应一个GPIO

//THEALE/RedLion/3.10.23/drivers/gpio/gpiolib.c

[html] view plain copy
  1. struct gpio_desc {  
  2.         struct gpio_chip        *chip;  
  3.         unsigned long           flags;  
  4.         const char              *label;  
  5. };  

GPIO 数据结构//THEALE/RedLion/3.10.23/include/asm-generic/gpio.h

[html] view plain copy
  1. Struct gpio_chip {    
  2.         …….  
  3.  int                     (*request)(struct gpio_chip *chip,  
  4.                                                 unsigned offset);  
  5.         void                    (*free)(struct gpio_chip *chip,  
  6.                                                 unsigned offset);  
  7.         int                     (*get_direction)(struct gpio_chip *chip,  
  8.                                                 unsigned offset);  
  9.         int                     (*direction_input)(struct gpio_chip *chip,  
  10.                                                 unsigned offset);  
  11.         int                     (*get)(struct gpio_chip *chip,  
  12.                                                 unsigned offset);  
  13.         int                     (*direction_output)(struct gpio_chip *chip,  
  14.                                                 unsigned offset, int value);  
  15.         int                     (*set_debounce)(struct gpio_chip *chip,  
  16.                                                 unsigned offset, unsigned debounce);  
  17.         void                    (*set)(struct gpio_chip *chip,  
  18.                                                 unsigned offset, int value);  
  19.         int                     (*to_irq)(struct gpio_chip *chip,  
  20.                                                 unsigned offset);  
  21.         int                     base;  
  22.         u16                     ngpio;  
  23.         ………  
  24. }  

申请和释放GPIO资源:

Extern intgpio_request(unsignedgpio, const char *label);

Extern voidgpio_free(unsignedgpio);


设置GPIO口方向的操作:

Extern intgpio_direction_input(unsignedgpio);

Extern intgpio_direction_output(unsignedgpio, int value);


设置GPIO口高低电平值操作:

Extern intgpio_get_value_cansleep(unsignedgpio);

Extern voidgpio_set_value_cansleep(unsigned gpio, int value);

Extern int __gpio_get_value(unsigned gpio);

Extern void __gpio_set_value(unsigned gpio, intvalue);


检测GPIO是否有效及中断

 int gpio_is_valid(int number); 

 int gpio_to_irq(unsigned gpio); àrequest_irq()free_irq()



5GPIO上层应用

//THEALE/RedLion/3.10.23/Documentation/gpio.txt .“Paths in Sysfs”


int gpio_export(unsigned gpio, bool direction_may_change);

void gpio_unexport(); 

/sys/class/gpio目录下的三种文件: 

  --export/unexport文件

  --gpioN指代具体的gpio引脚

 --gpio_chipN指代gpio控制器


 echo 19 > export ----/sys/class/gpio/gpio19--》

      direction

value 

edge 

echo 19 > unexport—》注销


GPIOcontrol (read_only)

/sys/class/gpio/gpiochipN/

           "base" ... same as N, the firstGPIO managed by this chip

           "label" ... provided fordiagnostics (not always unique)

           "ngpio" ... how many GPIOsthis manges (N to N + ngpio - 1)


测试Demo 程序:

[html] view plain copy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <sys/stat.h>  
  4. #include <linux/fs.h>  
  5. #include <fcntl.h>  
  6. #include <string.h>  
  7. #include <termios.h>  
  8. #include <sys/ioctl.h>  
  9.   
  10. int main(int argc, char **argv)  
  11. {  
  12.     int Mgpio_fd = -1;  
  13.     char Mgpio_on[] = "1";  
  14.     char Mgpio_num[]="110";  
  15.     char Mgpio_dir[]="out";  
  16.   
  17.     printf("test gpio start!\n");  
  18.     Mgpio_fd = open("/sys/class/gpio/export", O_WRONLY);  
  19.     write(Mgpio_fd, Mgpio_num, strlen(Mgpio_num));  
  20.     close(Mgpio_fd);  
  21.   
  22.     Mgpio_fd = open("/sys/class/gpio/gpio110/direction", O_RDWR);  
  23.     write(Mgpio_fd, Mgpio_dir, strlen(Mgpio_dir));  
  24.     close(Mgpio_fd);  
  25.   
  26.     Mgpio_fd = open("/sys/class/gpio/gpio110/value", O_RDWR);  
  27.     write(Mgpio_fd, Mgpio_on, strlen(Mgpio_on));  
  28.     close(Mgpio_fd);  
  29.   
  30.     Mgpio_fd = open("/sys/class/gpio/unexport",O_WRONLY);  
  31.     write(Mgpio_fd, Mgpio_num, strlen(Mgpio_num));  
  32.     close(Mgpio_fd);  
  33.   
  34.     printf("test gpio end!\n");  
  35.     return 0;  


原创粉丝点击