news 2026/9/18 23:06:57

一文搞懂 | Linux pinctrl/gpio子系统(1)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一文搞懂 | Linux pinctrl/gpio子系统(1)

pinctrl子系统和gpio子系统虽然难度不大,但在内核里的使用率非常高,本文争取一次性把相关内容介绍一遍。

pinctrl

数据结构

使用struct pinctrl_desc抽象一个pin controller,该结构的定义如下:

struct pinctrl_desc { const char *name; const struct pinctrl_pin_desc *pins; unsigned int npins; const struct pinctrl_ops *pctlops; const struct pinmux_ops *pmxops; const struct pinconf_ops *confops; struct module *owner; #ifdef CONFIG_GENERIC_PINCONF unsigned int num_custom_params; const struct pinconf_generic_params *custom_params; const struct pin_config_item *custom_conf_items; #endif };
  • pins

变量pins和npins把系统中所有的pin描述出来,并建立索引。驱动为了和具体的pin对应上,再将这些pin组织成一个struct pinctrl_pin_desc类型的数组,该类型的定义为:

struct pinctrl_pin_desc { unsigned number; const char *name; void *drv_data; };
  • pin groups

SoC中,有时需要将很多pin组合在一起,以实现特定的功能,例如uart接口、i2c接口等。因此pin controller需要以group为单位,访问、控制多个 pin,这就是pin groups。

pinctrl core在struct pinctrl_ops中抽象出三个回调函数,用来获取pin groups相关信息,如下:

struct pinctrl_ops { //获取系统中pin groups的个数,后续的操作,将以相应的索引为单位(类似数组的下标,个数为数组的大小) int (*get_groups_count) (struct pinctrl_dev *pctldev); //获取指定group(由索引selector指定)的名称 const char *(*get_group_name) (struct pinctrl_dev *pctldev, unsigned selector); //获取指定group的所有pins(由索引selector指定),结果保存在pins(指针数组)和num_pins(指针)中 int (*get_group_pins) (struct pinctrl_dev *pctldev, unsigned selector, const unsigned **pins, unsigned *num_pins); void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s, unsigned offset); //用于将device tree中的pin state信息转换为pin map int (*dt_node_to_map) (struct pinctrl_dev *pctldev, struct device_node *np_config, struct pinctrl_map **map, unsigned *num_maps); void (*dt_free_map) (struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps); };

group的组织方式是由驱动决定的。

  • pin configuration

除了上面的pin和pin group,有些管脚可以配置,比如上拉、下拉,高阻等。pin configuration来封装这些功能,具体体现在struct pinconf_ops数据结构中,如下:

struct pinconf_ops { #ifdef CONFIG_GENERIC_PINCONF bool is_generic; #endif //获取指定 pin 的当前配置,保存在 config 指针中 int (*pin_config_get) (struct pinctrl_dev *pctldev, unsigned pin, unsigned long *config); //设置指定pin的配置 int (*pin_config_set) (struct pinctrl_dev *pctldev, unsigned pin, unsigned long *configs, unsigned num_configs); //获取指定pin group的配置项 int (*pin_config_group_get) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *config); //设置指定pin group的配置项 int (*pin_config_group_set) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *configs, unsigned num_configs); ......
  • pin mux

为了兼容不同的应用场景,有很多管脚可以配置为不同的功能,例如A和B两个管脚,既可以当作普通的GPIO使用,又可以配置为I2C的的SCL和SDA,也可以配置为UART的TX和RX,这称作管脚的复用(简称pin mux)。使用struct pinmux_ops来抽象pin mux有关的操作,如下:

struct pinmux_ops { //检查某个pin是否已作它用,用于管脚复用时的互斥 int (*request) (struct pinctrl_dev *pctldev, unsigned offset); //request的反操作 int (*free) (struct pinctrl_dev *pctldev, unsigned offset); //获取系统中function的个数 int (*get_functions_count) (struct pinctrl_dev *pctldev); //获取指定function的名称 const char *(*get_function_name) (struct pinctrl_dev *pctldev, unsigned selector); //获取指定function所占用的pin group int (*get_function_groups) (struct pinctrl_dev *pctldev, unsigned selector, const char * const **groups, unsigned *num_groups); //将指定的pin group(group_selector)设置为指定的function(func_selector) int (*set_mux) (struct pinctrl_dev *pctldev, unsigned func_selector, unsigned group_selector); //以下是gpio相关的操作 int (*gpio_request_enable) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset); void (*gpio_disable_free) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset); int (*gpio_set_direction) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset, bool input); //为true时,说明该pin controller不允许某个pin作为gpio和其它功能同时使用 bool strict; };
  • pin state

根据前面的描述,pinctrl driver抽象出来了一些离散的对象:pin(pin group)、function、configuration,并实现了这些对象的控制和配置方式。然后我们回到某一个具体的device上(如 lpuart,usdhc)。一个设备在某一状态下(如工作状态、休眠状态等等),所使用的pin(pin group)、pin(pin group)的function和configuration,是唯一确定的。所以固定的组合可以确定固定的状态,在设备树里用pinctrl-names指明状态名字,pinctrl-x指明状态引脚。

  • pin map

pin state有关的信息是通过pin map收集,相关的数据结构如下:

struct pinctrl_map { //device的名称 const char *dev_name; //pin state的名称 const char *name; //该map的类型 enum pinctrl_map_type type; //pin controller device的名字 const char *ctrl_dev_name; union { struct pinctrl_map_mux mux; struct pinctrl_map_configs configs; } data; }; enum pinctrl_map_type { PIN_MAP_TYPE_INVALID, //不需要任何配置,仅仅为了表示state的存在 PIN_MAP_TYPE_DUMMY_STATE, //配置管脚复用 PIN_MAP_TYPE_MUX_GROUP, //配置pin PIN_MAP_TYPE_CONFIGS_PIN, //配置pin group PIN_MAP_TYPE_CONFIGS_GROUP, }; struct pinctrl_map_mux { //group的名字 const char *group; //function的名字 const char *function; }; struct pinctrl_map_configs { //该pin或者pin group的名字 const char *group_or_pin; //configuration数组 unsigned long *configs; //配置项的个数 unsigned num_configs; };

pinctrl driver确定了pin map各个字段的格式之后,就可以在dts文件中维护pin state以及相应的mapping table。pinctrl core在初始化的时候,会读取并解析dts,并生成pin map。

而各个consumer,可以在自己的dts node中,直接引用pinctrl driver定义的pin state,并在设备驱动的相应的位置,调用pinctrl subsystem提供的 API(pinctrl_lookup_state,pinctrl_select_state),active或者deactive这些state。

更多内容请看下回。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 11:36:43

YOLO目标检测模型版权保护:水印嵌入技术初探

YOLO目标检测模型版权保护:水印嵌入技术初探 在工业视觉、自动驾驶和智能安防等领域,YOLO系列模型早已成为实时目标检测的“标配”。从生产线上的缺陷识别到城市交通监控,其毫秒级响应与高精度表现让部署者趋之若鹜。然而,正因其开…

作者头像 李华
网站建设 2026/9/16 23:52:31

YOLO模型推理延迟分解:从加载到输出各阶段耗时

YOLO模型推理延迟分解:从加载到输出各阶段耗时 在一条高速SMT贴片生产线上,相机每20毫秒捕捉一帧图像,PLC控制系统要求目标检测结果必须在15毫秒内返回——否则将导致误判、漏检,甚至整批电路板报废。这样的场景在智能制造中早已司…

作者头像 李华
网站建设 2026/8/25 2:05:01

YOLO模型训练超参调优指南:GPU资源如何高效利用?

YOLO模型训练超参调优指南:GPU资源如何高效利用? 在智能制造车间的视觉质检线上,一台搭载Jetson AGX Xavier的检测设备正以每秒30帧的速度扫描PCB板。背后支撑这一实时推理能力的,是一个经过精心调优的YOLOv8s模型——而它的诞生过…

作者头像 李华
网站建设 2026/9/13 5:35:48

YOLO训练评估阶段卡顿?避免GPU与CPU同步等待

YOLO训练评估阶段卡顿?避免GPU与CPU同步等待 在工业质检产线的深夜调试中,你是否经历过这样的场景:模型已经训练了数十个epoch,终于进入验证阶段,结果系统突然“卡住”——GPU利用率从90%暴跌至10%,而CPU核…

作者头像 李华
网站建设 2026/9/5 22:18:53

YOLO目标检测在矿业生产中的应用:矿石粒度分析

YOLO目标检测在矿业生产中的应用:矿石粒度分析 在矿山破碎车间的轰鸣声中,传送带上的矿石如潮水般涌动。操作员盯着监控屏幕,试图判断是否有过大块矿石可能卡住下游设备——这一幕曾是选矿厂日常的真实写照。如今,越来越多的企业开…

作者头像 李华
网站建设 2026/9/7 0:08:23

YOLO模型太大加载慢?NVMe + GPU显存预加载方案

YOLO模型加载慢?用NVMe GPU显存预加载破局 在智能制造工厂的质检线上,一台AOI(自动光学检测)设备每秒捕捉50帧高清图像,系统必须在20毫秒内完成缺陷识别并触发分拣动作。然而上线初期频繁出现“首帧卡顿”——前几帧处…

作者头像 李华