ATF UFS初始化笔记

news2024/9/20 19:04:31

1. JESD220 中关于UFS初始化的描述

原文

13.1.3 Initialization and boot code download process
The initialization and boot code download process is made up of the following phases: partial initialization, boot transfer and initialization completion.

13.1.3.1 Partial initialization
The partial initialization phase starts after power on, or hardware reset, or EndPointReset and involves the entire UFS stack. At the end of this phase, the UniPro boot sequence shall be completed, and the UTP layer shall be capable of accessing Device Descriptor (if the bDescrAccessEn field of the Device Descriptor is ‘01h’) and exchanging UPIU for READ command and TEST UNIT READY command. If the bDescrAccessEn field is ‘00h‘ descriptors will be accessible only after the initialization completion phase. Each single layer in the UFS protocol stack executes the initialization process on both UFS host and UFS device sides.

a) Physical Layer (M-PHY) --> No SW action.
After reset events, the physical layer will move from DISABLED state to HIBERN8 state.

b) Link Layer (UniPro)
On host and device side UniPro boot sequence takes place:

c) UFS Transport Layer (UTP)
At the end of the UFS Interconnect Layer initialization on both host and device side, the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready. For some implementations, the device UTP layer may not be initialized yet, therefore the device may not respond promptly to NOP OUT UPIU sending NOP IN UPIU. The host waits until it receives the NOP IN UPIU from the device. When the NOP IN UPIU is received, the host is acknowledged that the UTP layer on the device is ready to execute UTP transactions.
ufs_check_resp(&utrd, NOP_IN_UPIU, NOP_OUT_TIMEOUT_MS);

d) Link Configuration
The host may configure the Link Attributes (i.e., Gear, HS Series, PWM Mode in Rx and Tx) by using DME primitives at UniPro level.

e) Device Descriptor Reading
The UFS host may optionally discover relevant device info for the boot process by accessing the Device Descriptor (i.e., Device Class/Subclass, Boot Enable, Boot LUs size, etc.). The UFS host is allowed to access the Device Descriptor only if the bDescrAccessEn is ‘01h’, otherwise this descriptor can be accessed only after the device has fully completed its initialization.

13.1.3.2 Boot transfer
The following steps can be executed only if bBootEnable field is set.

13.1.3.3 Initialization completion
After the host has completed the boot code download from the Boot well known logical unit, the initialization process proceeds as described in the following. The host sets the fDeviceInit flag to “01h” to communicate to the UFS device that it can complete its initialization. The device shall reset the fDeviceInit flag when the initialization is complete. The host polls the fDeviceInit flag to check the completion of the process. When the fDeviceInit is reset, the device is ready to accept any command.

翻译

UFS 学习笔记(功能认识篇) 有中文版。以下内容摘自UFS 学习笔记(功能认识篇)
3.1 部分初始化
部分初始化阶段在上电、硬件复位或端点复位之后开始,并涉及整个 UFS 堆栈。在此阶段结束时,应完成 UniPro 引导序列,并且UTP层应能够访问设备描述符(如果设备描述符的 bDescrAccessEn(描述符访问使能)字段为 01h)并交换读取命令和测试单元就绪命令的 UPIU。如果 bDescrAccessEn 字段为 00h,则只有在初始化完成阶段之后才能访问描述符。UFS 协议堆栈中的每个单独层在 UFS 主机和 UFS 设备两侧执行初始化过程。

a) 物理层(M-PHY)

复位事件后,物理层将从 DISABLED 状态转移到 HIBERN8 状态。

b) 链路层(UniPro)

在主机和设备端进行 UniPro 引导序列:

使用 DME_RESET.req 原语重置 UniPro 堆栈;
等待通过 DME_RESET.cnf_L 原语指示的复位完成;
使用 DME_ENABLE.req 原语启用 UniPro 堆栈;
等待通过 DME_ENABLE.cnf_L 原语指示的启用完成;
使用 DME_LINKSTARTUP.req 原语启动 UniPro 链路启动序列。UniPro 链路启动由一系列多相握手组成,以在 UFS 主机和设备之间建立初始双向链路通信;
等待通过 DME_LINKSTARTUP.cnf_L 原语指示的链路启动完成。

c) UFS传输层(UTP)

在主机和设备两侧的 UFS 互连层初始化结束后,主机应发送 NOP OUT UPIU 以验证设备的 UTP 层是否就绪。对于某些实现,设备的 UTP 层可能尚未初始化,因此设备可能无法及时响应 NOP OUT UPIU,并发送 NOP IN UPIU。主机等待接收到设备的 NOP IN UPIU。当接收到 NOP IN UPIU 时,主机确认设备的 UTP 层已准备好执行 UTP 事务。

d) 链路配置

主机可以使用 UniPro 级别的 DME 原语配置链路属性(如 Gear、HS Series、PWM Mode 在 Rx 和 Tx 中)。

e) 设备描述符读取

UFS 主机可以通过访问设备描述符(如设备类/子类、引导使能、引导 LU 大小等)来可选地发现引导过程的相关设备信息。只有在 bDescrAccessEn 为‘01h’时,UFS 主机才允许访问设备描述符,否则此描述符只能在设备完全完成初始化后才能访问。

3.2 引导传输(可选)
仅当 bBootEnable 字段设置时,才执行引导代码下载:

首先,UFS 主机向 Boot 固定逻辑单元发出 TEST UNIT READY 命令,以验证是否可以访问后者。如果命令成功,UFS 主机通过发出 SCSI READ 命令读取 Boot 固定逻辑单元,而 UFS 设备将开始在上行链路上发送引导代码。在此阶段,仅 Boot 固定逻辑单元可访问:该逻辑单元应接受读取命令,而其他逻辑单元可能尚未准备好。

3.3 初始化完成
在主机从 Boot 固定逻辑单元完成引导代码下载后,初始化过程按照以下描述继续进行。主机将 fDeviceInit 标志设置为“01h”,以向 UFS 设备通信,表示它可以完成其初始化。当初始化完成时,设备应将 fDeviceInit 标志复位。主机轮询 fDeviceInit 标志以检查进程的完成情况。当 fDeviceInit 被复位时,设备准备好接受任何。

在这里插入图片描述

2.ATF中代码与协议中的实现

田园诗人之园的ATF BL1 UFS初始化简单分析 中分析了ATF中UFS驱动初始化的流程。
田园诗人之园的ATF bl1 ufshc_dme_get/set处理流程分析分析了ATF DME操作是如何完成的。
这里就不做流程分析了,而是看一看ATF UFS驱动中是如何和JESD 220协议中的内容一一对应实现的。

a) 物理层(M-PHY)

物理层的初始化没有代码来控制,这部分是硬件实现的。

b) 链路层(UniPro)

在主机和设备端进行 UniPro 引导序列:

  • 使用 DME_RESET.req 原语重置 UniPro 堆栈;
  • 等待通过 DME_RESET.cnf_L 原语指示的复位完成;
  • 使用 DME_ENABLE.req 原语启用 UniPro 堆栈;
  • 等待通过 DME_ENABLE.cnf_L 原语指示的启用完成;
    在ATF中ufs_init–>ufshc_reset实现了这个操作。软件这边主要通过操作HCE寄存器的HCE_ENABLE位来实现UNIPRO的reset, 代码片段如下。
static int ufshc_reset(uintptr_t base)
{
	....
	/* disable controller if enabled */
	if (mmio_read_32(base + HCE) & HCE_ENABLE) {
		result = ufshc_hce_disable(base);
		...
	}
	for (retries = 0; retries < HCE_ENABLE_OUTER_RETRIES; ++retries) {
		result = ufshc_hce_enable(base);
	}
	...
}

下图是HCE寄存器的定义。
HCE寄存器定义

  • 使用 DME_LINKSTARTUP.req 原语启动 UniPro 链路启动序列。UniPro 链路启动由一系列多相握手组成,以在 UFS 主机和设备之间建立初始双向链路通信;
  • 等待通过 DME_LINKSTARTUP.cnf_L 原语指示的链路启动完成。
    ATF UFS驱动在ufs_init–>ufshc_link_startup中实现了这个逻辑
static int ufshc_link_startup(uintptr_t base)
{
	int data, result;
	int retries;

	for (retries = DME_LINKSTARTUP_RETRIES; retries > 0; retries--) {
		result = ufshc_dme_link_startup(base);
		if (result != 0) {
			/* Reset controller before trying again */
			result = ufshc_reset(base);
			...
		}
		assert(mmio_read_32(base + HCS) & HCS_DP);
		data = mmio_read_32(base + IS);
		if (data & UFS_INT_ULSS)
			mmio_write_32(base + IS, UFS_INT_ULSS);

		/* clear UE set due to line-reset */
		if (data & UFS_INT_UE) {
			mmio_write_32(base + IS, UFS_INT_UE);
		}
		/* clearing line-reset, UECPA is cleared on read */
		mmio_read_32(base + UECPA);
		return 0;
	}
	return -EIO;
}

ufshc_dme_link_startup实现非常简单,就是调用了UFSHC DME的寄存器发送了DME_LINKSTARTUP的UIC opcode给UNIPRO,使能链路层。

static int ufshc_dme_link_startup(uintptr_t base)
{
	uic_cmd_t cmd;

	memset(&cmd, 0, sizeof(cmd));
	cmd.op = DME_LINKSTARTUP;
	return ufshc_send_uic_cmd(base, &cmd);
}

c) UFS传输层(UTP)

UTP初始化需要主机发送NOP OUT UPIU给设备,然后设备返回正确的NOP IN UPIU给主机。在ATF中实现的代码在ufs_init–>ufs_enum–>ufs_verify_init中。

static void ufs_verify_init(void)
{
    utp_utrd_t utrd;
    int result;
	//初始化一个NOP OUT UPIU并发送给设备
    get_utrd(&utrd);
    ufs_prepare_nop_out(&utrd);
    ufs_send_request(utrd.task_tag);
    //接收NOP IN UPIUAQ	
    result = ufs_check_resp(&utrd, NOP_IN_UPIU, NOP_OUT_TIMEOUT_MS);
    assert(result == 0);
    (void)result;
}

d) 链路配置

主机可以使用 UniPro 级别的 DME 原语配置链路属性(如 Gear、HS Series、PWM Mode 在 Rx 和 Tx 中)
链路配置主要在dwufs_phy_initdwufs_phy_set_pwr_mode中实现。

static int dwufs_phy_init(ufs_params_t *params)
{
    ...
	/* Unipro VS_MPHY disable */
	ufshc_dme_set(VS_MPHY_DISABLE_OFFSET, 0, VS_MPHY_DISABLE_MPHYDIS); //Disable MPHY
	//选择HS-Gear的模式,HS-Gear有Series A和B选,可以看下面的图。
	//以下是UNIPRO中的Attribute模式原文:Phy Adapter 5.8 TX and RX Frequency Series in High Speed Mode A=1 B=2
	ufshc_dme_set(PA_HS_SERIES_OFFSET, 0, 2);

HS Gear模式

	//下面这些hardcode的0x81**的Attribute可能是kirin960芯片里UFS PHY特有的Attribute,在UNIPRO和MPHY中协议中没找到,我也不知道具体的bit是指代什么
	/* MPHY CBRATESEL */
	ufshc_dme_set(0x8114, 0, 1);				
	/* MPHY CBOVRCTRL2 */
	ufshc_dme_set(0x8121, 0, 0x2d);
	/* MPHY CBOVRCTRL3 */
	ufshc_dme_set(0x8122, 0, 0x1);
	ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1);

	/* MPHY RXOVRCTRL4 rx0 */
	ufshc_dme_set(0x800d, 4, 0x58);
	/* MPHY RXOVRCTRL4 rx1 */
	ufshc_dme_set(0x800d, 5, 0x58);
	/* MPHY RXOVRCTRL5 rx0 */
	ufshc_dme_set(0x800e, 4, 0xb);
	/* MPHY RXOVRCTRL5 rx1 */
	ufshc_dme_set(0x800e, 5, 0xb);
	/* MPHY RXSQCONTROL rx0 */
	ufshc_dme_set(0x8009, 4, 0x1);
	/* MPHY RXSQCONTROL rx1 */
	ufshc_dme_set(0x8009, 5, 0x1);
	ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1);

	ufshc_dme_set(0x8113, 0, 0x1);
	ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1);
	//配置RX_HS_G3_SYNC_LENGTH_Capability, RX_HS_G2_SYNC_LENGTH_Capability, 
	//RX_Min_ActivateTime_Capability和TX_Hibern8Time_Capability Attribute
	ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET, 4, 0x4a);
	ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET, 5, 0x4a);
	ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET, 4, 0x4a);
	ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET, 5, 0x4a);
	ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET, 4, 0x7);
	ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET, 5, 0x7);
	ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET, 0, 0x5);
	ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET, 1, 0x5);
	ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	ufshc_dme_set(PA_LOCAL_TX_LCC_ENABLE_OFFSET, 0, 0);

在这里插入图片描述
这个在UNIPRO和MPHY协议中没找到。VS_MK2_EXTN_SUPPORT_OFFSET 0xD0AB。感觉是使能某个硬件。

	ufshc_dme_set(VS_MK2_EXTN_SUPPORT_OFFSET, 0, 0);

	result = ufshc_dme_get(VS_MK2_EXTN_SUPPORT_OFFSET, 0, &data);
	assert((result == 0) && (data == 0));
	ufshc_dme_set(DL_AFC0_CREDIT_THRESHOLD_OFFSET, 0, 0);
	ufshc_dme_set(DL_TC0_OUT_ACK_THRESHOLD_OFFSET, 0, 0);
	ufshc_dme_set(DL_TC0_TX_FC_THRESHOLD_OFFSET, 0, 9);
	(void)result;
	return 0;
}

在这里插入图片描述

在这里插入图片描述
0xd0a0和0x1556这两个Attribute在UNIPRO和MPHY协议中没找到

static int dwufs_phy_set_pwr_mode(ufs_params_t *params)
{
    ....
	if ((flags & UFS_FLAGS_VENDOR_SKHYNIX) != 0U) {
		NOTICE("ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n");
		/* VS_DebugSaveConfigTime */
		result = ufshc_dme_set(0xd0a0, 0x0, 0x10);
		/* sync length */
		result = ufshc_dme_set(0x1556, 0x0, 0x48);
	}
	result = ufshc_dme_get(PA_TACTIVATE_OFFSET, 0, &data);
	if (data < 7) {
		result = ufshc_dme_set(PA_TACTIVATE_OFFSET, 0, 7);
	}

在这里插入图片描述
获取支持的tx和rx的lane并设置

	result = ufshc_dme_get(PA_CONNECTED_TX_DATA_LANES_OFFSET, 0, &tx_lanes);
	result = ufshc_dme_get(PA_CONNECTED_RX_DATA_LANES_OFFSET, 0, &rx_lanes);
	result = ufshc_dme_set(PA_ACTIVE_TX_DATA_LANES_OFFSET, 0, tx_lanes);
	result = ufshc_dme_set(PA_ACTIVE_RX_DATA_LANES_OFFSET, 0, rx_lanes);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	result = ufshc_dme_set(PA_TX_SKIP_OFFSET, 0, 0);

在这里插入图片描述
配置UFS为HS-GEAR3 Series B

	result = ufshc_dme_set(PA_TX_GEAR_OFFSET, 0, 3);
	result = ufshc_dme_set(PA_RX_GEAR_OFFSET, 0, 3);
	result = ufshc_dme_set(PA_HS_SERIES_OFFSET, 0, 2);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	result = ufshc_dme_set(PA_TX_TERMINATION_OFFSET, 0, 1);
	result = ufshc_dme_set(PA_RX_TERMINATION_OFFSET, 0, 1);
	result = ufshc_dme_set(PA_SCRAMBLING_OFFSET, 0, 0);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述



	result = ufshc_dme_set(PA_PWR_MODE_USER_DATA0_OFFSET, 0, 8191);
	result = ufshc_dme_set(PA_PWR_MODE_USER_DATA1_OFFSET, 0, 65535);
	result = ufshc_dme_set(PA_PWR_MODE_USER_DATA2_OFFSET, 0, 32767);
	result = ufshc_dme_set(DME_FC0_PROTECTION_TIMEOUT_OFFSET, 0, 8191);
	result = ufshc_dme_set(DME_TC0_REPLAY_TIMEOUT_OFFSET, 0, 65535);
	result = ufshc_dme_set(DME_AFC0_REQ_TIMEOUT_OFFSET, 0, 32767);
	result = ufshc_dme_set(PA_PWR_MODE_USER_DATA3_OFFSET, 0, 8191);
	result = ufshc_dme_set(PA_PWR_MODE_USER_DATA4_OFFSET, 0, 65535);
	result = ufshc_dme_set(PA_PWR_MODE_USER_DATA5_OFFSET, 0, 32767);
	result = ufshc_dme_set(DME_FC1_PROTECTION_TIMEOUT_OFFSET, 0, 8191);
	result = ufshc_dme_set(DME_TC1_REPLAY_TIMEOUT_OFFSET, 0, 65535);
	result = ufshc_dme_set(DME_AFC1_REQ_TIMEOUT_OFFSET, 0, 32767);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置power mode为fast mode

	result = ufshc_dme_set(PA_PWR_MODE_OFFSET, 0, 0x11);
	do {
		data = mmio_read_32(base + IS);
	} while ((data & UFS_INT_UPMS) == 0);
	mmio_write_32(base + IS, UFS_INT_UPMS);
	data = mmio_read_32(base + HCS);
	if ((data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL)
		INFO("ufs: change power mode success\n");
	else
		WARN("ufs: HCS.UPMCRS error, HCS:0x%x\n", data);
	(void)result;
	return 0;

在这里插入图片描述

e) 设备描述符读取

static void ufs_get_device_info(struct ufs_dev_desc *card_data)
{
	uint8_t desc_buf[DESC_DEVICE_MAX_SIZE];

	ufs_read_desc(DESC_TYPE_DEVICE, 0, (uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE);

	/*
	 * getting vendor (manufacturerID) and Bank Index in big endian
	 * format
	 */
	card_data->wmanufacturerid = (uint16_t)((desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8) |
				     (desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]));
}

初始化完成

ufs_init->ufs_enum->ufs_set_fdevice_init。通过QUERY UPIU 给UFS设备之上FDEVICE_INIT flag。

static int ufs_set_fdevice_init(void)
{
	unsigned int result;
	int timeout;

	ufs_set_flag(FLAG_DEVICE_INIT);

	timeout = FDEVICEINIT_TIMEOUT_MS;
	do {
		result = ufs_read_flag(FLAG_DEVICE_INIT);
		if (!result) {
			break;
		}
		mdelay(5);
		timeout -= 5;
	} while (timeout > 0);

	if (result != 0U) {
		return -ETIMEDOUT;
	}

	return 0;
}

3. Dump出代码中的初始化过程中的UPIU

UTRD header
在这里插入图片描述

NOP UPIU

NOP OUT UPIU

NOP OUT UPIU

UTRD header: 	0x11000000 0x0 0xf 0x0 0x1ffc0080 0x0 0x8000e 0x0 
CMD UPIU: 		0x1000000 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
RESP UPIU: 		0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
PRDT: 			0x0 0x0 0x0 0x0 
UTRD Header
CCI0
CE0
I1
DD0 - no data transfer
Command Type1
Overall Command Status0xF INVALID_OSC_VALUE
DUNU0
UTP Command Descriptor Base Address0x1ffc0080
UTP Command Descriptor Base Address Upper 32-bits0
Response UPIU Offset0x8
Response UPIU Length0xE
PRDT Length0
PRDT Offset0

在这里插入图片描述

[31:24][23:16][15:8][7:0]
Command Type=00(NOP OUT)Flags=00Reserved=00Task Tag=01
Reserved=00Reserved=00Reserved=00Reserved=00
Total EHS Length=00hReserved=00Data Length MSB=00Data Length LSB=00
Reserved=00Reserved=00Reserved=00Reserved=00
Reserved=00Reserved=00Reserved=00Reserved=00
Reserved=00Reserved=00Reserved=00Reserved=00
Header E2ECRC[31:24]=00Header E2ECRC[23:16]=00Header E2ECRC[15:8]=00Header E2ECRC[7:0]=00

NOP IN UPIU

UTRD header: 	0x11000000 0x0 0x0 0x0 0x1ffc0080 0x0 0x8000e 0x0 
CMD UPIU: 		0x1000000 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
RESP UPIU: 		0x1000020 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
PRDT: 			0x0 0x0 0x0 0x0
UTRD Header
CCI0
CE0
I1
DD0 - no data transfer
Command Type1
Overall Command Status0x0 SUCCESS
DUNU0
UTP Command Descriptor Base Address0x1ffc0080
UTP Command Descriptor Base Address Upper 32-bits0
Response UPIU Offset0x8
Response UPIU Length0xE
PRDT Length0
PRDT Offset0

在这里插入图片描述

[31:24][23:16][15:8][7:0]
Command Type=20(NOP IN)Flags=00Reserved=00Task Tag=01
Reserved=00Reserved=00Reserved=00Reserved=00
Total EHS Length=00hReserved=00Data Length MSB=00Data Length LSB=00
Reserved=00Reserved=00Reserved=00Reserved=00
Reserved=00Reserved=00Reserved=00Reserved=00
Reserved=00Reserved=00Reserved=00Reserved=00
Header E2ECRC[31:24]=00Header E2ECRC[23:16]=00Header E2ECRC[15:8]=00Header E2ECRC[7:0]=00

TEST UNIT UPIU

SET FDEVICE_INIT UPIU

READ CAPACITY UPIU

READ DEVICE DESCRIPTOR UPIU

READ BLOCK UPIU

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

果蔬识别系统性能优化之路(四)

目录 前情提要剩下问题 问题排查解决方案下一步 前情提要 果蔬识别系统性能优化之路&#xff08;三&#xff09; 剩下问题 同步数据库数据并初始化ivf依然要8,9秒 问题排查 通过断点加时间打印&#xff0c;发生其实初始化ivf的时间很快&#xff0c;慢的是数据在网络间的传…

【读论文】End-to-end reproducible AI pipelines in radiology using the cloud

文章目录 End-to-end reproducible AI pipelines in radiology using the cloud01 研究背景与目的医学成像领域&#xff08;1&#xff09;研究现状&#xff08;2&#xff09;存在问题 其他研究领域&#xff1a;基因组学&#xff08;genomics&#xff09;研究目的&#xff1a;提…

Vue3使用vue-qrcode-reader实现扫码绑定设备功能

需求描述 移动端进入网站后&#xff0c;登录网站进入设备管理界面。点击添加设备&#xff0c;可以选择直接添加或者扫一扫。点击扫一扫进行扫描二维码获取设备序列号自动填充到添加设备界面的序列号输入框中。然后点击完成进行设备绑定。 安装vue-qrcode-reader 这里使用的版…

《OpenCV计算机视觉》—— 身份证号码识别案例

文章目录 一、案例实现的整体思路二、代码实现1.首先定义两个函数2.模板图像中数字的定位处理3.身份证号码数字的定位处理4.使用模板匹配&#xff0c;计算匹配得分&#xff0c;找到正确结果 一、案例实现的整体思路 下面是一个数字0~9的模板图片 案例身份证如下&#xff1a; 对…

http有什么方法升级成https?

&#x1f512; 获取与安装证书 JoySSL注册填写申请码230907即可领取免费申请资格https://www.joyssl.com/certificate/select/free.html?nid7 &#x1f4c4; 申请SSL证书 选择证书&#xff1a;首先需选择合适的SSL证书&#xff0c;如域名认证&#xff08;DV&#xff09;、公…

120页ppt丨集团公司战略规划内容、方法、步骤及战略规划案例研究

响应会员需求&#xff0c;晓零分享一份经典资料《120页ppt集团公司战略规划内容、方法、步骤及战略规划案例研究》&#xff0c;欢迎进入星球下载学习。 以下是对企业战略规划三个阶段八个步骤的详细解析&#xff1a; 一、阶段一&#xff1a;内外分析 项目启动和前期准备&…

Parallels Desktop 20 发布下载,macOS Sequoia 和 Windows 11 24H2 支持准备就绪

Parallels Desktop for Mac 20.0.0 (build 55653) - 在 Mac 上运行 Windows macOS Sequoia 和 Windows 11 24H2 支持准备就绪 请访问原文链接&#xff1a;https://sysin.org/blog/parallels-desktop/&#xff0c;查看最新版。原创作品&#xff0c;转载请保出处。 作者主页&a…

Java | Leetcode Java题解之第400题第N位数字

题目&#xff1a; 题解&#xff1a; class Solution {public int findNthDigit(int n) {int d 1, count 9;while (n > (long) d * count) {n - d * count;d;count * 10;}int index n - 1;int start (int) Math.pow(10, d - 1);int num start index / d;int digitInde…

wifiip地址可以随便改吗?wifi的ip地址怎么改变

对于普通用户来说&#xff0c;WiFi IP地址的管理和修改往往显得神秘而复杂。本文旨在深入探讨WiFi IP地址是否可以随意更改&#xff0c;以及如何正确地改变WiFi的IP地址。虎观代理小二将详细解释WiFi IP地址的基本概念、作用以及更改时需要注意的事项&#xff0c;帮助用户更好地…

欧盟《人工智能法案》的重点监管要求

文章目录 前言一、欧盟《人工智能法案》的重点监管要求(一)基于风险的监管路径1.具有不可接受风险的人工智能系统2.高风险人工智能系统3.有限风险与低风险人工智能系统(二)对高风险人工智能的监管要求1.针对高风险人工智能系统的要求2.针对高风险人工智能系统产业链参与者的…

shader 案例学习笔记之fract函数

fract函数 可以理解为模1取余&#xff0c;获取一个数的小数部分&#xff0c;如果参数是向量&#xff0c;那就是获取每个向量分量上的小数 案例一 #ifdef GL_ES precision mediump float; #endif// 渲染分辨率 uniform vec2 u_resolution; // 程序运行时间 uniform float u_ti…

【卷起来】VUE3.0教程-08-路由管理

在Vue中&#xff0c;我们可以通过vue-router路由管理页面之间的关系。 Vue Router是Vue.js的官方路由&#xff0c;它与Vue.js核心深度集成&#xff0c;让用Vue.js构建单页应用变得轻而易举。 &#x1f332; 在Vue中引入路由 安装路由 npm install --save vue-router 建立三个…

【C++登堂入室】类和对象(中)——类的6个默认成员函数

目录 一、类的6个默认成员函数 ​编辑二、构造函数 2.1 概念 2.2 特性 三、析构函数 3.1 概念 3.2 特性 四、拷贝构造函数 4.1 概念 4.2 特征 五、赋值运算符重载 5.1 运算符重载 5.2 赋值运算符重载 5.3 前置和后置重载 六、日期类的实现 七、const成员 八、…

气膜建筑:设备吊装口临时封闭的理想选择—轻空间

在设备吊装作业中&#xff0c;吊装口的临时封闭对于保障工作环境安全、设备保护及操作顺利至关重要。传统封闭方式&#xff0c;如钢结构或简易的盖板封闭&#xff0c;不仅耗时耗力&#xff0c;还可能影响施工效率。气膜建筑技术凭借其轻便、快速和高效的特点&#xff0c;为设备…

亚信安全亮相2024国家网安周主会场,多样活动助推行业新发展

9月9日至15日&#xff0c;2024年国家网络安全宣传周在全国范围内统一开展。本届网安周以“网络安全为人民&#xff0c;网络安全靠人民”为主题&#xff0c;亚信安全网安周系列活动在全国30多个城市全面展开&#xff0c;通过线下展览、专题论坛和网络安全知识宣讲等多种形式&…

【软件方案】大屏可视化智能展示平台解决方案(word原件完整版)

构建综合大屏可视化展示平台&#xff0c;旨在整合各业务板块&#xff0c;打造统一大数据分析引擎。此平台将深度融合数据驾驶舱与智慧调度系统&#xff0c;实现对企业运营的全面洞察与高效指挥。我们深入钻研客户信息数据&#xff0c;秉承“大数据”精髓&#xff0c;推动业务模…

【测试八股】软件测试面试八股文

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 以下是软件测试相关的面试题及答案&#xff0c;希望对各位能有帮助&#xff01; 1、测试分为哪几个阶段? 一般来说分为5个阶段&#xff1a;单元测试、集成测试…

警惕!血糖升高初期,这10大微妙信号你捕捉到了吗?

在这个快节奏的时代&#xff0c;饮食不规律、缺乏运动等生活习惯悄然间让高血糖这一“隐形杀手”潜伏在我们身边。然而&#xff0c;高血糖并非悄无声息&#xff0c;它在早期往往会通过一系列微妙却重要的身体信号向我们发出警告。今天&#xff0c;就让我们一同揭开血糖高早期的…

【Unity错误】No cloud project ID was found by the Analytics SDK

在编译默认的URP 2D项目时&#xff0c;出现这样一个错误&#xff1a;No cloud project ID was found by the Analytics SDK. This means Analytics events will not be sent. Please make sure to link your cloud project in the Unity editor to fix this problem. 原因&…

yolov5明厨亮灶检测系统,厨师帽-口罩检测,带pyqt界面-可检测图片和视频,支持中文标签,检测接口已封装好并优化,代码可读性强!

明厨亮灶检测系统是一个专门用于餐饮业厨房安全监管的智能系统。该系统结合了先进的计算机视觉技术&#xff0c;尤其是使用YOLOv5模型进行厨师帽和口罩的实时检测&#xff0c;并通过PyQt5构建了一个用户友好的图形界面。该系统不仅能够检测图片和视频中的目标&#xff0c;而且支…