news 2026/5/1 10:25:33

一文搞懂 | 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/5/1 8:43:39

YOLO结合DeepSORT实现多目标跟踪:完整项目部署教程

YOLO结合DeepSORT实现多目标跟踪:完整项目部署教程 在智能监控系统日益普及的今天,如何让摄像头“看懂”画面中每一个移动对象的身份与轨迹?这不仅是安防领域的核心需求,也深刻影响着智慧交通、零售分析和工业自动化的发展。传统方…

作者头像 李华
网站建设 2026/4/22 11:15:19

YOLO训练数据去重:使用GPU加速哈希比对

YOLO训练数据去重:使用GPU加速哈希比对 在构建高性能目标检测模型的实践中,我们常常把注意力集中在网络结构优化、超参数调优和推理部署上,却容易忽略一个“不起眼”但影响深远的问题——训练数据中的重复样本。 想象这样一个场景&#xff1a…

作者头像 李华
网站建设 2026/5/1 8:44:11

YOLOv10引入PGI机制,提升小目标检测能力,GPU负担加重?

YOLOv10引入PGI机制,提升小目标检测能力,GPU负担加重? 在工业质检线上,一台高速相机每秒拍摄数十帧PCB板图像,系统需要精准识别出小于20像素的虚焊点——这类微小缺陷一旦漏检,可能导致整批产品返工甚至设…

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

YOLO目标检测评估数据集推荐:COCO、Pascal VOC

YOLO目标检测评估数据集推荐:COCO、Pascal VOC 在智能摄像头自动识别行人与车辆的今天,我们很少会去想——这个“看见”的能力从何而来?背后支撑这一切的,是一套高度标准化的技术体系:以YOLO为代表的实时检测模型&…

作者头像 李华
网站建设 2026/4/30 23:42:23

YOLO训练Batch Size设多少?取决于你的GPU显存大小

YOLO训练Batch Size设多少?取决于你的GPU显存大小 在工业质检车间里,一台搭载RTX 3060的工控机正试图训练YOLOv8m模型。工程师满怀期待地启动训练脚本,几秒后终端却弹出一行红色错误:CUDA out of memory。这并非个例——无数开发者…

作者头像 李华
网站建设 2026/4/20 18:52:30

YOLO训练任务支持可视化进度条与ETA预估

YOLO训练任务支持可视化进度条与ETA预估 在工业质检产线的深夜运维室里,工程师盯着终端屏幕上静止的日志输出,心里反复盘问:“这模型到底还在不在跑?是卡住了还是正常收敛?”这种“黑箱式”训练体验,在早期…

作者头像 李华