Pinctrl子系统_04_Pinctrl子系统主要数据结构

引言

本节说明Pinctrl子系统中主要的数据结构,对这些数据结构有所了解,也就是对Pinctrl子系统有所了解了。

前面说过,要使用Pinctrl子系统,就需要去配置设备树。

以内核面向对象的思想,设备树可以分为两部分,一部分(左边)用来描述Controller,另一部分(右边)则是描述使用引脚(使用controller)的device

对于controller的部分,内核会抽象出一个 pinctrl_dev 结构体;对于 device 的部分,内核会抽象出一个 device 结构体,device 结构体中会有 pinctrl 方面的成员。

显然,这个 pinctrl 方面的成员肯定会和左边的 pinctrl_dev 结构体产生联系。

那么,它们之间是什么样的关系呢?

答:在我们了解完Pinctrl子系统的数据结构之后,他们之间的关系也就清晰了。

首先,在了解Pinctrl子系统的数据结构前,先回忆一下Pinctrl子系统的三大作用

  1. 引脚枚举与命名(Enumerating and naming ):这个pinctrl支持哪些引脚,这些引脚叫什么名字;
  2. 引脚复用(Multiplexing ):用作什么功能,比如用作GPIO、I2C或其他功能;
  3. 引脚配置(Configuration):配置具体的引脚属性,比如上拉、下拉、open drain、驱动强度等;

记住这三大作用,就可以比较形象的去理解相关的结构体了。

那么,在Pinctrl子系统中,是怎么去实现这三大作用的呢?

pinctrl_desc和pinctrl_dev

我们刚刚说,controller 的部分,内核会抽象出一个 pinctrl_dev 结构体,但是事实上我们并不需要自己构造出这个 pinctrl_dev 结构体,而是使用内核提供的注册接口(pinctrl_register函数),我们只需要提供一个pinctrl_desc,然后调用这个接口,接口的返回值就是一个指向 pinctrl_dev 结构体的指针

通过 pinctrl_devpinctrl_desc 这两个结构体,就可以描述一个 pincontroller

controller相关结构体说明

imx6ull 为例,来了解pinctrl子系统中,controller 主要的数据结构,看看代码中是如何通过这些数据结构,实现 pinctrl 的三大作用的。

以下是 imx6ull 的pinctrl节点:

在设备启动后,这个节点会被转换成一个平台设备,和对应的平台驱动匹配完成后,就会调用对应的 probe 函数。

probe函数的大致流程

根据 compatible 属性值("fsl,imx6ul-iomuxc"),可以找到对应的驱动文件是 pinctrl-imx6ul.c,对应的 probe 函数是 imx6ul_pinctrl_probe,imx6ul_pinctrl_probe中则会调用 imx_pinctrl_probe函数。

imx_pinctrl_probe 函数中,会定义一个结构体指针 imx_pinctrl_desc,指向一个 pinctrl_desc 结构体。

在之后的代码中,首先申请一段内存,用来保存 pinctrl_desc,然后填充 pinctrl_desc 结构体,最后调用 devm_pinctrl_register,进行注册。

三大作用的具体实现

上面是probe函数中相关操作的大致流程,下面来具体说一下,在 Pinctrl 子系统中,是怎么去实现上面说的三大作用(引脚枚举与命名,引脚复用,引脚配置)的。

实现的关键就在于 pinctrl_desc 结构体,下面依次说明。

引脚的枚举与命名

首先看第一个功能,引脚的枚举与命名。

需要注意一下,引脚的枚举与命名分为两种情况

  1. 单个引脚 的枚举与命名;
  2. 多个引脚 的枚举与命名;
单个引脚

单个引脚的枚举和命名,主要是通过 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 宏的分析,可以看到,这里主要定义了两个成员:

  1. number(第几个引脚,引脚的枚举)
  2. name (引脚的名字,引脚的命名)

 

总结一下,单个引脚的枚举与命名,主要的相关结构体是:

  1. 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 selector:group选择器,表示选择哪个group。*/const char *(*get_group_name) (struct pinctrl_dev *pctldev,unsigned selector);/* 返回指定group的引脚数组,并在num_pins中返回数组大小。*  - struct pinctrl_dev *pctldev:引脚控制设备结构体指针,表示引脚控制器设备。*  - unsigned selector:group选择器,表示选择哪个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),相关的结构体是:

  1. 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"的缩写,表示引脚的配置操作。

可以看到,结构体内部主要还是一堆函数指针。

这里主要说明以下四个函数指针:

  1. pin_config_get:获取某个pin的配置;
  2. pin_config_set:设置某个pin的配置;
  3. pin_config_group_get:获取某个group的配置;
  4. 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 we're implementing pinmuxing, check the ops for sanity */ret = pinmux_check_ops(pctldev);/* If we're 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个:

  1. pinctrl_desc:用于描述一个特定的引脚控制器(pinctrl)的配置信息,包括该控制器管理的引脚数量、引脚的功能、引脚的默认状态等。
  2. pinctrl_dev:代表一个具体的引脚控制器设备,它与`pinctrl_desc`结构体相关联,用于在系统中表示和管理一个特定的引脚控制器。
  3. pinctrl_ops :定义了对引脚控制器进行操作的一组函数指针,包括引脚的配置、引脚的状态读取、引脚的状态设置等操作。
  4. pinmux_ops:定义了对引脚复用(pin multiplexing)进行操作的一组函数指针,用于配置引脚的不同功能模式,例如将一个引脚配置为GPIO模式或者特定外设的模式。
  5. 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 结构体的定义:

可以看到,主要定义了:

  1. 一个指向 pinctrl 结构体的结构体指针p;
  2. 4个指向 pinctrl_state 结构体的结构体指针 default_state,init_state,sleep_state,idle_state。

结合device节点,分析理解一下 dev_pin_info 结构体,以下面的device节点为例:

右边的device节点中,定义了两种状态:

  1. 状态0:default(对应 controller 节点 state_0_node_a) ;
  2. 状态1:sleep(对应 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,根据状态的序号,依次分别是default,sleep,plane。

并且 dev_pin_info 结构体中原先就有定义的 default_state 和 sleep_state,他们也会指向 states 成员中保存的 default 和 sleep 状态信息。

综上,对应device节点,最重要的结构体当属 pinctrl_state 结构体。

当设备进入某种状态时,就要把引脚配置成对应的 state。

那么,我们如何构造 pinctrl_state 呢?

如何构造pinctrl_state?

以下图为例,device 节点中的 pinctrl-0(default状态) 使用的是 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 节点,他主要有两个作用:

  1. pin mux,引脚复用;
  2. pin cfg,引脚配置;

那么,显然,pinctrl_map pinctrl_setting 就需要将这两个信息(引脚的复用信息,引脚的配置信息)保存记录下来。

首先,看一下 pinctrl_map 结构体:

可以看到,pinctrl_map 内部有一个联合体(union)data,这个联合体有两个成员:

  1. pinctrl_map_mux,记录复用信息;
  2. pinctrl_map_configs,记录配置信息;

所以,pinctrl_map 既可以记录引脚的复用信息,也可以记录引脚的配置信息;

刚刚说了,pinctrl_map 还会转换出 pinctrl_setting,来看一下 pinctrl_setting 结构体:

可以看到,他也有一个联合体(union) data,并且这个data也有两个成员:

  1. pinctrl_setting_mux,记录复用信息;
  2. 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.rhkb.cn/news/271981.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mint_21.3 drawing-area和goocanvas的FB笔记(五)

FreeBASIC SDL图形功能 SDL - Simple DirectMedia Layer 是完整的跨平台系统&#xff0c;有自己的窗口、直接捕获键盘、鼠标和游戏操纵杆的事件&#xff0c;直接操作音频和CDROM&#xff0c;在其surface上可使用gfx, openGL和direct3D绘图。Window3.0时代&#xff0c;各种应用…

Jenkins发送邮件、定时执行、持续部署

集成Allure报告只需要配置构建后操作即可。但如果是web自动化&#xff0c;或是用HTMLTestRunner生成报告&#xff0c;构建后操作要选择Publish HTML reports&#xff0c;而构建中还要添加Execute system Groovy script插件&#xff0c;内容&#xff1a; System.setProperty(&q…

如何快速分析OB集群日志,敏捷诊断工具obdiag分析能力实践——《OceanBase诊断系列》之四

1. 前言 obdiag是OceanBase的敏捷诊断工具。1.2版本中&#xff0c;obdiag支持快速收集诊断信息&#xff0c;但仅有收集能力是不够的&#xff0c;还需要有分析能力。因此在obdiag的1.3.0版本中&#xff0c;我们加入了OB集群的日志分析功能。用户可以一键进行集群的OB日志的分析…

运维知识点-Apache HTTP Server

Apache 介绍 介绍 Apache是一个开源的Web服务器软件&#xff0c;全称为Apache HTTP Server&#xff0c;由Apache软件基金会开发和维护。它是目前全球使用最广泛的Web服务器软件之一&#xff0c;占全球所有网络服务器的很大比例。Apache服务器具有跨平台的特性&#xff0c;可以…

软考高级:系统工程生命周期方法(计划驱动方法、渐进迭代式方法等)概念和例子

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【常见集合】Java 常见集合重点解析

Java 常见集合重点解析 1. 什么是算法时间复杂度&#xff1f; 时间复杂度表示了算法的 执行时间 和 数据规模 之间的增长关系&#xff1b; 什么是算法的空间复杂度&#xff1f; 表示了算法占用的额外 存储空间 与 数据规模 之间的增长关系&#xff1b; 常见的复杂度&#x…

防火墙配置实验

配置 配置IPSec FW1 FW3 NAT策略 FW1 FW3 安全策略 FW1 FW3 最后测试

数仓实战——京东数据指标体系的构建与实践

目录 一、如何理解指标体系 1.1 指标和指标体系的基本含义 1.2 指标和和标签的区别 1.3 指标体系在数据链路中的位置和作用 1.4 流量指标体系 1.5 指标体系如何向上支撑业务应用 1.6 指标体系背后的数据加工逻辑 二、如何搭建和应用指标体系 2.1 指标体系建设方法—OS…

分布式定时任务调度xxl-job

1. xxl-job基本介绍 1.1 Quartz的体系结构 Quartz中最重要的三个对象:Job&#xff08;作业&#xff09;、Trigger&#xff08;触发器&#xff09;、Scheduler&#xff08;调度器&#xff09;。 xxl-job的调度原理:调度线程在一个while循环中不断地获取一定数量的即将触发的Tr…

AIGC启示录:深度解析AIGC技术的现代性与系统性的奇幻旅程

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

政安晨:【深度学习处理实践】(三)—— 处理时间序列的数据准备

在深度学习中&#xff0c;对时间序列的处理主要涉及到以下几个方面&#xff1a; 序列建模&#xff1a;深度学习可以用于对时间序列进行建模。常用的模型包括循环神经网络&#xff08;Recurrent Neural Networks, RNN&#xff09;和长短期记忆网络&#xff08;Long Short-Term M…

【框架设计】MVC、MVP、MVVM对比图

1. MVC&#xff08;Model-View-Controller&#xff09; 2. MVP&#xff08;Model-View-Presenter&#xff09; 3. MVVM&#xff08;Model-View-ViewModel&#xff09;

ChatGPT Plus 支付出现「您的银行卡被拒绝/your card has been declined」怎么办?

ChatGPT Plus 支付出现「您的银行卡被拒绝/your card has been declined」怎么办&#xff1f; 在订阅 ChatGPT Plus 或者 OpenAI API 时&#xff0c;有时候会出现已下报错 &#xff1a; Your card has been declined. 您的银行卡被拒绝 出现这种错误&#xff0c;有以下几个解…

创邻科技获评环紫金港创新生态圈智源创新企业

3月1日&#xff0c;由杭州城西科创大走廊管理委员会指导&#xff0c;中共杭州市西湖区委员会、西湖区人民政府主办的“环紫金港创新生态圈”行动推进大会暨2024年紫金港科技城经济高质量发展大会在杭州举办。凭借重要的生态位置和创新业务成果&#xff0c;创邻科技受邀参会并被…

瑞芯微 | I2S-音频基础分享

1. 音频常用术语 名称含义ADC&#xff08;Analog to Digit Conversion&#xff09;模拟信号转换为数字信号AEC&#xff08;Acoustic Echo Cancellor&#xff09;回声消除AGC&#xff08;Automatic Gain Control&#xff09;自动增益补偿&#xff0c;调整MIC收音量ALSA&#xf…

深入探索Transformer时代下的NLP革新

《基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理》主要聚焦于如何使用Python编程语言以及深度学习框架如PyTorch和TensorFlow来构建、训练和调整用于自然语言处理任务的深度神经网络架构&#xff0c;特别是以Transformer为核心模型的架构。 书中详细介绍了Transf…

07.axios封装实例

一.简易axios封装-获取省份列表 1. 需求&#xff1a;基于 Promise 和 XHR 封装 myAxios 函数&#xff0c;获取省份列表展示到页面 2. 核心语法&#xff1a; function myAxios(config) {return new Promise((resolve, reject) > {// XHR 请求// 调用成功/失败的处理程序}) …

【嵌入式高级C语言】9:万能型链表懒人手册

文章目录 序言单向不循环链表拼图框架搭建 - Necessary功能拼图块1 创建链表头信息结构体 - Necessary2 链表头部插入 - Optional3 链表的遍历 - Optional4 链表的销毁 - Necessary5 链表头信息结构体销毁 - Necessary6 获取链表中节点的个数 - Optional7 链表尾部插入 - Optio…

git克隆过程报错

设置 git config 来强制 git 使用 HTTP 1.1 git config --global http.version HTTP/1.1想将其设置回 HTTP2&#xff0c;你可以这样做 git config --global http.version HTTP/2

飞驰云联CEO朱旭光荣获“科技领军人才”称号

2024年2月29日&#xff0c;苏州工业园区“优化营商环境暨作风效能建设大会”成功举办&#xff0c;会上公布了2023年度苏州工业园区第十七届第一批金鸡湖科技领军人才名单&#xff0c;Ftrans飞驰云联创始人兼CEO朱旭光先生凭借在数据安全以及文件交换领域取得的突出成果&#xf…