ATF UFS初始化笔记

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=2ufshc_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 Attributeufshc_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");elseWARN("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

设备返回给主机的NOP IN response

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

COMMAND UPIU

UTRD header: 	0x11000000 0x0 0xf 0x0 0x1ffc0080 0x0 0x8000e 0x0 
CMD UPIU: 		0x1000001 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=01(COMMAND)Flags=00LUN=00Task Tag=01
Command Set Type=00Reserved=00Reserved=00Reserved=00
Total EHS Length=00hReserved=00Data Length MSB=00Data Length LSB=00
Expected Data Transfer Length[31:24]=00[23:16]=00[15:8]=00[7:0]=00
CDB[0] (OP)=00(CDBCMD_TEST_UNIT_READY)CDB[1]=00CDB[2]=00CDB[3]=00
CDB[4]=00CDB[5]=00CDB[6]=00CDB[7]=00
CDB[8]=00CDB[9]=00CDB[10]=00CDB[11]=00
CDB[12]=00CDB[13]=00CDB[14]=00CDB[15]=00

RESPONSE UPIU

UTRD header: 	0x11000000 0x0 0x0 0x0 0x1ffc0080 0x0 0x8000e 0x0 
CMD UPIU: 		0x1000001 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
RESP UPIU: 		0x1000021 0x2000000 0x140000 0x0 0x0 0x0 0x0 0x0 0x701200 0x5 0xa00 0x200000 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=21(RESPONSE)Flags=00LUN=00Task Tag=01
Command Set Type=00Reserved=00Response=00Status=02(CHECK CONDITION)
Total EHS Length=00hReserved=00Data Length MSB=Data Length LSB=00
Expected Data Transfer Length[31:24]=00[23:16]=00[15:8]=00[7:0]=00
Reserved=00Reserved=00Reserved=00Reserved=00
Reserved=00Reserved=00Reserved=00Reserved=00
Reserved=00Reserved=00Reserved=00Reserved=00
Reserved=00Reserved=00Reserved=00Reserved=00
K=00K+1=0x12K+2(Response Code)=0x70K+3=0
K+4=0x05K+5=0K+6=0K+7=0
K+8=0x0K+9=0x0AK+10=0K+11=0
K+12=0K+13=0K+14=0x20K+15=0
K+16=0K+17=0

在这里插入图片描述

SET FDEVICE_INIT UPIU

READ CAPACITY UPIU

READ DEVICE DESCRIPTOR UPIU

READ BLOCK UPIU

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

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

相关文章

多线程——死锁

死锁 在Java中使用多线程&#xff0c;就会有可能导致死锁问题。死锁会让程序一直卡住&#xff0c;程序不再往下执行。 我们只能通过中止并重启的方式来让程序重新执行。 这是我们非常不愿意看到的一种现象&#xff0c;我们要尽可能避免死锁的情况发生&#xff01; 死锁的原因…

数据结构之栈和队列的应用

目录 一、栈的应用 1. 括号匹配 2. 计算后缀表达式 方法一&#xff08;栈&#xff09; 方法二&#xff08;数组模拟栈&#xff09; 二、队列应用 1. 二叉树层序遍历 方法一&#xff08;队列&#xff09; 三、总结 一、栈的应用 1. 括号匹配 给定一个只包括 (&#xf…

List<Map<String, Object>>汇总统计排序

开发环境&#xff1a;jdk 1.8 需求一&#xff1a; 1、统计每个小时(升序)不同事件的产品产量 2、统计不同事件&#xff08;OK 、NG&#xff09;的总产量 public static void main(String[] args) {//数据源List<Map<String, Object>> list new ArrayList<Map…

云计算实训48——k8s环境搭建(详细版)

1.创建主机、设置ip、设置hostname 2.设置免密登录 # 生成私钥 [rootk8s-master ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/id_rsa already exists. Overwrite (y/n)? y Enter passphr…

77-java 装饰器模式和适配器模式区别

‌Java中的装饰器模式和适配器模式虽然都涉及到对象的组合和包装&#xff0c;但它们的应用场景和目的有所不同。‌ ‌装饰器模式的目的是在不修改原始对象的基础上&#xff0c;动态地添加功能或行为。‌它允许用户通过创建一个包含原始对象的包装类&#xff08;装饰器&#xff…

Computer Vision的学习路线

学习**Computer Vision&#xff08;计算机视觉&#xff09;**的过程中&#xff0c;可以按照以下步骤循序渐进地掌握基础知识、算法和实际应用。这个学习路线将涵盖从基础理论到前沿技术的各个层面。 1. 数学与基础知识 1.1 线性代数 计算机视觉中的图像处理和模型训练都依赖…

Uni-app 开发微信小程序

随着移动互联网的发展&#xff0c;微信小程序已经成为一种流行的应用开发模式。Uni-app 作为一种跨平台的开发框架&#xff0c;使用 Vue.js 语法&#xff0c;能够方便快速地开发出 微信小程序、H5、App 等多端应用。本指南将引导您从环境配置到实战案例开发&#xff0c;帮助您快…

vue3 使用swiper制作带缩略图的轮播图

效果图 实现代码 <template><div class"wrap"><!-- 主轮播图 --><swiper :style"{--swiper-navigation-color: #fff,--swiper-pagination-color: #fff,}" :modules"modules" :navigation"true" :thumbs"{ …

计算机网络 第2章 物理层

文章目录 通信基础基本概念信道的极限容量编码与调制常用的编码方法常用的调制方法 传输介质双绞线同轴电缆光纤以太网对有限传输介质的命名规则无线传输介质物理层接口的特性 物理层设备中继器集线器一些特性 物理层任务&#xff1a;实现相邻节点之间比特&#xff08;0或1&…

GORM高级查询

在日常开发中&#xff0c;我们经常需要执行复杂的数据库查询以满足各种业务需求。GORM作为Go语言中一个流行的ORM库&#xff0c;提供了许多高级查询功能&#xff0c;可以帮助我们高效地处理这些复杂场景。本文将详细介绍GORM的高级查询功能&#xff0c;包括智能选择字段、锁、子…

pptpd配置文件/etc/pptpd.conf详解

正文共&#xff1a;1111 字 2 图&#xff0c;预估阅读时间&#xff1a;1 分钟 如果要在Linux系统配置PPTP&#xff08;Point-to-Point Tunneling Protocol&#xff0c;点到点隧道协议&#xff09;VPN&#xff0c;一般是使用pptpd软件。pptpd命令通常从配置文件/etc/pptpd.conf中…

单片机拍照_将采集的RGB图像封装为BMP格式保存到SD卡

文章目录 一、前言二、BMP文件结构2.1 BMP图片的格式说明 2.2 RGB888与RGB565格式是什么&#xff1f;&#xff08;1&#xff09;RGB565&#xff08;2&#xff09;RGB888&#xff08;3&#xff09;区别&#xff08;4&#xff09;如何构成&#xff08;5&#xff09;示例 三、实现…

【Leetcode56】合并区间(数组 | 排序)

文章目录 一、题目二、思路三、代码 一、题目 二、思路 先将所有子列表按照start_pos进行排序&#xff0c;有利于保持顺序性&#xff0c;每次处理新子列表时&#xff0c;只用和结果列表ans_lst的最后一个子列表对比&#xff0c;如果有重合则合并&#xff0c;然后将合并的新子列…

Java 入门指南:Java 并发编程 —— 同步工具类 Phaser(相位器)

文章目录 同步工具类Phaser主要特点核心方法使用步骤适用场景使用示例 同步工具类 JUC&#xff08;Java.util.concurrent&#xff09;是 Java 提供的用于并发编程的工具类库&#xff0c;其中包含了一些通信工具类&#xff0c;用于在多个线程之间进行协调和通信&#xff0c;特别…

创新实验报告VC++案例开发十二生肖的俄罗斯方块智力游戏完整代码设计方案

一&#xff0e;项目名称 十二生肖俄罗斯方块 二&#xff0e;开发背景&#xff1a; 俄罗斯方块是一个很低古老的一个小游戏&#xff0c;到但今日它还有很大的魅力。 三&#xff0e;技术路线或工作原理&#xff1a; 采用的软件及开发平台 Micosoft Visual 6.0 项目的总体方…

Kotlin 极简小抄 P1(变量与常量、基本数据类型、流程控制)

一、Kotlin Kotlin 由 JetBrains 开发&#xff0c;是一种在 JVM&#xff08;Java 虚拟机&#xff09;上运行的静态类型编程语言 Kotlin 旨在提高开发者的编码效率和安全性&#xff0c;同时保持与 Java 的高度互操作性 Kotlin 是 Android 应用开发的首选语言&#xff0c;也可以…

uniapp 原生插件开发 UI

前言&#xff1a; 在集成某些特定 原生SDK的时候&#xff0c;它本身是带UI控件的。当我们使用 uniapp 开发app的时候实是 可以使使用 nvue 页面&#xff0c;以 weex 的方式嵌入原生的UI控件。 我这边的场景是 接入连连app的支付&#xff0c;它有个自己的密码键盘 控件是原生的页…

树形弹窗选择框/vue2/Element/弹框选择

前言 此类选择器根据vueelementUI实现&#xff0c;使用vue3的可以根据此案例稍作改动即可实现&#xff0c;主要功能有弹出选择、搜索过滤、搜索结果高亮等&#xff0c;此选择器只支持单选&#xff0c;如需多选可在此基础进行改造。 效果图 代码实现 使用时&#xff0c;props-…

NVIDIA AI Workbench 让 Windows 上的 GPU 使用更加简便

NVIDIA AI Workbench 是一款免费的、用户友好型开发环境管理器&#xff0c;可在您选择的系统&#xff08;PC、工作站、数据中心或云&#xff09;上简化数据科学、ML 和 AI 项目。在 Windows、macOS 和 Ubuntu 上&#xff0c;您可以本地开发、测试项目和构建项目原型&#xff0c…

Redis 持久化机制详解

引言 Redis 是一款基于内存的高性能键值存储系统&#xff0c;为了在数据丢失时能快速恢复&#xff0c;Redis 提供了多种持久化机制。这些持久化机制可以将内存中的数据存储到磁盘上&#xff0c;确保即使系统重启或宕机后也能恢复数据。Redis 支持两种主要的持久化方式&#xf…