Pinctrl子系统中Pincontroller构造过程驱动分析:imx_pinctrl_soc_info结构体

往期内容

本专栏往期内容:

  1. Pinctrl子系统和其主要结构体引入
  2. Pinctrl子系统pinctrl_desc结构体进一步介绍
  3. Pinctrl子系统中client端设备树相关数据结构介绍和解析

input子系统专栏:

  1. 专栏地址:input子系统
  2. input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
    – 末片,有往期内容观看顺序

I2C子系统专栏:

  1. 专栏地址:IIC子系统
  2. 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
    – 末篇,有往期内容观看顺序

总线和设备树专栏:

  1. 专栏地址:总线和设备树
  2. 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
    – 末篇,有往期内容观看顺序

img

前言

Linux 4.x内核文档

  • Documentation\pinctrl.txt📎pinctrl.txt
  • Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt📎pinctrl-bindings.txt
  • arch/arm/boot/dts/imx6ull-14x14-evk.dts
  • arch/arm/boot/dts/100ask_imx6ull-14x14.dts
  • drivers\pinctrl\freescale\pinctrl-imx6ul.c📎pinctrl-imx6ul.c
  • drivers\pinctrl\freescale\pinctrl-imx.c📎pinctrl-imx.c

主要讲解pincontroller中设备树是如何去定义的,以及其驱动程序是如何去对设备树中节点的相关引脚去进行解析、获取相关信息并存储进imx_pinctrl_soc_info结构体当中。

1.设备树

img

对应的驱动程序:drivers\pinctrl\freescale\pinctrl-imx6ul.c📎pinctrl-imx6ul.c,这要是涉及具体的单板,内部还是会调用到pinctrl-imx.c中提供的通用的函数,具体往下面看。

img

2.驱动代码执行流程

img

主要函数是pinrctrl-imx6ull.c中的imx6ul_pinctrl_probe

drivers\pinctrl\freescale\pinctrl-imx6ul.c:
static int imx6ul_pinctrl_probe(struct platform_device *pdev)
{const struct of_device_id *match;struct imx_pinctrl_soc_info *pinctrl_info;// 1. 使用设备树匹配表(imx6ul_pinctrl_of_match)查找是否有匹配的设备节点//通过 of_match_device 函数,将设备树中定义的设备节点与 pdev->dev 设备的 compatible 属性进行匹配。match = of_match_device(imx6ul_pinctrl_of_match, &pdev->dev);// 2. 如果没有找到匹配项,返回 -ENODEV,表示没有此设备if (!match)return -ENODEV;// 3. 取出匹配的设备信息数据(即 pinctrl 的配置信息),并将它转换成合适的数据结构类型//match->data 存储了当前 SoC 的 pinctrl 信息,如引脚映射表等内容。通过类型转换将其解析为 struct imx_pinctrl_soc_info 类型,便于后续操作。pinctrl_info = (struct imx_pinctrl_soc_info *) match->data;// 4. 调用 imx_pinctrl_probe 函数,初始化 pinctrl,并将其注册到系统中//将平台设备 pdev 和其 pinctrl 信息 pinctrl_info 传入 imx_pinctrl_probe,完成引脚控制器的初始化。return imx_pinctrl_probe(pdev, pinctrl_info);
}

这个 imx6ul_pinctrl_probe 函数是 IMX6UL(NXP i.MX 6UL系列处理器)的引脚控制器(pinctrl)驱动程序中的探测函数,用于在内核加载时初始化该设备的引脚控制功能。此函数通过匹配设备树中的节点,将设备的 pinctrl 配置信息初始化并注册到系统中。

其中imx_pinctrl_probe,这个函数才是主要的。

drivers\pinctrl\freescale\pinctrl-imx.c:int imx_pinctrl_probe(struct platform_device *pdev,struct imx_pinctrl_soc_info *info)
{struct regmap_config config = { .name = "gpr" }; // 注册映射配置,名称为 "gpr"struct device_node *dev_np = pdev->dev.of_node; // 获取设备树节点struct pinctrl_desc *imx_pinctrl_desc; // 用于描述 pinctrl 的结构体struct device_node *np; // 临时设备节点指针struct imx_pinctrl *ipctl; // IMX pinctrl 控制器实例struct resource *res; // 存储资源信息struct regmap *gpr; // 注册映射指针int ret, i; // 返回值和循环计数器// 检查传入的 pinctrl 信息是否有效if (!info || !info->pins || !info->npins) {dev_err(&pdev->dev, "wrong pinctrl info\n"); // 打印错误信息return -EINVAL; // 返回无效参数错误}info->dev = &pdev->dev; // 将设备指针保存到信息结构中// 如果存在 GPR 兼容性,则获取 GPR 的注册映射if (info->gpr_compatible) {gpr = syscon_regmap_lookup_by_compatible(info->gpr_compatible);if (!IS_ERR(gpr))regmap_attach_dev(&pdev->dev, gpr, &config); // 附加设备到注册映射}// 为驱动创建状态持有者等结构体ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL); // 分配内存if (!ipctl)return -ENOMEM; // 如果内存分配失败,返回错误// 检查是否使用 SCU(系统控制单元)if (!(info->flags & IMX8_USE_SCU)) {// 为每个引脚分配寄存器数组内存info->pin_regs = devm_kmalloc(&pdev->dev, sizeof(*info->pin_regs) *info->npins, GFP_KERNEL);if (!info->pin_regs)return -ENOMEM; // 内存分配失败,返回错误// 初始化引脚寄存器结构体for (i = 0; i < info->npins; i++) {info->pin_regs[i].mux_reg = -1; // 初始化复用寄存器info->pin_regs[i].conf_reg = -1; // 初始化配置寄存器}// 获取设备的内存资源res = platform_get_resource(pdev, IORESOURCE_MEM, 0);ipctl->base = devm_ioremap_resource(&pdev->dev, res); // 映射资源到内存if (IS_ERR(ipctl->base))return PTR_ERR(ipctl->base); // 映射失败,返回错误// 检查设备树中是否存在 "fsl,input-sel" 属性if (of_property_read_bool(dev_np, "fsl,input-sel")) {np = of_parse_phandle(dev_np, "fsl,input-sel", 0); // 解析设备树句柄if (!np) {dev_err(&pdev->dev, "iomuxc fsl,input-sel property not found\n"); // 错误信息return -EINVAL; // 返回无效参数错误}ipctl->input_sel_base = of_iomap(np, 0); // 映射输入选择寄存器of_node_put(np); // 释放设备节点if (!ipctl->input_sel_base) {dev_err(&pdev->dev,"iomuxc input select base address not found\n"); // 错误信息return -ENOMEM; // 内存不足错误}}}// 为 pinctrl 描述结构体分配内存imx_pinctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*imx_pinctrl_desc),GFP_KERNEL);if (!imx_pinctrl_desc)return -ENOMEM; // 内存分配失败,返回错误// 初始化 pinctrl 描述结构体imx_pinctrl_desc->name = dev_name(&pdev->dev); // 设置设备名称imx_pinctrl_desc->pins = info->pins; // 设置引脚信息imx_pinctrl_desc->npins = info->npins; // 设置引脚数量imx_pinctrl_desc->pctlops = &imx_pctrl_ops; // 设置 pinctrl 操作imx_pinctrl_desc->pmxops = &imx_pmx_ops; // 设置 pinmux 操作imx_pinctrl_desc->confops = &imx_pinconf_ops; // 设置 pin 配置操作imx_pinctrl_desc->owner = THIS_MODULE; // 设置模块所有者// 通过设备树初始化 pinctrl 相关属性ret = imx_pinctrl_probe_dt(pdev, info);if (ret) {dev_err(&pdev->dev, "fail to probe dt properties\n"); // 错误信息return ret; // 返回错误}// 保存信息到 pinctrl 实例中ipctl->info = info; // 保存 pinctrl 信息ipctl->dev = info->dev; // 保存设备指针platform_set_drvdata(pdev, ipctl); // 设置平台驱动数据// 注册 pinctrl 驱动ipctl->pctl = devm_pinctrl_register(&pdev->dev,imx_pinctrl_desc, ipctl);if (IS_ERR(ipctl->pctl)) {dev_err(&pdev->dev, "could not register IMX pinctrl driver\n"); // 错误信息return PTR_ERR(ipctl->pctl); // 返回错误}// 初始化成功信息dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");return 0; // 返回成功
}

3.描述、获得引脚(解析设备树)

3.1 单个引脚

img

/sys/kernel/debug/pinctrl/20e0000.iomuxc]# cat pins

这种控制器支持哪些引脚在代码中就已经写死了,而比如某个芯片中的I2C模块既支持第A组中的引脚,也支持第B组中的引脚(又或者是A组引脚既支持I2C又支持GPIO模块),这些组的引脚则通过pinctrl_ops来描述,具体看下面一点

3.2 某组引脚

在imx6ull中,组引脚的信息是在设备树中进行构造的,而在stm157中则是在代码中构造写死的

比较长,可以看下面图就,建议放大观看。

img

某组引脚中,有哪些引脚?这要分析设备树:imx_pinctrl_probe_dt。

[root@100ask:/sys/kernel/debug/pinctrl/20e0000.iomuxc]# cat pingroups

img

下面是详细的解析代码:

drivers\pinctrl\freescale\pinctrl-imx6ul.c:int imx_pinctrl_probe(struct platform_device *pdev,struct imx_pinctrl_soc_info *info)
{struct regmap_config config = { .name = "gpr" }; // 注册映射配置,名称为 "gpr"struct device_node *dev_np = pdev->dev.of_node; // 获取设备树节点struct pinctrl_desc *imx_pinctrl_desc; // 用于描述 pinctrl 的结构体// 。。。。。。。。。。。。。。// 为 pinctrl 描述结构体分配内存imx_pinctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*imx_pinctrl_desc),GFP_KERNEL);if (!imx_pinctrl_desc)return -ENOMEM; // 内存分配失败,返回错误// 初始化 pinctrl 描述结构体imx_pinctrl_desc->name = dev_name(&pdev->dev); // 设置设备名称imx_pinctrl_desc->pins = info->pins; // 设置引脚信息imx_pinctrl_desc->npins = info->npins; // 设置引脚数量imx_pinctrl_desc->pctlops = &imx_pctrl_ops; // 设置 pinctrl 操作imx_pinctrl_desc->pmxops = &imx_pmx_ops; // 设置 pinmux 操作imx_pinctrl_desc->confops = &imx_pinconf_ops; // 设置 pin 配置操作imx_pinctrl_desc->owner = THIS_MODULE; // 设置模块所有者// 通过设备树初始化 pinctrl 相关属性ret = imx_pinctrl_probe_dt(pdev, info);if (ret) {dev_err(&pdev->dev, "fail to probe dt properties\n"); // 错误信息return ret; // 返回错误}//。。。。。。。。。。。。。。。。。
}

ret = imx_pinctrl_probe_dt(pdev, info);,设备树中组引脚的解析和信息提取主要是在该函数中。其中参2为info,为struct imx_pinctrl_soc_info *类型的,解析该函数钱需要讲解一下该结构体

3.2.1 imx_pinctrl_soc_info结构体

解析后的引脚的组信息会存放在info中

\Linux-4.9.88\drivers\pinctrl\freescale\pinctrl-imx.h:
// 用于描述 IMX 平台的 Pin 控制器的结构体
struct imx_pinctrl_soc_info {struct device *dev;               // 设备指针,指向使用该 pinctrl 的设备const struct pinctrl_pin_desc *pins; // 指向描述每个 pin 的数组,包含每个引脚的详细信息unsigned int npins;               // 引脚数量,表示 pins 数组中的元素数struct imx_pin_reg *pin_regs;     // 指向该 SoC 使用的寄存器地址映射结构struct imx_pin_group *groups;     // 描述各个引脚组的数组指针,每个组包含一组引脚配置unsigned int ngroups;             // 引脚组数量,即 groups 数组的元素数量unsigned int group_index;         // 引脚组的索引,用于指示当前配置的组struct imx_pmx_func *functions;   // 指向支持的引脚复用功能的数组指针unsigned int nfunctions;          // 支持的复用功能数量,即 functions 数组的元素数量unsigned int flags;               // 标志位,用于存储当前 pin 控制器的特殊设置或配置const char *gpr_compatible;       // 指向字符串,用于设备树兼容性匹配 (GPR) 的信息/* 当存在共享 MUX 和 CONF 寄存器的情况时,下面的字段用于控制 */unsigned int mux_mask;            // MUX_MODE 的掩码值,用于提取和设置特定位u8 mux_shift;                     // MUX_MODE 的位移值,用于确定 mux_mask 应应用的位位置u32 ibe_bit;                      // 用于配置输入缓冲区使能 (Input Buffer Enable) 的位掩码u32 obe_bit;                      // 用于配置输出缓冲区使能 (Output Buffer Enable) 的位掩码
};

下面是其相关成员的介绍:

  1. struct imx_pin_group *groups: 在 i.MX 平台中定义一个引脚组的集合,该集合中的引脚通常是具有特定功能需求或用途相关的。例如,某些引脚组用于 UART 功能,而另一些用于 SPI、I2C 等功能。通过这种分组,便于对相关引脚的统一配置和管理,同时可以通过 pinctrl 框架将一组引脚配置为同一功能,方便驱动和上层应用进行访问和配置。 这是一个数据指针类型的,也就是说引脚有多少组就该结构体有多少个
/*** struct imx_pin_group - 描述一个 i.MX 平台的引脚组(pin group)* @name: 引脚组名称*        用于标识该引脚组的名称(字符指针),通常用于调试或配置时参考。* * @npins: 引脚组中的引脚数量*         表示引脚组中的引脚数,即 .pins 数组中的元素数量。*         可以根据该值循环遍历 pins 数组中的元素。* * @pin_ids: 引脚组中每个引脚的 ID 数组*           一个存储每个引脚 ID 的数组(unsigned int* 类型),*           是 `pinctrl` 子系统所要求维护的,用于将每个引脚与其特定 ID 进行关联。*           引脚 ID 可以帮助查找和操作每个引脚的具体配置。* * @pins: 引脚数组*        一个 `struct imx_pin` 类型的数组,存储该引脚组中每个引脚的具体信息。*        该数组的每个元素对应引脚组中的一个引脚,其结构中可能包括引脚的复用、*        功能、驱动强度等详细配置。*/
struct imx_pin_group {const char *name;           // 引脚组的名称,用于标识该组unsigned npins;             // 引脚组中包含的引脚数量unsigned int *pin_ids;      // 引脚 ID 数组,用于引用每个引脚的唯一标识struct imx_pin *pins;       // 引脚数组,存储每个引脚的详细配置
};

其中imx_pin结构体,存储每个引脚的详细配置,它是数组类型。 通过 struct imx_pin,可以配置一个引脚的复用模式、电气特性等参数,适配不同的硬件平台(如基于内存映射或 SCU 管理的硬件)。imx_pin_memmapimx_pin_scu 为不同硬件平台提供了所需的配置结构体,确保在驱动开发中可以灵活地配置引脚功能和特性:

/*** struct imx_pin - 描述单个 i.MX 平台的引脚配置* @pin: 引脚的编号或 ID*       表示该引脚在整个引脚控制器(pinctrl)系统中的唯一标识符,*       用于在设置时引用特定的引脚。** @pin_conf: 引脚的配置信息,具体使用哪种结构视硬件平台而定*            使用共用体(union)来存储引脚配置,有两种配置结构体可选:*            1. `imx_pin_memmap` - 内存映射的配置(适用于较旧的 i.MX 硬件)*            2. `imx_pin_scu` - SCU 配置(适用于较新的 SCU 管理的 i.MX 硬件)*/
struct imx_pin {unsigned int pin;                // 引脚编号或 IDunion {struct imx_pin_memmap pin_memmap;  // 内存映射的引脚配置struct imx_pin_scu pin_scu;        // SCU 管理的引脚配置} pin_conf;                       // 选择合适的引脚配置结构
};/*** struct imx_pin_memmap - 描述基于内存映射的引脚配置(较旧的硬件平台)* @mux_mode: 复用模式*            设置引脚的功能复用模式,例如将该引脚配置为 UART、SPI、GPIO 等。*            不同的值对应不同的功能或信号通道。** @input_reg: 输入控制寄存器*             引脚的输入控制寄存器(16 位),用于配置引脚的输入特性,*             比如输入延迟或电平触发控制。** @input_val: 输入寄存器的值*             具体的输入控制值,决定输入配置的具体参数。设置引脚的输入配置时参考此值。** @config: 引脚的通用配置寄存器*          该寄存器的值用于设置引脚的电气特性和行为,如驱动强度、上拉/下拉电阻等。*/
struct imx_pin_memmap {unsigned int mux_mode;       // 引脚复用模式u16 input_reg;               // 输入控制寄存器unsigned int input_val;      // 输入寄存器值unsigned long config;        // 通用配置寄存器,用于电气特性设置
};/*** struct imx_pin_scu - 描述基于 SCU 管理的引脚配置(较新硬件平台)* @mux: 复用模式寄存器*       类似于 mux_mode,但用于 SCU 管理的硬件上。不同值代表不同功能复用。** @config: 通用配置寄存器*          用于设置引脚的电气特性和配置选项,包括驱动强度、上拉/下拉等。*          与 SCU 兼容的配置选项通常通过该寄存器控制。*/
struct imx_pin_scu {unsigned long mux;           // 复用模式寄存器,SCU 管理的硬件专用unsigned long config;        // 通用配置寄存器,SCU 兼容的电气特性设置
};
  • img
  • img
  • 以该组引脚为例子,其中一个印记哦MX6UL_PAD_UART1_RTS_B_GPIO1_IO19 0X17059,最后就是会被解析成imx_pin_memmap
  1. 回到imx_pinctrl_soc_info结构体,接下来讲一下其成员struct imx_pmx_func *functionsimx_pmx_func 结构体用于定义 i.MX 平台的 pinmux 功能(pin multiplexing function)。在嵌入式系统中,一个引脚通常具有多种复用功能(如 GPIO、I2C、SPI 等),通过定义 imx_pmx_func,驱动程序可以描述每个特定功能所需要的引脚组,从而在硬件和软件层面实现该功能。
/*** struct imx_pmx_func - 描述 i.MX 平台的 pinmux 功能* @name: 该功能的名称*        此字段用于标识特定的引脚复用(pinmux)功能。例如,可以命名为*        `i2c_func`、`spi_func` 等,以表示与不同外设关联的功能名称。** @groups: 关联的引脚组*          指向引脚组名称的字符串数组,表示执行该功能所需的引脚组。每个引脚组*          可以包含多个引脚,用于实现该功能的完整硬件连接。** @num_groups: 引脚组的数量*              该字段指定 `groups` 数组中的引脚组数量,用于迭代处理数组中的每个引脚组。*/
struct imx_pmx_func {const char *name;         // 功能的名称,标识具体的 pinmux 功能const char **groups;      // 对应的引脚组,指向该功能相关的引脚组名称数组unsigned num_groups;      // 引脚组的数量,指定 `groups` 数组中的元素个数
};

3.2.2 结构体关联图

img

3.2.3 回到函数解析

用到的设备树示例:

  • img

\Linux-4.9.88\drivers\pinctrl\freescale\pinctrl-imx.c

回到上文提到的imx_pinctrl_probe函数中,其中调用了imx_pinctrl_probe_dt函数,下面对该函数拆开来讲解:该设备树解析函数 imx_pinctrl_probe_dt 是用于解析 i.MX 平台的设备树节点(Device Tree Node),并从中获取引脚控制的配置信息,存储在 imx_pinctrl_soc_info 结构体中。下面逐步解析这段代码如何对应到您设备树的内容。

static int imx_pinctrl_probe_dt(struct platform_device *pdev,struct imx_pinctrl_soc_info *info)
{struct device_node *np = pdev->dev.of_node; // 获取设备树节点struct device_node *child;u32 nfuncs = 0;u32 i = 0;bool flat_funcs;if (!np)return -ENODEV;
  • np = pdev->dev.of_node;:获取当前设备(即 pdev)在设备树中的节点(对应您设备树中的 imx6ul-evk 节点)。
  1. 判断函数结构
    flat_funcs = imx_pinctrl_dt_is_flat_functions(np); // 检查函数结构if (flat_funcs) {nfuncs = 1;} else {nfuncs = of_get_child_count(np);if (nfuncs <= 0) {dev_err(&pdev->dev, "no functions defined\n");return -EINVAL;}}
  • imx_pinctrl_dt_is_flat_functions(np):检查函数是否以“平面”方式定义。如果 flat_funcs 为真,则表示函数定义是平面的,例如,所有引脚组在一个层级中定义,而不再划分不同的子节点。
  • nfuncs = of_get_child_count(np);:如果不是平面结构,计算 np 节点的子节点数,代表有多少个不同的功能模块(对应 imx6ul-evk 下的子节点,如 hdmigrphoggrp-1enetgrp 等每个模块分别代表一个功能组)。
  • 其实就是看设备树节点中有没有"fsl,pin",以上面的设备树为例子是有的,因此是非平面结构体,其解析方式的函数如下:
static bool imx_pinctrl_dt_is_flat_functions(struct device_node *np)
{struct device_node *function_np; // 用于存储 np 节点的子节点struct device_node *pinctrl_np;  // 用于存储 function_np 节点的子节点for_each_child_of_node(np, function_np) { // 遍历 np 的每个直接子节点if (of_property_read_bool(function_np, "fsl,pins"))return true; // 如果直接子节点包含 "fsl,pins" 属性,返回 true// 遍历 function_np 的每个子节点for_each_child_of_node(function_np, pinctrl_np) {if (of_property_read_bool(pinctrl_np, "fsl,pins"))return false; // 如果找到 "fsl,pins" 在 function_np 的子节点中,返回 false}}return true; // 如果遍历完没有发现嵌套结构,返回 true
}
  1. 分配内存空间
    info->nfunctions = nfuncs;info->functions = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pmx_func),GFP_KERNEL);if (!info->functions)return -ENOMEM;info->group_index = 0;if (flat_funcs) {info->ngroups = of_get_child_count(np);} else {info->ngroups = 0;for_each_child_of_node(np, child)info->ngroups += of_get_child_count(child);}
  • info->nfunctions = nfuncs;:将功能数量保存到 imx_pinctrl_soc_infonfunctions 字段。
  • info->functions 分配内存用于保存各功能的信息。
  • info->ngroups:若为平面结构,则直接获取节点 np 的子节点数;若非平面结构,遍历每个子节点,统计所有子节点的引脚组数量。

3.解析函数与引脚组

img

    info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct imx_pin_group),GFP_KERNEL);if (!info->groups)return -ENOMEM;if (flat_funcs) {imx_pinctrl_parse_functions(np, info, 0);} else {for_each_child_of_node(np, child)imx_pinctrl_parse_functions(child, info, i++);}return 0;
}
  • info->groups:分配用于保存引脚组信息的内存。

  • imx_pinctrl_parse_functions:根据是否为平面结构,选择性地解析功能:

    • 如果是平面结构,则直接解析 np 下的所有引脚组。
    • 如果非平面结构,则遍历 np 的每个子节点(即 imx6ul-evk 下的各功能组节点),分别解析。

img

4.总结

该函数imx_pinctrl_probe_dt主要是根据 imx6ul-evk 下的节点结构来设置功能和引脚组信息,并将这些信息填充到 imx_pinctrl_soc_info 结构体中,便于后续引脚复用的配置。

图中 hoggrp-1hdmigrp 等子节点被解析为各个功能组,fsl,pins 属性用于指定每个功能组内具体的引脚配置。

4.引脚复用和配置

引脚复用和引脚配置在 client端使用pinctrl过程的情景分析 中讲解,也就是下一章节,一般是由client的驱动程序来去调用相关函数实现的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/462454.html

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

相关文章

第十五章 Vue工程化开发及Vue CLI脚手架

目录 一、引言 二、Vue CLI 基本介绍 三、安装Vue CLI 3.1. 安装npm和yarn 3.2. 安装Vue CLI 3.3. 查看 Vue 版本 四、创建启动工程 4.1. 创建项目架子 4.2. 启动工程 五、脚手架目录文件介绍 六、核心文件讲解 6.1. index.html 6.2. main.js 6.3. App.vue 一、…

Rust 力扣 - 2841. 几乎唯一子数组的最大和

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们遍历长度为k的窗口&#xff0c;用一个哈希表记录窗口内的所有元素&#xff08;用来对窗口内元素去重&#xff09;&#xff0c;我们取哈希表中元素数量大于等于m的窗口总和的最大值 题解代码 use std::coll…

Python数据分析案例61——信贷风控评分卡模型(A卡)(scorecardpy 全面解析)

案例背景 虽然在效果上&#xff0c;传统的逻辑回归模型通常不如现代的机器学习模型&#xff0c;但在风控领域&#xff0c;解释性至关重要。逻辑回归的解释性是这些“黑箱”模型所无法比拟的&#xff0c;因此&#xff0c;研究传统的评分卡模型依然是有意义的。 传统的评分卡模型…

免费送源码:Java+Springboot+MySQL Springboot酒店客房管理系统的设计与实现 计算机毕业设计原创定制

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对酒店客房管理等问题&#xff0c;对酒店客房…

力扣每日一题 超级饮料的最大强化能量 动态规划(dp)

来自未来的体育科学家给你两个整数数组 energyDrinkA 和 energyDrinkB&#xff0c;数组长度都等于 n。这两个数组分别代表 A、B 两种不同能量饮料每小时所能提供的强化能量。 你需要每小时饮用一种能量饮料来 最大化 你的总强化能量。然而&#xff0c;如果从一种能量饮料切换到…

Linux高阶——1027—守护进程

1、守护进程的基本流程 1、父进程创建子进程&#xff0c;父进程退出 守护进程是孤儿进程&#xff0c;但是是工程师人为创建的孤儿进程&#xff0c;低开销模式运行&#xff0c;对系统没有压力 2、子进程&#xff08;守护进程&#xff09;脱离控制终端&#xff0c;创建新会话 …

抗疫物资管理:SpringBoot技术应用案例

目 录 摘 要 1 前 言 2 第1章 概述 2 1.1 研究背景 3 1.2 研究目的 3 1.3 研究内容 4 第二章 开发技术介绍 5 2.1相关技术 5 2.2 Java技术 6 2.3 MySQL数据库 6 2.4 Tomcat介绍 7 2.5 Spring Boot框架 8 第三章 系统分析 9 3.1 可行性分析 9 3.1.1 技术可行性 9 3.1.2 经济可行…

pandas——数据结构

一、series &#xff08;一&#xff09;创建series import pandas as pd#1.使用列表或数组创建Series # 使用列表创建Series&#xff0c;索引默认从0开始 s1 pd.Series([1, 2, 3]) print(s1) # 使用列表和自定义索引创建Series s2 pd.Series([1, 2, 3], index[a, b, c]) pr…

MySQL的SQL语句之触发器的创建和应用

触发器 Trigger 一.触发器 作用&#xff1a;当检测到某种数据表发生数据变化时&#xff0c;自动执行操作&#xff0c;保证数据的完整性&#xff0c;保证数据的一致性。 1.创建一个触发器 如上图所示&#xff0c;查看这个create的帮助信息的时候&#xff0c;这个create trig…

服务器数据恢复—DELL EqualLogic PS6100系列存储简介及如何收集故障信息?

DELL EqualLogic PS6100系列存储采用虚拟ISCSI SAN阵列&#xff0c;支持VMware、Solaris、Linux、Mac、HP-UX、AIX操作系统&#xff0c;提供全套企业级数据保护和管理功能&#xff0c;具有可扩展性和容错功能。DELL EqualLogic PS6100系列存储介绍&#xff1a; 1、上层应用基础…

什么是无限钱包系统?有什么优势?

在数字货币风起云涌的今天&#xff0c;一个名为“无限钱包系统”的创新平台正悄然引领着行业的变革。它不仅重新定义了数字资产的管理方式&#xff0c;更以卓越的安全性、便捷的操作体验以及前瞻性的技术理念&#xff0c;成为了广大数字货币爱好者心中的理想之选。 一、数字货币…

API网关 - JWT认证 ; 原理概述与具体实践样例

API网关主要提供的能力&#xff0c;就是协议转换&#xff0c;安全&#xff0c;限流等能力。 本文主要是分享 如何基于API网关实现 JWT 认证 。 包含了JWT认证的流程&#xff0c;原理&#xff0c;与具体的配置样例 API网关认证的重要性 在现代Web应用和微服务架构中&#x…

前端加密解密

一、 AES 加密与解密 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。是一种对称加密算法也就是加密和解密用相同的密钥; 1.1 使用 crypto-js 实现 AES 加密 1.1.1 参数说明 data 要加密的明文key 秘钥iv …

基于知识引导提示的因果概念提取(论文复现)

基于知识引导提示的因果概念提取(论文复现) 本文所涉及所有资源均在传知代码平台可获取 文章目录 基于知识引导提示的因果概念提取(论文复现)论文概述论文方法提示构造器获取典型概念集聚类典型概念构建训练数据训练主题分类器概念提取器输入构造指针网络置信度评分训练损失…

【element ui系列】分享几种实现el-table表格单选的方法

在实际的开发中&#xff0c;经常会用到从表格中选择一条记录的情况&#xff0c;虽然官方给出的例子&#xff0c;但是给人感觉看起来不明显&#xff0c;于是&#xff0c;在此基础上做了改进。接下来&#xff0c;介绍两种常见的实现方法&#xff1a; 1、采用复选框(checkbox)实现…

63 mysql 的 行锁

前言 我们这里来说的就是 我们在 mysql 这边常见的 几种锁 行共享锁, 行排他锁, 表意向共享锁, 表意向排他锁, 表共享锁, 表排他锁 意向共享锁, 意向排他锁, 主要是 为了表粒度的锁获取的同步判断, 提升效率 意向共享锁, 意向排他锁 这边主要的逻辑意义是数据表中是否有任…

江协科技STM32学习- P26 UART串口外设

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

使用 ADB 在某个特定时间点点击 Android 设备上的某个按钮

前提条件 安装 ADB&#xff1a;确保你已经在计算机上安装了 Android SDK&#xff08;或单独的 ADB&#xff09;。并将其添加到系统环境变量中&#xff0c;以便你可以在命令行中运行 adb。 USB调试&#xff1a;确保 Android 设备已启用 USB 调试模式。这可以在设备的“设置” -…

mint-ui Picker 显示异常

mint-ui Picker 显示异常 现象 最近一个老项目页面显示异常&#xff0c;使用mint-ui Picker显示异常,直接显示成了 数据对象&#xff0c;而不是具体travelName 字段 组件 mint-ui Picker 使用方式(vue方式) // template <mt-picker :slots"slots" value-key…

FastAPI性能对比:同步vs异步

大家好&#xff0c;FastAPI已成为构建Python API的最流行框架之一&#xff0c;因其速度和易用性而广受欢迎。但在构建高性能应用程序时&#xff0c;使用同步&#xff08;sync&#xff09;还是异步&#xff08;async&#xff09;代码执行是很重要的问题。本文将通过现实世界的性…