当前位置: 首页 > news >正文

网站开发从零到上线天眼查网站建设公司

网站开发从零到上线,天眼查网站建设公司,flash 网站建设,定制系统引言 本节说明Pinctrl子系统中主要的数据结构#xff0c;对这些数据结构有所了解#xff0c;也就是对Pinctrl子系统有所了解了。 前面说过#xff0c;要使用Pinctrl子系统#xff0c;就需要去配置设备树。 以内核面向对象的思想#xff0c;设备树可以分为两部分#x…引言 本节说明Pinctrl子系统中主要的数据结构对这些数据结构有所了解也就是对Pinctrl子系统有所了解了。 前面说过要使用Pinctrl子系统就需要去配置设备树。 以内核面向对象的思想设备树可以分为两部分一部分左边用来描述Controller另一部分右边则是描述使用引脚使用controller的device。 对于controller的部分内核会抽象出一个 pinctrl_dev 结构体对于 device 的部分内核会抽象出一个 device 结构体device 结构体中会有 pinctrl 方面的成员。 显然这个 pinctrl 方面的成员肯定会和左边的 pinctrl_dev 结构体产生联系。 那么它们之间是什么样的关系呢 答在我们了解完Pinctrl子系统的数据结构之后他们之间的关系也就清晰了。 首先在了解Pinctrl子系统的数据结构前先回忆一下Pinctrl子系统的三大作用 引脚枚举与命名Enumerating and naming 这个pinctrl支持哪些引脚这些引脚叫什么名字引脚复用Multiplexing 用作什么功能比如用作GPIO、I2C或其他功能引脚配置Configuration配置具体的引脚属性比如上拉、下拉、open drain、驱动强度等 记住这三大作用就可以比较形象的去理解相关的结构体了。 那么在Pinctrl子系统中是怎么去实现这三大作用的呢 pinctrl_desc和pinctrl_dev 我们刚刚说controller 的部分内核会抽象出一个 pinctrl_dev 结构体但是事实上我们并不需要自己构造出这个 pinctrl_dev 结构体而是使用内核提供的注册接口pinctrl_register函数我们只需要提供一个pinctrl_desc然后调用这个接口接口的返回值就是一个指向 pinctrl_dev 结构体的指针。 通过 pinctrl_dev 和 pinctrl_desc 这两个结构体就可以描述一个 pincontroller controller相关结构体说明 以 imx6ull 为例来了解pinctrl子系统中controller 主要的数据结构看看代码中是如何通过这些数据结构实现 pinctrl 的三大作用的。 以下是 imx6ull 的pinctrl节点 在设备启动后这个节点会被转换成一个平台设备和对应的平台驱动匹配完成后就会调用对应的 probe 函数。 probe函数的大致流程 根据 compatible 属性值fsl,imx6ul-iomuxc可以找到对应的驱动文件是 pinctrl-imx6ul.c对应的 probe 函数是 imx6ul_pinctrl_probeimx6ul_pinctrl_probe中则会调用 imx_pinctrl_probe函数。 在 imx_pinctrl_probe 函数中会定义一个结构体指针 imx_pinctrl_desc指向一个 pinctrl_desc 结构体。 在之后的代码中首先申请一段内存用来保存 pinctrl_desc然后填充 pinctrl_desc 结构体最后调用 devm_pinctrl_register进行注册。 三大作用的具体实现 上面是probe函数中相关操作的大致流程下面来具体说一下在 Pinctrl 子系统中是怎么去实现上面说的三大作用引脚枚举与命名引脚复用引脚配置的。 实现的关键就在于 pinctrl_desc 结构体下面依次说明。 引脚的枚举与命名 首先看第一个功能引脚的枚举与命名。 需要注意一下引脚的枚举与命名分为两种情况 单个引脚 的枚举与命名多个引脚 的枚举与命名 单个引脚 单个引脚的枚举和命名主要是通过 pinctrl_desc 结构体的 pins 成员和 npins 成员来实现的。 其中pins 成员是一个结构体指针指向一个 pinctrl_pin_desc 结构体主要负责引脚的枚举与命名而 npins 成员则是一个无符号的整型数据用来记录引脚的总个数。 在 probe 函数中会对 pins 和 npins 赋值大致流程如下 其中imx6ul_pinctrl_info 变量的类型是 imx_pinctrl_soc_info 结构体他也有 pins 和 npins 成员 可以看到他的 pins 成员指向了一个 imx6ul_pinctrl_pads 变量这个变量是一个结构体数组我们稍后再说。 综上相当于执行了 imx_pinctrl_desc-pins imx6ull_snvs_pinctrl_pads;imx_pinctrl_desc-npins ARRAY_SIZE(imx6ull_snvs_pinctrl_pads); 下面看一下 imx6ul_pinctrl_pads 变量他是一个结构体数组。通过对 IMX_PINCTRL_PIN 宏的分析可以看到这里主要定义了两个成员 number第几个引脚引脚的枚举 name 引脚的名字引脚的命名 总结一下单个引脚的枚举与命名主要的相关结构体是 pinctrl_pin_desc结构体 多个引脚 上面说 pins 和 npins他们是描述单个引脚。而在实际使用中有时候会需要同时操作多个引脚group比如i2c中我们要用到一组引脚要如何同时操作多个引脚呢 答这个时候就要用到 pinctrl_ops 结构体了 可以看到 pinctrl_ops结构体的成员全部都是函数指针它们的功能如下 struct pinctrl_ops {/* 返回已注册的group数* - struct pinctrl_dev *pctldev引脚控制设备结构体指针表示引脚控制器设备。*/int (*get_groups_count) (struct pinctrl_dev *pctldev);/* 返回指定group的名字* - struct pinctrl_dev *pctldev引脚控制设备结构体指针表示引脚控制器设备。* - unsigned selectorgroup选择器表示选择哪个group。*/const char *(*get_group_name) (struct pinctrl_dev *pctldev,unsigned selector);/* 返回指定group的引脚数组并在num_pins中返回数组大小。* - struct pinctrl_dev *pctldev引脚控制设备结构体指针表示引脚控制器设备。* - unsigned selectorgroup选择器表示选择哪个group。* - const unsigned **pins指向存储引脚数组的指针的指针。* - unsigned *num_pins指向存储引脚数组大小的变量的指针。*/int (*get_group_pins) (struct pinctrl_dev *pctldev,unsigned selector,const unsigned **pins,unsigned *num_pins);/* 可选的debugfs钩子函数用于在debugfs中为特定引脚提供每个设备的信息。* - struct pinctrl_dev *pctldev引脚控制设备结构体指针表示引脚控制器设备。* - struct seq_file *s序列文件结构体指针用于在debugfs中显示信息。* - unsigned offset偏移量表示特定引脚的偏移量。*/void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,unsigned offset);/* 解析设备树中的“引脚配置节点”并为其创建映射表条目。这些通过map和num_maps输出参数返回。此函数是可选的对于不支持设备树的引脚控制驱动程序可以省略。* - struct pinctrl_dev *pctldev引脚控制设备结构体指针表示引脚控制器设备。* - struct device_node *np_config设备树中的引脚配置节点。* - struct pinctrl_map **map指向映射表指针的指针用于返回映射表条目。* - unsigned *num_maps指向存储映射表条目数量的变量的指针。*/int (*dt_node_to_map) (struct pinctrl_dev *pctldev,struct device_node *np_config,struct pinctrl_map **map, unsigned *num_maps);/* 释放通过dt_node_to_map创建的映射表条目。必须释放顶层map指针以及映射表条目本身的任何动态分配成员。此函数是可选的对于不支持设备树的引脚控制驱动程序可以省略。* - struct pinctrl_dev *pctldev引脚控制设备结构体指针表示引脚控制器设备。* - struct pinctrl_map *map映射表指针需要释放。* - unsigned num_maps映射表条目数量。*/void (*dt_free_map) (struct pinctrl_dev *pctldev,struct pinctrl_map *map, unsigned num_maps); };这里说明一下pinctrl_ops结构体成员中有一个很关键的函数指针 dt_node_to_map他是用来处理设备树的我们以后再说这里先点一下。 所以对于多个引脚group相关的结构体是 pinctrl_ops 结构体 引脚复用 类似的引脚的复用也是由一个结构体来实现pinmux_ops。 pinmux_ops 就是 Pin Multiplexing Operations的缩写表示引脚复用操作。 可以看到结构体内部主要也是一堆函数指针。 其中引脚的复用主要是通过 set_mux 成员来实现的他也是一个函数指针 这里目前只对set_mux成员做说明后面如果有用到其他函数指针到时候再补充。 struct pinmux_ops {int (*request) (struct pinctrl_dev *pctldev, unsigned offset);int (*free) (struct pinctrl_dev *pctldev, unsigned offset);int (*get_functions_count) (struct pinctrl_dev *pctldev);const char *(*get_function_name) (struct pinctrl_dev *pctldev,unsigned selector);int (*get_function_groups) (struct pinctrl_dev *pctldev,unsigned selector,const char * const **groups,unsigned *num_groups);/* 启用特定的muxing功能与特定的group。驱动程序无需确定启用此功能是否与该组中pin的其他用途冲突这种冲突由pinmux子系统处理。* - struct pinctrl_dev *pctldev: 指向pinctrl设备结构的指针用于表示设置mux的pinctrl设备。* - unsigned func_selector: 无符号整数表示选择什么功能。* - unsigned group_selector: 无符号整数表示选择哪个group。*/int (*set_mux) (struct pinctrl_dev *pctldev, unsigned func_selector,unsigned group_selector);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);bool strict; }; 引脚配置 我们还可以将一个或一组引脚设置成不同的配置比如上拉下拉open drain开漏等等。 这是怎么操作的呢 答同样是通过一个结构体pinconf_ops pinconf_ops 就是Pin Configuration Options的缩写表示引脚的配置操作。 可以看到结构体内部主要还是一堆函数指针。 这里主要说明以下四个函数指针 pin_config_get获取某个pin的配置pin_config_set设置某个pin的配置pin_config_group_get获取某个group的配置pin_config_group_set设置某个group的配置 注册pinctrl_dev 填充完 pinctrl_desc 结构体之后调用 devm_pinctrl_register 或 pinctrl_register就可以根据 pinctrl_desc 构造出 pinctrl_dev并且把 pinctrl_dev 放入链表 devm_pinctrl_registerpinctrl_registerstruct pinctrl_dev *pctldev;pctldev kzalloc(sizeof(*pctldev), GFP_KERNEL);pctldev-owner pctldesc-owner;pctldev-desc pctldesc;pctldev-driver_data driver_data;/* check core ops for sanity */ret pinctrl_check_ops(pctldev);/* If were implementing pinmuxing, check the ops for sanity */ret pinmux_check_ops(pctldev);/* If were implementing pinconfig, check the ops for sanity */ret pinconf_check_ops(pctldev);/* Register all the pins */ret pinctrl_register_pins(pctldev, pctldesc-pins, pctldesc-npins);list_add_tail(pctldev-node, pinctrldev_list); 总结 综上对于controller涉及的结构体主要有5个 pinctrl_desc用于描述一个特定的引脚控制器pinctrl的配置信息包括该控制器管理的引脚数量、引脚的功能、引脚的默认状态等。pinctrl_dev代表一个具体的引脚控制器设备它与pinctrl_desc结构体相关联用于在系统中表示和管理一个特定的引脚控制器。pinctrl_ops 定义了对引脚控制器进行操作的一组函数指针包括引脚的配置、引脚的状态读取、引脚的状态设置等操作。pinmux_ops定义了对引脚复用pin multiplexing进行操作的一组函数指针用于配置引脚的不同功能模式例如将一个引脚配置为GPIO模式或者特定外设的模式。pinconf_ops定义了对引脚配置pin configuration进行操作的一组函数指针用于设置和获取引脚的一些特定属性例如引脚的电压、上下拉设置等。 device相关结构体说明 上面主要是对左边controller相关的结构体说明下面来讨论一下右边device相关的结构体。 dev_pin_info 结构体 在设备树中使用pinctrl时device节点格式如下 /* For a client device requiring named states */ device {pinctrl-names active, idle;pinctrl-0 state_0_node_a;pinctrl-1 state_1_node_a state_1_node_b; }; 设备节点要么被转换为 platform_device要么转换为其他结构体(比如i2c_client)但是里面都会有一个 device 结构体。在 device 结构体中会有一个 pins 成员这个 pins 成员是一个结构体指针指向一个 dev_pin_info 结构体。 dev_pin_info 结构体保存的就是这个 device 的 pinctrl 信息。 下面是 dev_pin_info 结构体的定义 可以看到主要定义了 一个指向 pinctrl 结构体的结构体指针p4个指向 pinctrl_state 结构体的结构体指针 default_stateinit_statesleep_stateidle_state。 结合device节点分析理解一下 dev_pin_info 结构体以下面的device节点为例 右边的device节点中定义了两种状态 状态0default对应 controller 节点 state_0_node_a 状态1sleep对应 controller 节点 state_1_node_a 和 state_1_node_b。 那么就会用这些节点来构造 dev_pin_info 结构体中的 default_state 和 sleep_state 可以看到dev_pin_info 结构体中已经定义了 4 个pinctrl_state指针如果要添加我们自定义的state要怎么记录呢 答dev_pin_info 结构体中有一个 pinctrl 结构体我们自定义的 state 就存放在这个 pinctrl 结构体中。 假设要添加一个自定义的state名字叫做“plane”意为飞行模式那么节点会变成这样 pinctrl 结构体中有一个 states 成员这个成员就会以链表的形式保存所有state根据状态的序号依次分别是defaultsleepplane。 并且 dev_pin_info 结构体中原先就有定义的 default_state 和 sleep_state他们也会指向 states 成员中保存的 default 和 sleep 状态信息。 综上对应device节点最重要的结构体当属 pinctrl_state 结构体。 当设备进入某种状态时就要把引脚配置成对应的 state。 那么我们如何构造 pinctrl_state 呢 如何构造pinctrl_state 以下图为例device 节点中的 pinctrl-0default状态 使用的是 state_0_node_a 节点那么自然就要根据 state_0_node_a 节点来构造出 default_state。 那么怎么根据pinctrl节点构造state呢 答需要用到 pinctrl_ops 结构体中的 dt_node_to_map 成员了。 dt_node_to_map 就是 device tree node 》map顾名思义就是将设备树的节点转换成一系列的map结构体即pinctrl_map结构体的意思。 通过 dt_node_to_map将 pinctrl 节点转换为 pinctrl_map再由 pinctrl_map 转换为 pinctrl_setting最后pinctrl_setting 会被存入 pinctrl_state 中的 settings 链表。 那么pinctrl_map 和 pinctrl_setting 中需要保存哪些信息呢 答对于 pinctrl 节点他主要有两个作用 pin mux引脚复用pin cfg引脚配置 那么显然pinctrl_map 和 pinctrl_setting 就需要将这两个信息引脚的复用信息引脚的配置信息保存记录下来。 首先看一下 pinctrl_map 结构体 可以看到pinctrl_map 内部有一个联合体uniondata这个联合体有两个成员 pinctrl_map_mux记录复用信息pinctrl_map_configs记录配置信息 所以pinctrl_map 既可以记录引脚的复用信息也可以记录引脚的配置信息 刚刚说了pinctrl_map 还会转换出 pinctrl_setting来看一下 pinctrl_setting 结构体 可以看到他也有一个联合体union data并且这个data也有两个成员 pinctrl_setting_mux记录复用信息pinctrl_setting_configs记录配置信息 所以与 pinctrl_map 一样pinctrl_setting 也是既可以记录引脚的复用信息也可以记录引脚的配置信息。 对比 pinctrl_map 与 pinctrl_setting可以发现两者高度类似都可以保存引脚的复用信息配置信息。 综上我们知道了 驱动程序会把 pinctrl子节点 转换成一系列为什么说一系列因为一个pinctrl子节点可能包含多个引脚的 pinctrl_map 和 pinctrl_setting 结构体在 pinctrl_map 和 pinctrl_setting 结构体中会保存引脚的配置信息复用信息。 并且 pinctrl_setting 结构体还会被存入 pinctrl_state以后我们选择让这个设备进入某种状态时就会根据这些setting来设置那些引脚选择引脚的功能配置引脚的上下拉驱动强度等等。 使用pinctr_setting 最后我们来看一下 pinctrl_state 中的这一系列 setting是如何被调用的又是如何去配置引脚的。 这主要会涉及 pinmux_ops 结构体中的 set_mux设置复用和 pinconf_ops 结构体中的 pin_config_set设置引脚配置pin_config_group_set设置group配置。 调用的流程如下 really_probepinctrl_bind_pinspinctrl_select_state/* Apply all the settings for the new state */list_for_each_entry(setting, state-settings, node) {switch (setting-type) {/* 引脚复用 */case PIN_MAP_TYPE_MUX_GROUP:ret pinmux_enable_setting(setting);ret ops-set_mux(...);break;/* 引脚配置单引脚多引脚 */case PIN_MAP_TYPE_CONFIGS_PIN:case PIN_MAP_TYPE_CONFIGS_GROUP:ret pinconf_apply_setting(setting);switch (setting-type) {case PIN_MAP_TYPE_CONFIGS_PIN:ret ops-pin_config_set(...);break;case PIN_MAP_TYPE_CONFIGS_GROUP:ret ops-pin_config_group_set(...);break;default:return -EINVAL;}break;default:ret -EINVAL;break;} 这样左右两边的结构体controller和device就产生了联系当设备进入某种状态时就可以将引脚设置为对应的配置。 当我们对上述的结构体都有了初步的了解之后后面就可以开始进行更深入的分析了。 以上就是本节全部内容。
http://www.tj-hxxt.cn/news/137246.html

相关文章:

  • 山东建设局网站 王局为什么做电影网站没有流量吗
  • thinkphp做直播网站办公室电脑局域网组建
  • 永州商城网站建设wordpress 排除分类
  • 温州企业网站建设要多少钱wordpress 更换中文
  • 长春专业做网站公司排名网站建设方案协议书
  • 南京网站优化哪家好培训机构的网站建设
  • html网页设计网站开发报告做视频的背景音乐哪里下载网站
  • 黑色风格网站主页面新公司需要做网站
  • 网站未备案 打不开建设网站哪个模板网站
  • 做简单的网站链接前端网页模板
  • 南京网络公司网站无锡网站排名公司
  • 网站建设管理员角色设置亿网正品
  • 企业网站的基本内容和营销功能深圳网站搜索优化工具
  • 多语言网站建设应注意哪些事项济南个人急售二手房
  • 正规的镇江网站建设怎样在我的世界做汽车视频网站
  • 网站开发需要哪些职位做网站大约多少钱
  • 免费门户网站系统wordpress 文章编辑 插件
  • 网站程序开发外包平面设计公司广告语
  • 表白网站制作模板巴南市政建设网站
  • 广东 网站建设汽车租赁网站建设内容
  • 男男床做第一次视频网站wordpress文章循环不带置顶文章
  • 微信订阅号 网站开发网店模板
  • 北京大型网站优化wordpress 女性模板
  • 网站开发维护成本wordpress 文章版权
  • 游戏网站首页模板最快做网站的语言
  • 郑州企业免费建站wordpress3.6
  • 网站不显示内容佛山网站建设专业定制
  • 我自己做的一个网站显示证书错误郑州新闻
  • 住房和城乡建设部网站诚信评价win7一键优化工具
  • 未备案网站处理系统做邀请函用哪个网站好呢