dwc3控制器是怎么处理otg

news/2024/5/10 17:03:50

概念

在OTG中,初始主机设备称为A设备,外设称为B设备。可用电缆的连接方式来决定初始角色。两用设备使用新型Mini-AB插座,从而使Mini-A插头、Mini-B插头和Mini-AB插座增添了第5个引脚(ID),以用于识别不同的电缆端点。Mini-A插头中的ID引脚接地,Mini-B插头中的ID引脚浮空。当OTG设备检测到接地的ID引脚时,表示默认的是A设备(主机),而检测到ID引脚浮空的设备则认为是B设备(外设)。系统一旦连接后,OTG的角色还可以更换,以采用新的HNP协议。而SRP允许B设备请求A设备打开VBUS电源并启动一次对话。

设备树

我们直接看支持otg的dwc3是怎么处理otg的,从设备开始看驱动,usb3_0的这个节点一般就是厂商自己定义的,主要包括中断,一般用于vbus检测,usb的插拔情况;dwc3_0这个子节点就是通用的dwc3核心,主要包括中断,一般用于id脚的检测,来判断当前是设备还是主机;如果dr_mode设置了模式,就会用固定的模式去初始化控制器

usb3phy: usb3phy@c0030000 {compatible = "usb3-phy";reg = <0xc0030000 0x1000>;clocks = <&soc_clocks CLK_USB>;clock-names = "usb_clk";status = "disabled";
};
usb3_0: usb3-0 {compatible = "arch,dwc3";#address-cells = <1>;#size-cells = <1>;ranges;interrupts = <53>;clocks = <&soc_clocks CLK_USB>;clock-names = "usb_clk";status = "disabled";usb_dwc3_0: dwc31@c0000000 {compatible = "snps,dwc3";reg = <0xc0000000 0x11000>;interrupts = <44>;usb-phy = <&usb3phy>;maximum-speed = "super-speed";dr_mode = "peripheral";phy_type = "utmi";lpm-qos = <PM_QOS_CPUIDLE_BLOCK_AXI>;snps,dis_u3_susphy_quirk;/* allow-suspend; */status = "okay";};
};

驱动框架

设备树跟驱动match后,会执行dwc3_probe;主要是一些初始化操作,如果设置了dr_mode为peripheral,就调用dwc_gadget_init去初始化设备控制器;dr_mode为host,就调用dwc3_host_init去初始化为主机控制器;如果dr_mode为otg,就根据id的情况去初始化为主机或设备

dwc3_probedwc3_get_dr_modedwc3_core_initdwc3_debugfs_initdwc3_core_init_mode//根据模式进入一种dwc3_gadget_initdwc->gadget.ops	= &dwc3_gadget_ops;//初始化设备控制器操作函数dwc3_gadget_init_endpoints(dwc, dwc->num_eps);dep->endpoint.ops = &dwc3_gadget_ep_ops;usb_add_gadget_udc(dwc->dev, &dwc->gadget);//注册设备控制器dwc3_host_initxhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);platform_device_add(xhci)//初始化xhci平台设备;用于匹配到usb_xhci_driver-----其probe来初始化主机控制器,填充操作函数xhci_hc_driver,并注册主机控制器dwc3_drd_initrequest_threaded_irq(dwc->otg_irq, dwc3_otg_irq,dwc3_otg_thread_irq,IRQF_SHARED, "dwc3-otg", dwc);dwc3_set_mode__dwc3_set_modedwc3_otg_update//根据模式进入一种dwc3_host_initdwc3_gadget_init

主机控制器的初始化

上面的代码分析到:dwc3_host_init会通过 platform_device_add(xhci)//初始化xhci平台设备;用于匹配到usb_xhci_driver-----其probe来初始化主机控制器,填充操作函数xhci_hc_driver,并注册主机控制器

drivers/usb/host/xhci-plat.c中的usb_xhci_driver通过name(xhci-hcd)匹配上;xhci_init_driver将通用的xhci_hc_driver,赋值给xhci_plat_hc_driver;过程跟ehci_init_driver一致

static int xhci_plat_probe(struct platform_device *pdev)
{const struct xhci_plat_priv *priv_match;const struct hc_driver	*driver;struct device		*sysdev, *tmpdev;struct xhci_hcd		*xhci;struct resource         *res;struct usb_hcd		*hcd;int			ret;int			irq;struct xhci_plat_priv	*priv = NULL;if (usb_disabled())return -ENODEV;driver = &xhci_plat_hc_driver;irq = platform_get_irq(pdev, 0);if (irq < 0)return irq;/** sysdev must point to a device that is known to the system firmware* or PCI hardware. We handle these three cases here:* 1. xhci_plat comes from firmware* 2. xhci_plat is child of a device from firmware (dwc3-plat)* 3. xhci_plat is grandchild of a pci device (dwc3-pci)*/for (sysdev = &pdev->dev; sysdev; sysdev = sysdev->parent) {if (is_of_node(sysdev->fwnode) ||is_acpi_device_node(sysdev->fwnode))break;
#ifdef CONFIG_PCIelse if (sysdev->bus == &pci_bus_type)break;
#endif}if (!sysdev)sysdev = &pdev->dev;/* Try to set 64-bit DMA first */if (WARN_ON(!sysdev->dma_mask))/* Platform did not initialize dma_mask */ret = dma_coerce_mask_and_coherent(sysdev,DMA_BIT_MASK(64));elseret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(64));/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */if (ret) {ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(32));if (ret)return ret;}pm_runtime_set_active(&pdev->dev);pm_runtime_enable(&pdev->dev);pm_runtime_get_noresume(&pdev->dev);hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,dev_name(&pdev->dev), NULL);if (!hcd) {ret = -ENOMEM;goto disable_runtime;}res = platform_get_resource(pdev, IORESOURCE_MEM, 0);hcd->regs = devm_ioremap_resource(&pdev->dev, res);if (IS_ERR(hcd->regs)) {ret = PTR_ERR(hcd->regs);goto put_hcd;}hcd->rsrc_start = res->start;hcd->rsrc_len = resource_size(res);xhci = hcd_to_xhci(hcd);/** Not all platforms have clks so it is not an error if the* clock do not exist.*/xhci->reg_clk = devm_clk_get_optional(&pdev->dev, "reg");if (IS_ERR(xhci->reg_clk)) {ret = PTR_ERR(xhci->reg_clk);goto put_hcd;}ret = clk_prepare_enable(xhci->reg_clk);if (ret)goto put_hcd;xhci->clk = devm_clk_get_optional(&pdev->dev, NULL);if (IS_ERR(xhci->clk)) {ret = PTR_ERR(xhci->clk);goto disable_reg_clk;}ret = clk_prepare_enable(xhci->clk);if (ret)goto disable_reg_clk;priv_match = of_device_get_match_data(&pdev->dev);if (priv_match) {priv = hcd_to_xhci_priv(hcd);/* Just copy data for now */if (priv_match)*priv = *priv_match;}device_wakeup_enable(hcd->self.controller);xhci->main_hcd = hcd;xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,dev_name(&pdev->dev), hcd);if (!xhci->shared_hcd) {ret = -ENOMEM;goto disable_clk;}/* imod_interval is the interrupt moderation value in nanoseconds. */xhci->imod_interval = 40000;/* Iterate over all parent nodes for finding quirks */for (tmpdev = &pdev->dev; tmpdev; tmpdev = tmpdev->parent) {if (device_property_read_bool(tmpdev, "usb2-lpm-disable"))xhci->quirks |= XHCI_HW_LPM_DISABLE;if (device_property_read_bool(tmpdev, "usb3-lpm-capable"))xhci->quirks |= XHCI_LPM_SUPPORT;if (device_property_read_bool(tmpdev, "quirk-broken-port-ped"))xhci->quirks |= XHCI_BROKEN_PORT_PED;device_property_read_u32(tmpdev, "imod-interval-ns",&xhci->imod_interval);}hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);if (IS_ERR(hcd->usb_phy)) {ret = PTR_ERR(hcd->usb_phy);if (ret == -EPROBE_DEFER)goto put_usb3_hcd;hcd->usb_phy = NULL;} else {ret = usb_phy_init(hcd->usb_phy);if (ret)goto put_usb3_hcd;}hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);xhci->shared_hcd->tpl_support = hcd->tpl_support;if (priv) {ret = xhci_priv_plat_setup(hcd);if (ret)goto disable_usb_phy;}if ((xhci->quirks & XHCI_SKIP_PHY_INIT) || (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)))hcd->skip_phy_initialization = 1;ret = usb_add_hcd(hcd, irq, IRQF_SHARED);if (ret)goto disable_usb_phy;if (HCC_MAX_PSA(xhci->hcc_params) >= 4)xhci->shared_hcd->can_do_streams = 1;ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);if (ret)goto dealloc_usb2_hcd;device_enable_async_suspend(&pdev->dev);pm_runtime_put_noidle(&pdev->dev);/** Prevent runtime pm from being on as default, users should enable* runtime pm using power/control in sysfs.*/pm_runtime_forbid(&pdev->dev);return 0;
....
}
static struct platform_driver usb_xhci_driver = {.probe	= xhci_plat_probe,.remove	= xhci_plat_remove,.shutdown = usb_hcd_platform_shutdown,.driver	= {.name = "xhci-hcd",.pm = &xhci_plat_pm_ops,.of_match_table = of_match_ptr(usb_xhci_of_match),.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),},
};
MODULE_ALIAS("platform:xhci-hcd");static int __init xhci_plat_init(void)
{xhci_init_driver(&xhci_plat_hc_driver, &xhci_plat_overrides);return platform_driver_register(&usb_xhci_driver);
}
module_init(xhci_plat_init);static void __exit xhci_plat_exit(void)
{platform_driver_unregister(&usb_xhci_driver);
}
module_exit(xhci_plat_exit);

dwc3_core_init_mode

dwc3_core_init_mode根据设备树获得的模式,初始化控制器为对应模式,初始化控制器的操作函数:主机有主机的操作函数;设备有设备的操作函数

static int dwc3_core_init_mode(struct dwc3 *dwc)
{struct device *dev = dwc->dev;int ret;switch (dwc->dr_mode) {case USB_DR_MODE_PERIPHERAL:dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);if (dwc->usb2_phy)otg_set_vbus(dwc->usb2_phy->otg, false);phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);ret = dwc3_gadget_init(dwc);if (ret) {if (ret != -EPROBE_DEFER)dev_err(dev, "failed to initialize gadget\n");return ret;}break;case USB_DR_MODE_HOST:dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);if (dwc->usb2_phy)otg_set_vbus(dwc->usb2_phy->otg, true);phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);ret = dwc3_host_init(dwc);if (ret) {if (ret != -EPROBE_DEFER)dev_err(dev, "failed to initialize host\n");return ret;}break;case USB_DR_MODE_OTG:INIT_WORK(&dwc->drd_work, __dwc3_set_mode);ret = dwc3_drd_init(dwc);if (ret) {if (ret != -EPROBE_DEFER)dev_err(dev, "failed to initialize dual-role\n");return ret;}break;default:dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);return -EINVAL;}return 0;
}

OTG模式

注册中断

一般是通过id脚注册中断:use OTG block to get ID event

int dwc3_drd_init(struct dwc3 *dwc)
{int ret, irq;dwc->edev = dwc3_get_extcon(dwc);if (IS_ERR(dwc->edev))return PTR_ERR(dwc->edev);if (ROLE_SWITCH &&device_property_read_bool(dwc->dev, "usb-role-switch")) {ret = dwc3_setup_role_switch(dwc);if (ret < 0)return ret;} else if (dwc->edev) {dwc->edev_nb.notifier_call = dwc3_drd_notifier;ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,&dwc->edev_nb);if (ret < 0) {dev_err(dwc->dev, "couldn't register cable notifier\n");return ret;}dwc3_drd_update(dwc);} else {dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG);dwc->current_dr_role = DWC3_GCTL_PRTCAP_OTG;/* use OTG block to get ID event */irq = dwc3_otg_get_irq(dwc);if (irq < 0)return irq;dwc->otg_irq = irq;/* disable all OTG IRQs */dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);/* clear all events */dwc3_otg_clear_events(dwc);ret = request_threaded_irq(dwc->otg_irq, dwc3_otg_irq,dwc3_otg_thread_irq,IRQF_SHARED, "dwc3-otg", dwc);if (ret) {dev_err(dwc->dev, "failed to request irq #%d --> %d\n",dwc->otg_irq, ret);ret = -ENODEV;return ret;}dwc3_otg_init(dwc);dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);}return 0;
}

中断处理

根据id脚的状态,判断是做主机还是设备

static irqreturn_t dwc3_otg_irq(int irq, void *_dwc)
{u32 reg;struct dwc3 *dwc = _dwc;irqreturn_t ret = IRQ_NONE;reg = dwc3_readl(dwc->regs, DWC3_OEVT);if (reg) {/* ignore non OTG events, we can't disable them in OEVTEN */if (!(reg & DWC3_OTG_ALL_EVENTS)) {dwc3_writel(dwc->regs, DWC3_OEVT, reg);return IRQ_NONE;}if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST &&!(reg & DWC3_OEVT_DEVICEMODE))dwc->otg_restart_host = 1;dwc3_writel(dwc->regs, DWC3_OEVT, reg);ret = IRQ_WAKE_THREAD;}return ret;
}

可以看作中断下半部,来通过dwc3_set_mode将控制器初始化为主机或者设备

static irqreturn_t dwc3_otg_thread_irq(int irq, void *_dwc)
{struct dwc3 *dwc = _dwc;spin_lock(&dwc->lock);if (dwc->otg_restart_host) {dwc3_otg_host_init(dwc);dwc->otg_restart_host = 0;}spin_unlock(&dwc->lock);dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);return IRQ_HANDLED;
}void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
{unsigned long flags;spin_lock_irqsave(&dwc->lock, flags);dwc->desired_dr_role = mode;spin_unlock_irqrestore(&dwc->lock, flags);queue_work(system_freezable_wq, &dwc->drd_work);
}

设置模式

模式设置的是设备或者主机,就直接调用dwc3_gadget_init或者dwc3_host_init初始化控制器;如果是otg模式,就要根据dwc3_otg_update去判断id脚的情况来更新为设备或者主机

static void __dwc3_set_mode(struct work_struct *work)
{struct dwc3 *dwc = work_to_dwc(work);unsigned long flags;int ret;u32 reg;if (dwc->dr_mode != USB_DR_MODE_OTG)return;if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG)dwc3_otg_update(dwc, 0);if (!dwc->desired_dr_role)return;if (dwc->desired_dr_role == dwc->current_dr_role)return;if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev)return;switch (dwc->current_dr_role) {case DWC3_GCTL_PRTCAP_HOST:dwc3_host_exit(dwc);break;case DWC3_GCTL_PRTCAP_DEVICE:dwc3_gadget_exit(dwc);dwc3_event_buffers_cleanup(dwc);break;case DWC3_GCTL_PRTCAP_OTG:dwc3_otg_exit(dwc);spin_lock_irqsave(&dwc->lock, flags);dwc->desired_otg_role = DWC3_OTG_ROLE_IDLE;spin_unlock_irqrestore(&dwc->lock, flags);dwc3_otg_update(dwc, 1);break;default:break;}spin_lock_irqsave(&dwc->lock, flags);dwc3_set_prtcap(dwc, dwc->desired_dr_role);spin_unlock_irqrestore(&dwc->lock, flags);switch (dwc->desired_dr_role) {case DWC3_GCTL_PRTCAP_HOST:ret = dwc3_host_init(dwc);if (ret) {dev_err(dwc->dev, "failed to initialize host\n");} else {if (dwc->usb2_phy)otg_set_vbus(dwc->usb2_phy->otg, true);phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);if (dwc->dis_split_quirk) {reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);reg |= DWC3_GUCTL3_SPLITDISABLE;dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);dwc3_save_controller_regs(DWC3_GUCTL3, reg);}}break;case DWC3_GCTL_PRTCAP_DEVICE:dwc3_event_buffers_setup(dwc);if (dwc->usb2_phy)otg_set_vbus(dwc->usb2_phy->otg, false);phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);ret = dwc3_gadget_init(dwc);if (ret)dev_err(dwc->dev, "failed to initialize peripheral\n");break;case DWC3_GCTL_PRTCAP_OTG:dwc3_otg_init(dwc);dwc3_otg_update(dwc, 0);break;default:break;}
}

更新模式

ignore_idstatus为0,就回去读id相关寄存器,获取id脚的状态desired_otg_role;为高就是DWC3_OTG_ROLE_DEVICE,为低就是DWC3_OTG_ROLE_HOST;跟current_otg_role一样就返回,不一样就关掉当前的控制器,初始化为desired_otg_role的控制器模式

void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus)
{int ret;u32 reg;int id;unsigned long flags;if (dwc->dr_mode != USB_DR_MODE_OTG)return;/* don't do anything if debug user changed role to not OTG */if (dwc->current_dr_role != DWC3_GCTL_PRTCAP_OTG)return;if (!ignore_idstatus) {reg = dwc3_readl(dwc->regs, DWC3_OSTS);id = !!(reg & DWC3_OSTS_CONIDSTS);dwc->desired_otg_role = id ? DWC3_OTG_ROLE_DEVICE :DWC3_OTG_ROLE_HOST;}if (dwc->desired_otg_role == dwc->current_otg_role)return;switch (dwc->current_otg_role) {case DWC3_OTG_ROLE_HOST:dwc3_host_exit(dwc);spin_lock_irqsave(&dwc->lock, flags);dwc3_otg_host_exit(dwc);spin_unlock_irqrestore(&dwc->lock, flags);break;case DWC3_OTG_ROLE_DEVICE:dwc3_gadget_exit(dwc);spin_lock_irqsave(&dwc->lock, flags);dwc3_event_buffers_cleanup(dwc);dwc3_otg_device_exit(dwc);spin_unlock_irqrestore(&dwc->lock, flags);break;default:break;}spin_lock_irqsave(&dwc->lock, flags);dwc->current_otg_role = dwc->desired_otg_role;spin_unlock_irqrestore(&dwc->lock, flags);switch (dwc->desired_otg_role) {case DWC3_OTG_ROLE_HOST:spin_lock_irqsave(&dwc->lock, flags);dwc3_otgregs_init(dwc);dwc3_otg_host_init(dwc);spin_unlock_irqrestore(&dwc->lock, flags);ret = dwc3_host_init(dwc);if (ret) {dev_err(dwc->dev, "failed to initialize host\n");} else {if (dwc->usb2_phy)otg_set_vbus(dwc->usb2_phy->otg, true);if (dwc->usb2_generic_phy)phy_set_mode(dwc->usb2_generic_phy,PHY_MODE_USB_HOST);}break;case DWC3_OTG_ROLE_DEVICE:spin_lock_irqsave(&dwc->lock, flags);dwc3_otgregs_init(dwc);dwc3_otg_device_init(dwc);dwc3_event_buffers_setup(dwc);spin_unlock_irqrestore(&dwc->lock, flags);if (dwc->usb2_phy)otg_set_vbus(dwc->usb2_phy->otg, false);if (dwc->usb2_generic_phy)phy_set_mode(dwc->usb2_generic_phy,PHY_MODE_USB_DEVICE);ret = dwc3_gadget_init(dwc);if (ret)dev_err(dwc->dev, "failed to initialize peripheral\n");break;default:break;}
}

debugfs

drivers/usb/dwc3/debugfs.c通过应用层写模式到属性文件中,也能直接切换模式

static ssize_t dwc3_mode_write(struct file *file,const char __user *ubuf, size_t count, loff_t *ppos)
{struct seq_file         *s = file->private_data;struct dwc3             *dwc = s->private;u32                     mode = 0;char                    buf[32];if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))return -EFAULT;if (!strncmp(buf, "host", 4))mode = DWC3_GCTL_PRTCAP_HOST;if (!strncmp(buf, "device", 6))mode = DWC3_GCTL_PRTCAP_DEVICE;if (!strncmp(buf, "otg", 3))mode = DWC3_GCTL_PRTCAP_OTG;dwc3_set_mode(dwc, mode);return count;
}


http://www.mrgr.cn/p/15751845

相关文章

存储器数据恢复相关知识

讲述硬盘基本结构及其储存理论,介绍如何恢复常用存储器数据。目录目录理论知识 硬盘如何储存数据? 磁道和扇区简介 盘面号 磁道 柱面 扇区 硬盘如何读写数据? 数据删除原理 数据如何丢失的? 人为原因造成的数据丢失: 自然灾害造成的数据丢失: 软件原因造成…

ARM学习(26)链接库的依赖查看

笔者今天来聊一下查看链接库的依赖。 通常情况下&#xff0c;运行一个可执行文件的时候&#xff0c;可能会出现找不到依赖库的情况&#xff0c;比如图下这种情况&#xff0c;可以看到是缺少了license.dll或者libtest.so&#xff0c;所以无法运行。怎么知道它到底缺少什么dll呢&…

构建RAG应用-day05: 如何评估 LLM 应用 评估并优化生成部分 评估并优化检索部分

评估 LLM 应用 1.一般评估思路 首先,你会在一到三个样本的小样本中调整 Prompt ,尝试使其在这些样本上起效。 随后,当你对系统进行进一步测试时,可能会遇到一些棘手的例子,这些例子无法通过 Prompt 或者算法解决。 最终,你会将足够多的这些例子添加到你逐步扩大的开发集中…

android脱壳第二发:grpc-dumpdex加修复

上一篇我写的dex脱壳&#xff0c;写到银行类型的app的dex修复问题&#xff0c;因为dex中被抽取出来的函数的code_item_off 的偏移所在的内存&#xff0c;不在dex文件范围内&#xff0c;所以需要进行一定的修复&#xff0c;然后就停止了。本来不打算接着搞得&#xff0c;但是写了…

ELK 日志分析系统(二)

一、ELK Kibana 部署 1.1 安装Kibana软件包 #上传软件包 kibana-5.5.1-x86_64.rpm 到/opt目录 cd /opt rpm -ivh kibana-5.5.1-x86_64.rpm 1.2 设置 Kibana 的主配置文件 vim /etc/kibana/kibana.yml --2--取消注释&#xff0c;Kiabana 服务的默认监听端口为5601 server.po…

简单的jmeter脚本自动化

1、创建线程组&#xff0c;定义自定义变量&#xff0c;保存请求默认值 2、用csv编写测试用例 备注&#xff1a;如果单元格内本身就有引号&#xff0c;则格式会有点小问题&#xff0c;不能直接修改为csv 用txt打开后 有引号的需要在最外层多包一层引号&#xff0c;每个引号前…

SpringBoot+vue开发记录(二)

说明&#xff1a;本篇文章的主要内容为SpringBoot开发中后端的创建 项目创建: 1. 新建项目&#xff1a; 如下&#xff0c;这样简单创建就行了&#xff0c;JDK什么的就先17&#xff0c;当然1.8也是可以的&#xff0c;后面可以改。 这样就创建好了&#xff1a; 2. pom.xml…

Golang | Leetcode Golang题解之第44题通配符匹配

题目&#xff1a; 题解&#xff1a; func isMatch(s string, p string) bool {for len(s) > 0 && len(p) > 0 && p[len(p)-1] ! * {if charMatch(s[len(s)-1], p[len(p)-1]) {s s[:len(s)-1]p p[:len(p)-1]} else {return false}}if len(p) 0 {retur…

go的编译以及运行时环境

开篇 很多语言都有自己的运行时环境&#xff0c;go自然也不例外&#xff0c;那么今天我们就来讲讲go语言的运行时环境&#xff01; 不同语言的运行时环境对比 我们都知道Java的运行时环境是jvm &#xff0c;javascript的运行时环境是浏览器内核 Java -->jvm javascript…

基于Springboot的网课管理系统

基于SpringbootVue的网课管理系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 课程表 论坛交流 学校公告 后端 学生管理 教师管理 班级管理 课程分类管理…

TODO -蓝桥杯2018年A组-付账问题

0.题目 题目描述 几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。 现在有 \(n\) 个人出去吃饭,他们总共消费了 \(S\) 元。其中第 \(i\) 个人带了 \(a_i\) 元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢? 为了…

【TCP:可靠数据传输,快速重传,流量控制,TCP流量控制】

文章目录 可靠数据传输TCP&#xff1a;可靠数据传输TCP发送方事件快速重传流量控制TCP流量控制 可靠数据传输 TCP&#xff1a;可靠数据传输 TCP在IP不可靠服务的基础上建立了rdt 管道化的报文段 GBN or SR 累计确认&#xff08;像GBN&#xff09;单个重传定时器&#xff08;像…

小伙伴:我是专升本,能不写在简历里吗?

大家好,我是树哥。 最近我推出了简历辅导服务(详见:500 块就能获得 10 年的行业经验,太赚了!),有一位同学找我做了简历辅导。 在阅读他的简历的时候,我发现他的学历没有写入学时间和毕业时间,感觉不是很直观,于是让他补全一下。小伙伴回复说:我是专升本的,本科只有…

JetBrains PhpStorm v2024.1 安装教程 (PHP集成开发IDE)

前言 PhpStorm是由JetBrains推出的一款轻量级集成开发环境&#xff0c;专为PHP开发者而设计。该软件融合了智能的HTML/CSS/JavaScript/PHP编辑器、代码质量分析工具、版本控制系统集成&#xff08;包括SVN和GIT&#xff09;、调试和测试等功能。除此之外&#xff0c;PhpStorm还…

PyQt介绍——动画使用详解之QPropertyAnimation

一、继承关系 PyQt5的动画框架是QAbstractAnimation&#xff0c;它是一个抽象类&#xff0c;不能直接使用&#xff0c;需要使用它的子类。它的类结构如下&#xff1a; QAbstractAnimation&#xff1a;抽象动画&#xff0c;是所有动画的基类&#xff0c;不能直接使用。 QVariant…

Jetpack Compose 中如何实现全面屏

看问题本质,设置全面屏,是系统窗口的行为,与 View 和 Compose 有什么关系呢? 所以,原理和传统 View 视图是一样的,甚至 Api 都是一模一样的,不熟悉的可以看我之前的文章。传送门: Android 全面屏体验 那为什么还要写这篇文章呢?主要是在 Compose 中写法上的一些区别,…

论文解读:Label Hallucination for Few-Shot Classification

文章汇总 动机 本文的一个思想就是&#xff1a;尽管新类的标签并不能“恰如其分”地表示基数据集中的样本&#xff0c;但是很多基数据集的样本会包含与新类中相似的对象&#xff0c;例如&#xff0c;基数据集中的老虎和新类中的猫有相似的特征&#xff0c;那么就有60%的概率将…

【CSS】使用 scroll snap 实现页面的垂直大屏滚动

CSS 属性 scroll-snap-type 设置了在有滚动容器的情形下吸附至吸附点的严格程度。 scroll-snap-type 使用 scroll snap 也可以用于垂直滚动&#xff0c;全屏展示就是一个很好的例子: <main><section class"section section-1"></section><sect…

4.26文件上传学习

文件上传,绕过,验证,检测一、文件上传 概念:(不赘述转web安全文件上传)[[9.6-9.7基础和过滤方式]] 前置知识:(除解析漏洞)后门代码需要以特定格式后缀解析,不能以图片后缀解析; 知识点 1、文件上传-前端验证 直接修改前端js代码,文件上传格式; 2、黑白名单 3、use…

MySQL—MySQL的存储引擎之InnoDB

MySQL—MySQL的存储引擎之InnoDB 存储引擎及种类 存储引擎说明MyISAM高速引擎&#xff0c;拥有较高的插入&#xff0c;查询速度&#xff0c;但不支持事务InnoDB5.5版本后MySQL的默认数据库存储引擎&#xff0c;支持事务和行级锁&#xff0c;比MyISAM处理速度稍慢ISAMMyISAM的…