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

RK3568平台(显示篇)DRM vop驱动程序分析

一.设备树配置

vopb: vop@ff900000 {compatible = "rockchip,rk3399-vop-big";reg = <0x0 0xff900000 0x0 0x2000>, <0x0 0xff902000 0x0 0x1000>;interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>;assigned-clocks = <&cru ACLK_VOP0>, <&cru HCLK_VOP0>;assigned-clock-rates = <400000000>, <100000000>;clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;clock-names = "aclk_vop", "dclk_vop", "hclk_vop";iommus = <&vopb_mmu>;power-domains = <&power RK3399_PD_VOPB>;resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>;reset-names = "axi", "ahb", "dclk";status = "disabled";vopb_out: port {#address-cells = <1>;#size-cells = <0>;vopb_out_edp: endpoint@0 {reg = <0>;remote-endpoint = <&edp_in_vopb>;};vopb_out_mipi: endpoint@1 {reg = <1>;remote-endpoint = <&mipi_in_vopb>;};vopb_out_hdmi: endpoint@2 {reg = <2>;remote-endpoint = <&hdmi_in_vopb>;};vopb_out_mipi1: endpoint@3 {reg = <3>;remote-endpoint = <&mipi1_in_vopb>;};vopb_out_dp: endpoint@4 {reg = <4>;remote-endpoint = <&dp_in_vopb>;};};
};

vop具体实现文件:

drivers/gpu/drm/rockchip/rockchip_drm_vop.c;
drivers/gpu/drm/rockchip/rockchip_vop_reg.c;
drivers/gpu/drm/rockchip/rockchip_drm_vop.h;
drivers/gpu/drm/rockchip/rockchip_vop_reg.h;

二.驱动分析

const struct component_ops vop_component_ops = {.bind = vop_bind,.unbind = vop_unbind,
};

vop的驱动程序主要是从vop_bind开始,其定义在:drivers/gpu/drm/rockchip/rockchip_drm_vop.c

vop_bind函数涉及到对vop设备节点的解析,咱们以vopb设备节点为例进行分析;

static int vop_bind(struct device *dev, struct device *master, void *data)
{// 1. 获取platform_devicestruct platform_device *pdev = to_platform_device(dev);const struct vop_data *vop_data;struct drm_device *drm_dev = data;struct vop *vop;struct resource *res;int ret, irq;// 2. 得到rk3399_vop_bigvop_data = of_device_get_match_data(dev);if (!vop_data)return -ENODEV;/* Allocate vop struct and its vop_win array,初始化vop win */vop = devm_kzalloc(dev, struct_size(vop, win, vop_data->win_size),GFP_KERNEL);if (!vop)return -ENOMEM;vop->dev = dev;vop->data = vop_data;vop->drm_dev = drm_dev;// 设置驱动数据为vopdev_set_drvdata(dev, vop);// 3. 初始化vop winvop_win_init(vop);// 4. 获取第一个内存资源,即<0x0 0xff900000 0x0 0x2000>; VOP_BIG相关寄存器基地址res = platform_get_resource(pdev, IORESOURCE_MEM, 0);// 将VOP_BIG相关寄存器起始物理地址映射到虚拟地址,并返回虚拟地址vop->regs = devm_ioremap_resource(dev, res);if (IS_ERR(vop->regs))return PTR_ERR(vop->regs);vop->len = resource_size(res);// 5. 获取第二个内存资源,即<0x0 0xff902000 0x0 0x1000>; LUT相关寄存器基地址res = platform_get_resource(pdev, IORESOURCE_MEM, 1);if (res) {if (vop_data->lut_size != 1024 && vop_data->lut_size != 256) {DRM_DEV_ERROR(dev, "unsupported gamma LUT size %d\n", vop_data->lut_size);return -EINVAL;}// LUT相关寄存器起始物理地址映射到虚拟地址,并返回虚拟地址vop->lut_regs = devm_ioremap_resource(dev, res);if (IS_ERR(vop->lut_regs))return PTR_ERR(vop->lut_regs);}vop->regsbak = devm_kzalloc(dev, vop->len, GFP_KERNEL);if (!vop->regsbak)return -ENOMEM;// 6. 获取第1个IRQ编号 interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>;irq = platform_get_irq(pdev, 0);if (irq < 0) {DRM_DEV_ERROR(dev, "cannot find irq for vop\n");return irq;}vop->irq = (unsigned int)irq;// 初始化自旋锁和互斥锁spin_lock_init(&vop->reg_lock);spin_lock_init(&vop->irq_lock);mutex_init(&vop->vop_lock);// 7. 创建crtc对象,并和plane关联在一起ret = vop_create_crtc(vop);if (ret)return ret;// 电源管理相关pm_runtime_enable(&pdev->dev);// 8. vop初始化ret = vop_initial(vop);if (ret < 0) {DRM_DEV_ERROR(&pdev->dev,"cannot initial vop dev - err %d\n", ret);goto err_disable_pm_runtime;}// 9. 申请中断,中断处理函数设置为vop_isrret = devm_request_irq(dev, vop->irq, vop_isr,IRQF_SHARED, dev_name(dev), vop);if (ret)goto err_disable_pm_runtime;// 未设置if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) {vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev);if (IS_ERR(vop->rgb)) {ret = PTR_ERR(vop->rgb);goto err_disable_pm_runtime;}}// 10. dma初始化rockchip_drm_dma_init_device(drm_dev, dev);return 0;err_disable_pm_runtime:pm_runtime_disable(&pdev->dev);vop_destroy_crtc(vop);return ret;
}

这里我们以设备节点vopb为例,对这段代码进行分析,主要流程如下:

(1) 调用to_platform_device获取platform device,设备节点为vopb

(2) 调用of_device_get_match_data获取与特定设备匹配的数据,这里获取到的数据为rk3399_vop_big;

(3) 调用vop_win_init初始化vop win

(4) 首先调用platform_get_resource(pdev, IORESOURCE_MEM, 0)获取第一个内存资源,即:

<0x0 0xff900000 0x0 0x2000>

0xff900000VOP_BIG相关寄存器基地址;

接着调用devm_ioremap_resource(dev, res)VOP_BIG相关寄存器起始物理地址映射到虚拟地址,并返回虚拟地址;

(5) 调用platform_get_resource(pdev, IORESOURCE_MEM, 1)获取第二个内存资源,即:

<0x0 0xff902000 0x0 0x1000>

0xff902000LUT相关寄存器基地址;

接着调用devm_ioremap_resource(dev, res)LUT相关寄存器起始物理地址映射到虚拟地址,并返回虚拟地址;

(6) 调用platform_get_irq(pdev, 0) 获取第1个IRQ编号:

 interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>

(7) 调用vop_create_crtc(vop)初始化crtc对象,并和plane关联在一起;

(8) 调用vop_initial(vop)进行vop初始化;

(9) 调用devm_request_irq(dev, vop->irq, vop_isr, IRQF_SHARED, dev_name(dev), vop)申请中断,中断处理函数设置为vop_isr

(10) 调用rockchip_drm_dma_init_device(drm_dev, dev)进行dma相关的初始化工作;

vop_bind函数里面比较重要的几个函数:

vo_win_init用于初始化vop win,那么什么是vop win,指定就是vop图层。

vop_create_crtc用于初始化crtc对象,crtcFramebuffer中读取待显示的图像。

vop_initial用户vop初始化。

vo_win_init:初始化vop win。

/** Initialize the vop->win array elements.*/
static void vop_win_init(struct vop *vop)
{const struct vop_data *vop_data = vop->data;unsigned int i;// 遍历每一个图层for (i = 0; i < vop_data->win_size; i++) {// 获取第i个vop winstruct vop_win *vop_win = &vop->win[i];// 获取第i个vop win配置相关寄存器信息const struct vop_win_data *win_data = &vop_data->win[i];// 初始化成员vop_win->data = win_data;vop_win->vop = vop;// rk3399定义了win_yuv2yuv,因此初始化yuv2yuv_dataif (vop_data->win_yuv2yuv)vop_win->yuv2yuv_data = &vop_data->win_yuv2yuv[i];}
}

vop_create_crtc:用于初始化crtc对象。

static int vop_create_crtc(struct vop *vop)
{// 获取vop dataconst struct vop_data *vop_data = vop->data;// 获取device,对应的设备节点为vopbstruct device *dev = vop->dev;// 获取drm devicestruct drm_device *drm_dev = vop->drm_dev;struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;// 获取drm crtcstruct drm_crtc *crtc = &vop->crtc;struct device_node *port;int ret;int i;/** Create drm_plane for primary and cursor planes first, since we need* to pass them to drm_crtc_init_with_planes, which sets the* "possible_crtcs" to the newly initialized crtc.         * 1. 遍历每一个vop win,每个vop win内部包含一个drm_plane,对类型为primary和cursor plane* 进行初始化*/for (i = 0; i < vop_data->win_size; i++) {// 获取第i个vop winstruct vop_win *vop_win = &vop->win[i];// 获取第i个vop win dataconst struct vop_win_data *win_data = vop_win->data;// 只处理primary和cursor planeif (win_data->type != DRM_PLANE_TYPE_PRIMARY &&win_data->type != DRM_PLANE_TYPE_CURSOR)continue;// 进行plane的初始化,其中funcs被设置为vop_plane_funcsret = drm_universal_plane_init(vop->drm_dev,    // drm设备&vop_win->base,  // 要初始化的plane对象0,  // 可能的CRTCs的位掩码&vop_plane_funcs,  // plane的控制函数集合win_data->phy->data_formats,  // 支持的格式数组(DRM_FORMAT_*)win_data->phy->nformats,   // formats数组的长度win_data->phy->format_modifiers, win_data->type, // plane的类型NULL);if (ret) {DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",ret);goto err_cleanup_planes;}// 获取当前planeplane = &vop_win->base;// 设置plane的辅助函数helper_private为plane_helper_funcsdrm_plane_helper_add(plane, &plane_helper_funcs);// 如果vop win data配置了x_mir_en/y_mir_en,则调用drm_plane_create_rotation_property为plane附加rotation propertyvop_plane_add_properties(plane, win_data);// 保存primary planeif (plane->type == DRM_PLANE_TYPE_PRIMARY)primary = plane;// 保存cursor planeelse if (plane->type == DRM_PLANE_TYPE_CURSOR)cursor = plane;}// 2. 使用指定的primary and cursor planes初始化的crtc对象,其中crtc回调函数funcs设置为vop_crtc_funcsret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,&vop_crtc_funcs, NULL);if (ret)goto err_cleanup_planes;// 3. 设置crtc的辅助函数helper_private为vop_crtc_helper_funcsdrm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);// 进入if (vop->lut_regs) {drm_mode_crtc_set_gamma_size(crtc, vop_data->lut_size);drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size);}/** Create drm_planes for overlay windows with possible_crtcs restricted* to the newly created crtc.* 4. 遍历每一个vop win,每个vop win内部包含一个drm_plane,对类型为overlay plane* 进行初始化*/for (i = 0; i < vop_data->win_size; i++) {// 获取第i个vop winstruct vop_win *vop_win = &vop->win[i];// 获取第i个vop win dataconst struct vop_win_data *win_data = vop_win->data;unsigned long possible_crtcs = drm_crtc_mask(crtc);// 只处理overlay planeif (win_data->type != DRM_PLANE_TYPE_OVERLAY)continue;// 进行plane的初始化,其中funcs被设置为vop_plane_funcsret = drm_universal_plane_init(vop->drm_dev, &vop_win->base,possible_crtcs,&vop_plane_funcs,win_data->phy->data_formats,win_data->phy->nformats,win_data->phy->format_modifiers,win_data->type, NULL);if (ret) {DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",ret);goto err_cleanup_crtc;}// 设置plane的辅助函数helper_private为plane_helper_funcsdrm_plane_helper_add(&vop_win->base, &plane_helper_funcs);// 如果vop win data配置了x_mir_en/y_mir_en,则调用drm_plane_create_rotation_property为plane附加rotation propertyvop_plane_add_properties(&vop_win->base, win_data);}// 5. 从vopb节点的子节点列表中查找名为port的子节点,也就是vopb_out节点port = of_get_child_by_name(dev->of_node, "port");if (!port) {DRM_DEV_ERROR(vop->dev, "no port node found in %pOF\n",dev->of_node);ret = -ENOENT;goto err_cleanup_crtc;}// 6. 初始化工作队列drm_flip_work_init(&vop->fb_unref_work, "fb_unref",vop_fb_unref_worker);// 初始化完成量,init_completion(&vop->dsp_hold_completion);init_completion(&vop->line_flag_completion);// 设置port节点crtc->port = port;// 7. 对crtc进行自刷新相关的辅助函数初始化ret = drm_self_refresh_helper_init(crtc);if (ret)DRM_DEV_DEBUG_KMS(vop->dev,"Failed to init %s with SR helpers %d, ignoring\n",crtc->name, ret);return 0;err_cleanup_crtc:drm_crtc_cleanup(crtc);
err_cleanup_planes:list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,head)drm_plane_cleanup(plane);return ret;err_cleanup_crtc:drm_crtc_cleanup(crtc);
err_cleanup_planes:list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,head)drm_plane_cleanup(plane);return ret;
}

(1) 遍历每一个vop win,每个vop win内部包含一个drm_plane,对类型为primarycursor plane进行初始化;具体是调用drm_universal_plane_init来初始化drm_plane,并且添加plane辅助函数、设置属性等;其中funcs被设置为vop_plane_funcs,定义在drivers/gpu/drm/rockchip/rockchip_drm_vop.c

static const struct drm_plane_funcs vop_plane_funcs = {.update_plane   = drm_atomic_helper_update_plane,.disable_plane  = drm_atomic_helper_disable_plane,.destroy = vop_plane_destroy,.reset = drm_atomic_helper_plane_reset,.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,.format_mod_supported = rockchip_mod_supported,
};

(2) 调用drm_crtc_init_with_planes使用指定的primary and cursor planes初始化的crtc对象,其中crtc回调函数funcs设置为vop_crtc_funcs,定义在drivers/gpu/drm/rockchip/rockchip_drm_vop.c

static const struct drm_crtc_funcs vop_crtc_funcs = {.set_config = drm_atomic_helper_set_config,.page_flip = drm_atomic_helper_page_flip,.destroy = vop_crtc_destroy,.reset = vop_crtc_reset,.atomic_duplicate_state = vop_crtc_duplicate_state,.atomic_destroy_state = vop_crtc_destroy_state,.enable_vblank = vop_crtc_enable_vblank,.disable_vblank = vop_crtc_disable_vblank,.set_crc_source = vop_crtc_set_crc_source,.verify_crc_source = vop_crtc_verify_crc_source,
};

(3) 调用drm_crtc_helper_add设置crtc的辅助函数helper_privatevop_crtc_helper_funcs,定义在drivers/gpu/drm/rockchip/rockchip_drm_vop.c

static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {.mode_fixup = vop_crtc_mode_fixup,.atomic_check = vop_crtc_atomic_check,.atomic_begin = vop_crtc_atomic_begin,.atomic_flush = vop_crtc_atomic_flush,.atomic_enable = vop_crtc_atomic_enable,.atomic_disable = vop_crtc_atomic_disable,
};

(4) 遍历每一个vop win,每个vop win内部包含一个drm_plane,对类型为overlay plane进行初始化;

(5) 调用of_get_child_by_namevopb节点的子节点列表中查找名为port的子节点,也就是vopb_out节点;

(6) 调用drm_flip_work_init(&vop->fb_unref_work, "fb_unref",vop_fb_unref_worker)初始化工作队列;

vop_initial

vop_initial用户vop初始化,定义在drivers/gpu/drm/rockchip/rockchip_drm_vop.c

static int vop_initial(struct vop *vop)
{struct reset_control *ahb_rst;int i, ret;// 根据时钟名称hclk_vop获取时钟,设备节点属性clock-names、clocks,指定了名字为hclk_vop对应的时钟为<&cru HCLK_VOP0>vop->hclk = devm_clk_get(vop->dev, "hclk_vop");if (IS_ERR(vop->hclk)) {DRM_DEV_ERROR(vop->dev, "failed to get hclk source\n");return PTR_ERR(vop->hclk);}// 根据时钟名称aclk_vop获取时钟,设备节点属性clock-names、clocks,指定了名字为aclk_vop对应的时钟为<&cru ACLK_VOP0>vop->aclk = devm_clk_get(vop->dev, "aclk_vop");if (IS_ERR(vop->aclk)) {DRM_DEV_ERROR(vop->dev, "failed to get aclk source\n");return PTR_ERR(vop->aclk);}// 根据时钟名称dclk_vop获取时钟,设备节点属性clock-names、clocks,指定了名字为dclk_vop对应的时钟为<&cru DCLK_VOP0>vop->dclk = devm_clk_get(vop->dev, "dclk_vop");if (IS_ERR(vop->dclk)) {DRM_DEV_ERROR(vop->dev, "failed to get dclk source\n");return PTR_ERR(vop->dclk);}// 电源相关,,使能设备的runtime pm功能 暂且忽略ret = pm_runtime_resume_and_get(vop->dev);if (ret < 0) {DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret);return ret;}// dclk时钟准备,使其处于可用状态,但不启用它ret = clk_prepare(vop->dclk);if (ret < 0) {DRM_DEV_ERROR(vop->dev, "failed to prepare dclk\n");goto err_put_pm_runtime;}/* Enable both the hclk and aclk to setup the vop,hclk时钟准备和使能 */ret = clk_prepare_enable(vop->hclk);if (ret < 0) {DRM_DEV_ERROR(vop->dev, "failed to prepare/enable hclk\n");goto err_unprepare_dclk;}// aclk时钟准备和使能ret = clk_prepare_enable(vop->aclk);if (ret < 0) {DRM_DEV_ERROR(vop->dev, "failed to prepare/enable aclk\n");goto err_disable_hclk;}/** do hclk_reset, reset all vop registers. 获取ahb相应的reset句柄*/ahb_rst = devm_reset_control_get(vop->dev, "ahb");if (IS_ERR(ahb_rst)) {DRM_DEV_ERROR(vop->dev, "failed to get ahb reset\n");ret = PTR_ERR(ahb_rst);goto err_disable_aclk;}// 对传入的reset资源进行复位操作reset_control_assert(ahb_rst);// 睡眠,单位为微妙usleep_range(10, 20);// 对传入的reset资源进行解复位操作reset_control_deassert(ahb_rst);// 设置rk3399_vop_big.intr.clear所描述寄存器相应位的值VOP_INTR_SET_TYPE(vop, clear, INTR_MASK, 1);       // 设置rk3399_vop_big.intr.enable所描述寄存器相应位的值VOP_INTR_SET_TYPE(vop, enable, INTR_MASK, 0);// 备份vop相关寄存器的值for (i = 0; i < vop->len; i += sizeof(u32))vop->regsbak[i / 4] = readl_relaxed(vop->regs + i);// 设置rk3399_vop_big.misc.global_regdone_en所描述寄存器相应位的值VOP_REG_SET(vop, misc, global_regdone_en, 1);// 设置rk3399_vop_big.common.dsp_blank所描述寄存器相应位的值VOP_REG_SET(vop, common, dsp_blank, 0);// 遍历每一个vop winfor (i = 0; i < vop->data->win_size; i++) {// 获取第i个vop winstruct vop_win *vop_win = &vop->win[i];// 获取第i个vop win dataconst struct vop_win_data *win = vop_win->data;int channel = i * 2 + 1;// 设置rk3399_vop_big.win[i].phy.channel所描述寄存器相应位的值VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel);// 禁止当前vop winvop_win_disable(vop, vop_win);// 设置rk3399_vop_big.win[i].phy.gate所描述寄存器相应位的值VOP_WIN_SET(vop, win, gate, 1);}// 设置rk3399_vop_big.common.cfg_done所描述寄存器相应位的值,enable reg configvop_cfg_done(vop);/** do dclk_reset, let all config take affect. 获取dclk相应的reset句柄*/vop->dclk_rst = devm_reset_control_get(vop->dev, "dclk");if (IS_ERR(vop->dclk_rst)) {DRM_DEV_ERROR(vop->dev, "failed to get dclk reset\n");ret = PTR_ERR(vop->dclk_rst);goto err_disable_aclk;}// 对传入的reset资源进行复位操作reset_control_assert(vop->dclk_rst);// 睡眠,单位为微妙usleep_range(10, 20);// 对传入的reset资源进行解复位操作reset_control_deassert(vop->dclk_rst);// 禁止时钟hclkclk_disable(vop->hclk);// 禁止时钟aclkclk_disable(vop->aclk);// 使能标志位vop->is_enabled = false;pm_runtime_put_sync(vop->dev);return 0;err_disable_aclk:clk_disable_unprepare(vop->aclk);
err_disable_hclk:clk_disable_unprepare(vop->hclk);
err_unprepare_dclk:clk_unprepare(vop->dclk);
err_put_pm_runtime:pm_runtime_put_sync(vop->dev);return ret;
}

该函数主要做了两件事件:

  • vop相关时钟初始化:aclk_vopdclk_vophclk_vop
  • vop相关寄存器配置,底层通过vop_reg_set设置配置寄存器值;

相关文章:

RK3568平台(显示篇)DRM vop驱动程序分析

一.设备树配置 vopb: vopff900000 {compatible "rockchip,rk3399-vop-big";reg <0x0 0xff900000 0x0 0x2000>, <0x0 0xff902000 0x0 0x1000>;interrupts <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>;assigned-clocks <&cru ACLK_VOP0>, &…...

vue3 动态加载组件

//模版调用 <component :is"geticon(item.icon)" />//引入 import { ref, onMounted, markRaw, defineAsyncComponent } from vue;//异步添加icon图标组建 function geticon(params) {const modules import.meta.glob(../components/icons/*.vue);const link …...

Latex on overleaf入门语法

Latex on overleaf入门语法 前言基本结构序言 简单的格式化命令添加注释&#xff1a;%加粗、斜体、下划线有序列表、无序列表 添加图片图片的标题、标签和引用 添加表格一个简单的表格为表格添加边框标题、标签、引用 数学表达式基本的数学命令 基本格式摘要段落、新行章节、分…...

使用Echarts来实现数据可视化

目录 一.什么是ECharts? 二.如何使用Springboot来从后端给Echarts返回响应的数据&#xff1f; eg:折线图&#xff1a; ①Controller层&#xff1a; ②service层&#xff1a; 一.什么是ECharts? ECharts是一款基于JavaScript的数据可视化图标库&#xff0c;提供直观&…...

一文搞懂GIT

文章目录 1. GiT概述1.1 GIT概述1.2 GIT安装 2. GIT组成3. GIT基本命令3.1 基本命令3.2 分支操作3.3 远程操作3.4 标签操作3.5 其他命令 1. GiT概述 1.1 GIT概述 Git 是一个分布式版本控制系统&#xff0c;被广泛应用于软件开发中。 Git 具有众多优点&#xff0c;比如&#…...

jQuery入门(四)案例

jQuery 操作入门案例 一、复选框案例 功能: 列表的全选&#xff0c;反选&#xff0c;全不选功能实现。 实现步骤和分析&#xff1a; - 全选 1. 为全选按钮绑定单击事件。 2. 获取所有的商品项复选框元素&#xff0c;为其添加 checked 属性&#xff0c;属性值为 true。 -…...

揭秘MITM攻击:原理、手法与防范措施

中间人攻击发生时&#xff0c;攻击者会在通讯两端之间插入自己&#xff0c;成为通信链路的一部分。攻击者可以拦截、查看、修改甚至重新定向受害者之间的通信数据&#xff0c;而不被双方察觉。这种攻击常见于未加密的Wi-Fi网络、不安全的HTTP连接或者通过社会工程学手段诱导受害…...

【YOLOv8】一文全解+亮点介绍+训练教程+独家魔改优化技巧

前言 Hello&#xff0c;大家好&#xff0c;我是cv君&#xff0c;最近开始在空闲之余&#xff0c;经常更新文章啦&#xff01;除目标检测、分类、分隔、姿态估计等任务外&#xff0c;还会涵盖图像增强领域&#xff0c;如超分辨率、画质增强、降噪、夜视增强、去雾去雨、ISP、海…...

创建mvp ubo(uniform buffer object)

创建过程&#xff1a; 创建一个uniform buffer查找buffer memory requirements分配、绑定buffer memorymap buffer memory拷贝mvp data to buffer memoryunmap buffer memory 示例代码&#xff1a; glm::mat4 projection glm::perspective(glm::radians(45.0f), 1.0f, 0.1f…...

1.GPIO

理论说明 输入 上拉输入&#xff1a;拉高电平 下拉输入&#xff1a;拉低电平 浮空输入&#xff1a;不拉高也不拉低电平 输出 开漏输出&#xff1a;不能输出高电平&#xff08;P-MOS不可用&#xff0c;则只能低电平&#xff09; 推挽输出&#xff1a;可输出高低电平 输出速率…...

C++必修:STL之vector的了解与使用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. C/C中的数组 1.1. C语言中的数组 在 C 语言中&#xff0c;数组是一组相同类型…...

【MySQL】索引 【上】 {没有索引的查询/磁盘/mysql与磁盘IO/初识索引}

文章目录 1.没有索引存在的问题2. 认识磁盘MySQL与存储MySQL与磁盘交互基本单位建立共识图解IO认识索引 在关系数据库中&#xff0c;索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构&#xff0c;它是某个表中一列或若干列值的集合和相应的指向表中物…...

GO goroutine状态流转

Gidle -> Grunnable newproc获取新的goroutine&#xff0c;并放置到P运行队列中 这也是go关键字之后实际编译调用的方法 func newproc(fn *funcval) {// 获取当前正在运行中的goroutinegp : getg()// 获取调用者的程序计数器地址&#xff0c;用于调试和跟踪pc : getcallerp…...

DLMS/COSEM中的信息安全:DLMS/COSEM安全概念(上)

DLMS/COSEM中的信息安全描述并规定: ——DLMS/COSEM安全概念; ——选择加密算法; ——安全密钥; ——使用加密算法进行实体认证、xDLMS APDU保护和COSEM数据保护。 1.综述 DLMS/COSEM服务器的资源(COSEM对象属性和方法)可以由在应用连接内的DLMS/COSEM客户机访问。 在AA…...

C语言第九天笔记

数组的概念 什 么是数组 数组是 相同类型&#xff0c; 有序数据的集合。 数 组的特征 数组中的数据被称为数组的 元素&#xff0c;是同构的 数组中的元素存放在内存空间里 (char player_name[6]&#xff1a;申请在内存中开辟6块连续的基于char类 型的变量空间) 衍生概念&…...

智慧环卫可视化:科技赋能城市清洁管理

图扑智慧环卫可视化通过实时监控、数据分析和智能调度&#xff0c;提高环卫作业效率&#xff0c;优化资源配置&#xff0c;提升城市清洁水平&#xff0c;实现城市管理的精细化和现代化。...

【力扣】SQL题库练习5

高级查询和连接 1341.电影评分 表&#xff1a;Movies ------------------------ | Column Name | Type | ------------------------ | movie_id | int | | title | varchar | ------------------------ movie_id 是这个表的主键(具有唯一值的列)。 ti…...

永结无间Ⅸ--你不需要LLM Agent

人们将目光锁定在下一个闪亮的事物上。FOMO 是人性的一部分。这也适用于企业。就像数据科学成为每个企业分析功能的热潮一样&#xff0c;Agentic Architecture 是大多数 AI 雷达上的热门目标。 但您是否考虑过您是否真的需要它&#xff1f; 实际情况是&#xff0c;您不需要 A…...

Simulink|基于粒子群算法的永磁同步电机多参数辨识

目录 主要内容 模型研究 结果一览 下载链接 主要内容 仿真程序参考文献《改进粒子群算法的永磁同步电机多参数辨识》&#xff0c;采用粒子群算法与simulink模型结合的方式&#xff0c;对永磁同步电机进行多参数辨识。程序以定子绕组电阻、d轴电感、q轴电感和永磁…...

程序如何自动点击亚马逊商户后台的“邀请评论”按钮

要在亚马逊上自动点击“邀请评论”按钮&#xff0c;可以使用自动化脚本来实现。由于你希望自动化操作&#xff0c;我提供一个示例代码&#xff0c;使用 Selenium WebDriver 来执行这个任务。Selenium 是一个流行的浏览器自动化工具&#xff0c;能够模拟用户操作&#xff0c;例如…...

大模型算法面试题(十八)

本系列收纳各种大模型面试题及答案。 1、P-tuning v2 思路、优缺点是什么 P-tuning v2是清华大学自然语言处理实验室&#xff08;THUDM&#xff09;等研究机构提出的一种新的预训练模型优化方法&#xff0c;主要关注如何通过动态构建任务相关的提示序列来引导预训练模型进行更…...

手机在网状态接口如何对接?(二)

一、什么是手机在网状态&#xff1f; 传入手机号码&#xff0c;查询该手机号的在网状态&#xff0c;返回内容有正常使用、停机、在网但不可用、不在网&#xff08;销号/未启用/异常&#xff09;、预销户等多种状态。 二、手机在网状态使用场景&#xff1f; 1.用户验证与联系…...

力扣-3232. 判断是否可以赢得数字游戏

给你一个 正整数 数组 nums。 Alice 和 Bob 正在玩游戏。在游戏中&#xff0c;Alice 可以从 nums 中选择所有个位数 或 所有两位数&#xff0c;剩余的数字归 Bob 所有。如果 Alice 所选数字之和 严格大于 Bob 的数字之和&#xff0c;则 Alice 获胜。 如果 Alice 能赢得这场游…...

Table SQL connectors以及FileSystem、JDBC connector

目录 Flink支持的连接器 如何使用连接器 FileSystem SQL Connector 文件格式 分区文件 Source 目录监控 元数据 Streaming Sink 滚动策略 文件合并 JDBC SQL Connector 依赖 如何创建JDBC表 连接器配置 案例 pom依赖 代码 测试 Flink的Table API和SQL…...

Animate软件基础:“分散到图层”创建的新图层

FlashASer&#xff1a;AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084 FlashASer&#xff1a;实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer&#xff1a;Animate教程及作品源文件https://zhuanlan.zhihu.co…...

ffmpeg命令-Windows下常用最全

查询命令 参数 说明 -version 显示版本。 -formats 显示可用的格式&#xff08;包括设备&#xff09;。 -demuxers 显示可用的demuxers。 -muxers 显示可用的muxers。 -devices 显示可用的设备。 -codecs 显示libavcodec已知的所有编解码器。 -decoders 显示可用…...

反序列化漏洞靶机实战-serial

一.安装靶机 下载地址为https://download.vulnhub.com/serial/serial.zip&#xff0c;安装好后开启靶机&#xff0c;这里并不需要我们去登录&#xff0c;直接扫描虚拟机nat模式下c网段的ip&#xff0c;看看哪个的80端口开放&#xff0c;然后直接去访问 二.查找cookie 访问靶…...

医疗器械产品没有互联网连接,就不适用于网络安全要求吗?

医疗器械产品是否不适用于网络安全要求&#xff0c;需要考虑产品是否具有网络连接功能以进行电子数据交换或远程控制&#xff0c;以及是否采用储存媒介进行电子数据交换。详细解析如下&#xff1a; 一、医疗器械的网络安全要求不仅限于互联网连接 数据交换接口&#xff1a;医疗…...

可视掏耳勺安全吗?独家揭示六大风险弊病!

很多人习惯在洗漱完顺手拿一根棉签掏耳朵&#xff0c;但是棉签的表面直径大且粗糙&#xff0c;不易将耳朵深处的耳垢挖出&#xff0c;耳垢堆积在耳道深处长时间不清理会导致堵塞耳道&#xff0c;引起耳鸣甚至感染。而可视掏耳勺作为一种新型的挖耳工具&#xff0c;它的安全性也…...

JavaScript 变量声明var、let、const

在 JavaScript 中&#xff0c;var、let和const是用于声明变量的关键字。 let和const是JavaScript里相对较新的变量声明方式。 let用法类似于var&#xff0c;但是所声明的变量&#xff0c;只在let命令所在的代码块内有效。 const声明一个只读的常量。一旦声明&#xff0c;常量的…...

除了wordpress还有什么非php/市场调研数据网站

java 实现网易云音乐下载和播放发布时间&#xff1a;2018-08-27 16:49,浏览次数&#xff1a;872, 标签&#xff1a;java不废话 直接上代码首先 是下载工具类 根据url 下载文件import java.io.BufferedInputStream; import java.io.BufferedReader; importjava.io.DataOutputSt…...

免费手机网站平台注册/怎么做网络宣传推广

第11章 Hive&#xff1a;SQL on Hadoop 11.5 HQL&#xff1a;DDL数据定义 HQL中数据定义部分&#xff0c;也就是DDL&#xff0c;主要包括数据库定义和数据表的定义。 前面创建的Hive数据表都是普通的数据表&#xff0c;下来演示分区表等特殊表的定义与使用。 11.5.1 删除表 …...

用aspx做的网站/关键词林俊杰歌词

成绩提前公布!2021省考成绩查询时间出了!最早4月15日!成绩提前公布!2021省考成绩查询时间出了!最早4月15日!《教育部关于做好2021届全国普通高校毕业生就业创业工作的通知》中明确说明&#xff1a;力争在2021年6月底以前完成全部政策性岗位招录工作。也就是说从笔试结束到6月底…...

书店商城网站建设方案/百度怎么提交收录

假设consul软件安装在电脑ComputerA上&#xff0c;那么需要注册的服务ServiceA1也需要安装在电脑ComputerA上&#xff0c; 一个服务就是一个提供了ipport&#xff08;或者域名&#xff09;的应用程序。 服务&#xff1a; 服务&#xff1a; 1、服务名称&#xff1a;XXX。则生成的…...

wordpress安装不了主题/搭建网站基本步骤

PhotoShop修复工具组 污点修复画笔工具属性调节画笔和污点差不多大小一般在图层上面新建一个图层&#xff0c;在新建图层上使用污点修复工具&#xff08;勾选对所有图层取样&#xff09;修复画笔工具属性使用方式&#xff1a;先按住ALT取样&#xff0c;再使用。&#xff08;ATL…...

应用下载安装/seo数据优化

一、什么是wifi 模块百度百科上这样定义&#xff1a;Wi-Fi模块又名串口Wi-Fi模块&#xff0c;属于物联网传输层&#xff0c;功能是将串口或TTL电平转为符合Wi-Fi无线网络通信标准的嵌入式模块&#xff0c;内置无线网络协议IEEE802.11b.g.n协议栈以及TCP/IP协议栈。传统的硬件设…...