文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一篇带给你Pinctrl子系统的深入分析

2024-12-02 18:12

关注

博主假设大家已经看过下面这篇文章:

GPIO 软件框架

本文就直接深入分析 pinctrl 子系统。

使用 pinctrl 和 gpio 子系统进行 GPIO 驱动开发,是嵌入式驱动工程师的基本操作,但大部分驱动工程师只会用子系统提供的 API 接口,不会对其底层实现进行分析,本文对其底层实现进行分析,文末有参考文章链接。

在此框架中,(1)、(2)、(3)由半导体厂商搞定,半导体厂商会利用 Linux 提供的框架,根据自己的芯片,客制化代码。普通的驱动工程师就是调用 API 即可,就算是写驱动了。

本文着重讲解(2),所以由图我们知道,pinctrl 子系统和 gpio 子系统都依赖于(2)的驱动。

工具

分析源码可以在线查看 Linux 内核源码,在线网址跳转函数和查找结构体也很方便:

https://elixir.bootlin.com/linux/latest/source

对嵌入式工程师来讲,较少谈及设计模式、重构等,因为我们受限于两个方面:硬件、系统(Linux、Android)。很多东西操作系统都规定好了,留给我们重新设计的很少,我们不做设计题,我们做填空题。

在 Linux 内核源码中,pinctrl 子系统的代码大都在 kernel/drivers/pinctrl/...,不同平台有不同的文件夹。gpio 子系统的代码大都在 kernel/drivers/gpio/...目录下。

博主买了正点原子 imx6ull 开发板,所以就以此板为例程,进行分析。

一、主要结构体

pinctrl 子系统主要结构体关系:

pinctrl_dev 是 pinctrl 子系统的根源结构体,它主要包含三条路:

pinctrl_desc:这里包含了pinctrl 子系统三个最重要的结构体,有三个操作函数集,pinctrl_ops 包含了对 PIN 的操作函数集,pinmux_ops 包含了对 PIN 的复用函数集,pinconf_ops 包含了对 PIN 的配置函数,大家可以在自己平台中点进去看看自己平台实现了哪个函数,如何实现的。

pinctrl 结构体:这里包含了 PIN 控制器所控制 PIN 的状态 state,state 里面包含了 setting,这个 setting 就是在设备树中对PIN的设置,大家点进去看相关数据结构就可以看到自己在设备树中用到的字符串。

gpio 相关的结构体,我们说过 pinctrl 子系统和 gpio 子系统是耦合的,我们从结构体就可以看得出来,它包含了最重要的结构体 gpio_chip。

我们已经阐述了pinctrl 子系统主要的数据结构,后面讲述函数调用关系。

二、函数调用逻辑

在文件 drivers/pinctrl/freescale/pinctrl-imx6ul.c 中有如下内容:

驱动的入口是 arch_initcall 中声明的函数,类似于我们经常写的 module_init,只是 arch_initcall 会先调用,具体我在这边写过:

Linux 驱动挂载顺序分析

我们从下往上看,可以看到最后调用的是 imx6ul_pinctrl_probe 函数,和普通驱动的 probe 函数一样,也就是说,pinctrl 子系统的驱动也是一个标准的 platform 驱动框架,分为:驱动、设备、总线。platform 虚拟总线会按照 of_device_id 结构体中的 compatible 属性去匹配 pinctrl 驱动和设备。

在不同芯片厂商的 probe 函数中,都是对上面所描述数据结构的初始化、填充、调用,释放。

我们看 292 行,是匹配结构体,根据 compatible 和设备树的compatible 字段进行匹配,匹配成功执行这个 probe 函数。每个平台 probe 函数都有区别,就不详讲了。

我们看 292 行的 of_device_id 定义的数组,最后一个是空元素,这是必须的,原因是 platform 本身的 match 函数中需要判断是否达到末尾,of_device_id 定义的 compatible 经常不止一个,系统需要知道是否匹配到最后一个元素,这一点一定要注意。

pinctrl_register

probe 函数后面的调用中,最重要的是调用 pinctrl_register 函数,此函数用于向 Linux 内核注册一个 PIN 控制器,,此函数原型如下:

  1. struct pinctrl_dev *pinctrl_register( 
  2. struct pinctrl_desc *pctldesc, 
  3. struct device *dev, 
  4. void *driver_data) 

参数 pctldesc 非常重要,因为此参数就是要注册的 PIN 控制器,PIN 控制器用于配置 SOC的 PIN 复用功能和电气特性。参数 pctldesc 是 pinctrl_desc 结构体类型指针,pinctrl_desc 结构体如下所示:

  1. struct pinctrl_desc { 
  2.  const char *name
  3.  struct pinctrl_pin_desc const *pins; 
  4.  unsigned int npins; 
  5.  const struct pinctrl_ops *pctlops; 
  6.  const struct pinmux_ops *pmxops; 
  7.  const struct pinconf_ops *confops; 
  8.  struct module *owner; 
  9.  #ifdef CONFIG_GENERIC_PINCONF 
  10.  unsigned int num_custom_params; 
  11.  const struct pinconf_generic_params *custom_params; 
  12.  const struct pin_config_item *custom_conf_items; 
  13.  #endif 
  14. }; 

这三个 “_ops” 结构体指针非常重要!因为这三个结构体就是 PIN 控制器的“工具”,这三个结构体里面包含了很多操作函数,通过这些操作函数就可以完成对某一个 PIN 的配置。pinctrl_desc 结构体需要由用户提供,结构体里面的成员变量也是用户提供的。但是这个用户并不是我们这些使用芯片的程序员,而是半导体厂商,半导体厂商发布的 Linux 内核源码中已经把这些工作做完了。

下面是参考文章,写的比博主更深入,尤其第一个链接,大家可以查看。

参考文章:

http://www.wowotech.net/sort/gpio_subsystem

https://www.freesion.com/article/89301077969/

https://blog.csdn.net/u012830148/article/details/80609337

《正点原子 imx6u Linux 驱动开发指南》

来源:嵌入式Linux系统开发内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯