1.goio库的作用:由于GPIO口较多,当编程人员调用使用GPIO时难免发生不同驱动使用同一个GPIO的情况,因此内核便采用gpio库去帮助统一管理gpio。
2.学习思路:a.了解驱动框架的设置,在内核中提供的接口和在厂商芯片代码的接口。b.以一条主线的方式去追gpio的建立过程,中间涉及的零碎信息也要搞清楚但不要丢失主线。c.区分各结构体信息和作用。d.培养架构思想,因为越复杂的驱动也会有越复杂的架构思想在里面,包含许多软硬件知识。
3.gpio在内核中的建立(以S5PV210为参考):
a.函数s5pv210_gpiolib_init首先设置结构体:
驱动开发之gpiolib库的学习及使用
驱动开发之gpiolib库的学习及使用
如图为类型为s3c_gpio_chip的结构体数组。其中每一个表示一个GPIO端口的抽象表现,.base返回一个端口的编号,.ngpio接收一个宏,记录该端口的IO口数量,.lable为端口名,.to_irq接收换算得来的中断号。
部分端口在.chip为还有.base(记录端口的起始地址)和.config(配置)等。
for循环将未配置的结构体设为默认配置,将未提供端口起始地址的数组提供起始地址。其中的偏移量为ox20(可对照数据手册验证)。
b.调用samsung_gpiolib_add_4bit_chips函数。
从函数名即可看出此函数由芯片商提供,4bit表示当前的gpio为4位为一IO引脚设置,S5PV210和未来的趋势也均为向4bit方向发展,而2440等采用的为2bit为一引脚的设置。
该函数依次调用函数samsung_gpiolib_add_4bit2(chip)和s3c_gpiolib_add(chip);
samsung_gpiolib_add_4bit2(chip) :设置结构体中的direction_input和direction_output函数,即输入模式和输出模式。
在设置的函数中,首先用了container_of的宏去通过该结构体在s3c_gpio_chip的地址信息反推的得到.chip外的.base的起始地址信息(在上面介绍过),通过这样获得端口起始地址去读寄存器信息,位或更改数值后再写入。这便是我们熟悉的“读写改”三部曲。
s3c_gpiolib_add :检验之前是否初始换输出和输入,若没有采用默认值(追进去发现默认值为2440的方式,即2bit为一个IO口的设置)。由进行了get和set的默认设置。
直到这里便完成了所有gpio的初始化设置,但还没有完成真正的注册。
4.注册:
注册实际上就是gpiochip_add函数将我们完成的整个结构体信息挂接到内核gpio模块的一个gpio_desc数组中去。
从该函数名也可看出这是内核提供的驱动框架,即各家芯片厂商通用的用于向内核注册的接口。
5.驱动框架角度的分析:
之前的函数介绍均为芯片商与内核之间去建立联系。而我们去使用这些则需要gpio_request(gpio申请)、gpio_free(gpio释放)、 gpio_request_one(申请并设置输入输出)、 gpiochip_is_requested(判断gpio是否被成功申请)、 gpio_direction_input/output(设置输入输出模式)等函数对gpio达到操作的目的。、
以上这些函数本身并不直接操控硬件,而是调用芯片商提供的函数去操控。

gpiolib的建立过程还涉及一些电源管理、自旋锁、睡眠唤醒等设置,详见内核代码吧。

涉及的代码目录大多在arm/arm/mach-s5pv210下,可自行查找。

相关文章:

  • 2021-12-05
  • 2022-02-12
  • 2021-10-20
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-11-16
  • 2021-08-29
  • 2021-05-25
  • 2022-01-08
  • 2021-11-06
  • 2022-12-23
相关资源
相似解决方案