驱动学习之gpiolib的建立过程

简介:

1:gpiolib的学习重点

(1)gpiolib的建立过程:gpiolib和虚拟地址映射类似,也是需要一个建立

过程的,因此在学习的时候,我们需要明白gpiolib是什么时候建立的,建立函数在哪被调用的。

(2)gpiolib的使用方法:申请、使用、释放

(3)gpiolib的架构:涉及哪些目录的哪些文件

2:什么是gpiolib,为什么需要使用gpiolib

linux中从2.6.35以后就开始有gpiolib库了,gpiolib的作用是对所有的gpio实行统一管理,因为驱动在工作的时候,会出现好几个驱动共同使用同一个gpio的情况;这会造成混乱。所以内核提供了一些方法来管理gpio资源;


3:gpiolib的初始化函数

在我们的mach-smdkc110.c文件中的

smdkc110_map_io

s5pv210_gpiolib_init  这个函数是gpiolib的初始化函数

smdkc110_map_io这个函数的调用过程,在我们分析静态映射的时候已经分析了。

4结构体struct s3c_gpio_chip

1
2
3
4
5
6
7
8
9
10
11
12
struct  s3c_gpio_chip
  {
     struct  gpio_chipchip;
     struct  s3c_gpio_cfg*config;
     struct  s3c_gpio_pm*pm;
     void  __iomem*base;
     inteint_offset;
     spinlock_t lock;
     #ifdef CONFIG_PM
     u32pm_save[7];
     #endif
};

(1)这个结构体在arch/arm/palt-samsung/include/plat/gpio-core.h中

(2)一个s3c_gpio_chip结构体类型的变量就可以用来描述一个gpio端口(注意这里是一个端口,而不是一个IO口,一个端口里面可以有多个IO口(一般是一个端口有8个IO))

(3)需要struct gpio_chip结构体中的元素

const char *label;

这个元素是用来记录当前IO坐在的IO端口的名字,比如IO口GPA0.0所在的IO端口就是GPA0

(4)int base;  

当前IO口所属的IO端口的编号,我们的gpiolib中 记录IO的方法是通过记录每一组IO的端口基础编号,然后通过一个IO的端口就在这个基准端口上叠加即可。

比如:

端口GPA0共有8个IO,IO口编号为0 -7,那么基准号就是0,也就是base = 0;

端口GPA1共有4个IO,IO口编号为8-11,那么基准号就是8,也就是base = 8;

5:s5pv210_gpio_4bit

(1)s5pv210_gpio_4bit是一个s3c_gpio_chip类型的结构体数组。

(2)将所有的gpio的.chip结构体中的一些元素初始化,这个数组的所有元素是与数据手册中的所有gpio是一一对应的。

(4)分析可知,这个数组就是对当前MPU中的所有的IO端口和每个端口的IO口进行了统一的描述,有了这个数组, 我们就知道当前开发板有多少个端口,有多少个IO口,以及每个IO口的编号。


6:s5pv210_gpiolib_init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__init  int  s5pv210_gpiolib_init( void )
{
     struct  s3c_gpio_chip *chip = s5pv210_gpio_4bit;
     int  nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
     int  i = 0;
     for  (i = 0; i < nr_chips; i++, chip++)
      {
         if  (chip->config == NULL)
         chip->config = &gpio_cfg;
         if  (chip->base == NULL)
         chip->base = S5PV210_BANK_BASE(i);
     }
     samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
 
     return  0;
}



(1)通过上面的分析可知,s5pv210_gpiolib_init这个函数的作用是将我们开发板中所有GPIO的端口进行一个配置,并且为所有GPIO端口分配一个基准端口的虚拟地址,通过这个基准地址就能得到这组端口中所有IO口的寄存器的地址。

(2)我们之前讲过,在我们的s5pv210_gpio_4bit这个数组中绑定了开发板中所有IO口的信息,int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);得到我们s5pv210_gpio_4bit数组的元素个数,然后调用samsung_gpiolib_add_4bit_chips这个函数,将开发板中的所有信息向我们的系统进行注册,这样系统就能知道当前系统中的所以IO口的信息。

7:samsung_gpiolib_add_4bit_chips

1
2
3
4
5
6
7
8
void  __init samsung_gpiolib_add_4bit_chips( struct  s3c_gpio_chip *chip, int  nr_chips)
{
     for  (; nr_chips > 0; nr_chips--, chip++)
      {
         samsung_gpiolib_add_4bit(chip);    //这里的chip指针+1实际上加的是一个元素
         s3c_gpiolib_add(chip);
     }
}

(1)经过分析,发现samsung_gpiolib_add_4bit内部其实并没有做gpiolib的注册工作,而是还在做填充,填充的是每一个GPIO被设置成输入模式/输出模式的操作方法。

(2)s3c_gpiolib_add

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
__init  void  s3c_gpiolib_add( struct  s3c_gpio_chip *chip)
{
     struct  gpio_chip *gc = &chip->chip;
     int  ret;
     BUG_ON(!chip->base);
     BUG_ON(!gc->label);
     BUG_ON(!gc->ngpio);
     spin_lock_init(&chip->lock);
     if  (!gc->direction_input)
     gc->direction_input = s3c_gpiolib_input;
     if  (!gc->direction_output)
     gc->direction_output = s3c_gpiolib_output;
     if  (!gc->set)
     gc->set = s3c_gpiolib_set;
     if  (!gc->get)
     gc->get = s3c_gpiolib_get;
     #ifdef CONFIG_PM
     if  (chip->pm != NULL) 
     {
         if  (!chip->pm->save || !chip->pm->resume)
         printk(KERN_ERR  "gpio: %s has missing PM functions\n" ,gc->label);
    
     else
         printk(KERN_ERR  "gpio: %s has no PM function\n" , gc->label);
     #endif
     /* gpiochip_add() prints own failure message on error. */
     ret = gpiochip_add(gc);
     if  (ret >= 0)
     s3c_gpiolib_track(chip);
}

(1)首先我们在前面的分析可知,在samsung_gpiolib_add_4bit函数中,已经添加了我们的input和output方法,所以这里的if不会成立,并且分析函数可知,这里挂接的input和output方法是针对2bit的CON寄存器的芯片(2440)。

(2)这个函数首先是对我们的GPIO进行进一步的填充,主要是添加set和get的方法。

(3)调用gpiochip_add函数来完成真真的注册。


本文转自 菜鸟养成记 51CTO博客,原文链接:http://blog.51cto.com/11674570/1941106


相关文章
|
Unix Shell Linux
Shell 内置命令:trap
Shell 内置命令:trap
433 1
|
运维 Kubernetes 监控
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
3894 0
|
机器学习/深度学习 算法 Shell
【实操:人脸矫正】两次定位操作解决人脸矫正问题
【实操:人脸矫正】两次定位操作解决人脸矫正问题
479 0
|
存储 固态存储 Linux
BLOCK 层这么多参数都是什么意思?!
每个 request queue 会维护一个 struct queue_limits 结构来描述对应的块设备的硬件参数,这些参数描述了硬件存储单元的组织方式,会影响 block layer 的很多行为,其中部分参数在 `/sys/block//queue/` 下导出 ```c struct request_queue { struct queue_limits limits; ... } `
4258 1
|
运维 分布式计算 供应链
医院HIS系统源码,全套云化医院信息管理系统
HIS系统完全基于云端部署,采用B/S架构,并通过软件即服务(SaaS)的形式面向二级医院的可快速交付、便捷运维、云化的医院核心业务平台产品。融合医院HIS和EMR两大主营系统,构建涵盖患者、费用、医嘱、电子病历等核心业务的医院基础信息系统。将HIS与电子病历整合一起形成一体化医护工作站。
544 0
医院HIS系统源码,全套云化医院信息管理系统
|
机器学习/深度学习 算法 PyTorch
深度学习在人脸识别技术中的最新进展
深度学习在人脸识别技术中的最新进展
|
数据可视化 算法 大数据
深入解析高斯过程:数学理论、重要概念和直观可视化全解
这篇文章探讨了高斯过程作为解决小数据问题的工具,介绍了多元高斯分布的基础和其边缘及条件分布的性质。文章通过线性回归与维度诅咒的问题引出高斯过程,展示如何使用高斯过程克服参数爆炸的问题。作者通过数学公式和可视化解释了高斯过程的理论,并使用Python的GPy库展示了在一维和多维数据上的高斯过程回归应用。高斯过程在数据稀疏时提供了一种有效的方法,但计算成本限制了其在大数据集上的应用。
779 1
|
程序员 Go
【Go语言精进之路】Go语言fmt包深度探索:格式化输入输出的利器
【Go语言精进之路】Go语言fmt包深度探索:格式化输入输出的利器
261 3
|
监控 数据挖掘 数据安全/隐私保护
ERP系统中的客户投诉管理与解决方案解析
【7月更文挑战第25天】 ERP系统中的客户投诉管理与解决方案解析
870 1
|
移动开发 网络协议 算法
TCP中的粘包、拆包问题产生原因及解决方法
TCP中的粘包、拆包问题产生原因及解决方法
1313 0
TCP中的粘包、拆包问题产生原因及解决方法

热门文章

最新文章