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

zynq sd卡初始化流程

1  sd控制器的初始化 :XSdPs_CfgInitialize();

s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
				u32 EffectiveAddr)
{
	s32 Status;
	u8 PowerLevel;
	u8 ReadReg;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(ConfigPtr != NULL);

	/* Set some default values. */
	InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
	InstancePtr->Config.BaseAddress = EffectiveAddr;
	InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
	InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
	InstancePtr->Config.CardDetect =  ConfigPtr->CardDetect;
	InstancePtr->Config.WriteProtect =  ConfigPtr->WriteProtect;
	InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
	InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
	InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
	InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
	InstancePtr->SectorCount = 0;
	InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
	InstancePtr->Config_TapDelay = NULL;
	InstancePtr->Dma64BitAddr = 0U;

	/* Disable bus power and issue emmc hw reset */
	if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
			XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK) ==
			XSDPS_HC_SPEC_V3)
		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
				XSDPS_POWER_CTRL_OFFSET, XSDPS_PC_EMMC_HW_RST_MASK);
	else
		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
				XSDPS_POWER_CTRL_OFFSET, 0x0);

    //对eMMC设备执行硬件复位(通过拉高EMMC_HW_RST信号),确保设备进入初始状态,
      
	/* Delay to poweroff card */
    (void)usleep(1000U);
    //eMMC JEDEC标准要求硬件复位后需等待至少1ms电源稳定时间‌

	/* "Software reset for all" is initiated */
	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
			XSDPS_SWRST_ALL_MASK);

	/* Proceed with initialization only after reset is complete */
	ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
				XSDPS_SW_RST_OFFSET);
	while ((ReadReg & XSDPS_SWRST_ALL_MASK) != 0U) {
		ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
				XSDPS_SW_RST_OFFSET);
	}
    //等待软复位完成
	/* Host Controller version is read. */
	 InstancePtr->HC_Version =
			(u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
			XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
    
	/*
	 * Read capabilities register and update it in Instance pointer.
	 * It is sufficient to read this once on power on.
	 */
	InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
						XSDPS_CAPS_OFFSET);

	/* Select voltage and enable bus power. */
	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3)
		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
				XSDPS_POWER_CTRL_OFFSET,
				(XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK) &
				~XSDPS_PC_EMMC_HW_RST_MASK);
	else
		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
				XSDPS_POWER_CTRL_OFFSET,
				XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);


    
     
	/* Delay before issuing the command after emmc reset */
	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3)
		if ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) ==
				XSDPS_CAPS_EMB_SLOT)
			usleep(200);

    //根据主机能力寄存器(Host_Caps)选择3.3V/3.0V/1.8V供电(优先支持3.3V)。
	/* Change the clock frequency to 400 KHz */
	Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);
	if (Status != XST_SUCCESS) {
		Status = XST_FAILURE;
		goto RETURN_PATH ;
	}


    //根据主机能力寄存器(Host_Caps)选择3.3V/3.0V/1.8V供电(优先支持3.3V)。

    if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK) != 0U) {
		PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK;
	} else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK) != 0U) {
		PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK;
	} else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK) != 0U) {
		PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK;
	} else {
		PowerLevel = 0U;
	}

	/* Select voltage based on capability and enable bus power. */
	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
			XSDPS_POWER_CTRL_OFFSET,
			PowerLevel | XSDPS_PC_BUS_PWR_MASK);

	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
		/* Enable ADMA2 in 64bit mode. */
		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
				XSDPS_HOST_CTRL1_OFFSET,
				XSDPS_HC_DMA_ADMA2_64_MASK);
	} else {
		/* Enable ADMA2 in 32bit mode. */
		XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
				XSDPS_HOST_CTRL1_OFFSET,
				XSDPS_HC_DMA_ADMA2_32_MASK);
	}


    //开启所有正常中断(除卡检测)和错误中断的状态记录
	/* Enable all interrupt status except card interrupt initially */
	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_NORM_INTR_STS_EN_OFFSET,
			XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));

	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_ERR_INTR_STS_EN_OFFSET,
			XSDPS_ERROR_INTR_ALL_MASK);


    //初始化阶段禁用中断信号触发,防止未就绪的中断服务程序(ISR)误执行。
	/* Disable all interrupt signals by default. */
	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U);
	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U);


    
	/*
	 * Transfer mode register - default value
	 * DMA enabled, block count enabled, data direction card to host(read)
	 */
	TransferMode = XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
			XSDPS_TM_DAT_DIR_SEL_MASK;


    //512字节‌是SD/eMMC协议的标准块大小,适用于大多数存储设备的初始化阶段‌。
    块大小需与物理扇区大小一致,否则可能导致数据传输错误或CRC校验失败‌
	/* Set block size to 512 by default */
	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);

	Status = XST_SUCCESS;

RETURN_PATH:
	return Status;

}

2 sd卡的初始化 XSdPs_MmcCardInitialize();

---->如果是sd卡时,检测sd卡是否插入。XSDPS_CAPS_EMB_SLOT 嵌入式卡槽,这里代表emcc。

	if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) ||
				((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
				!= XSDPS_CAPS_EMB_SLOT)) {
		if(InstancePtr->Config.CardDetect != 0U) {
			/*
			 * Check the present state register to make sure
			 * card is inserted and detected by host controller
			 */
			PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
					XSDPS_PRES_STATE_OFFSET);
			if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)	{
				Status = XST_FAILURE;
				goto RETURN_PATH;
			}
		}
	}

命令编号    类型    命令名称    描述
CMD0    CMD    GO_IDLE_STATE    将SD卡置于空闲状态。
CMD2    CMD    ALL_SEND_CID    请求卡发送其卡识别号(CID)。
CMD3    CMD    SEND_RELATIVE_ADDR    请求卡发布一个新的相对地址(RCA),这是卡的网络地址。
CMD5    CMD    IO_SEND_OP_COND    SDIO特有命令,用于发送操作条件。
CMD7    CMD    SELECT/DESELECT_CARD    选择或取消选择RCA指定的卡。
CMD8    CMD    SEND_IF_COND    发送接口条件,验证供电电压范围,并提供一种方法来验证主机支持的最高版本的SD物理层规范。
CMD9    CMD    SEND_CSD    请求选定的卡发送其卡特定数据(CSD)。
CMD10    CMD    SEND_CID    请求选定的卡发送其卡识别号(CID)。
CMD12    CMD    STOP_TRANSMISSION    强制卡停止当前的数据读取或写入过程。
CMD13    CMD    SEND_STATUS    查询选定卡的状态。
CMD16    CMD    SET_BLOCKLEN    设置块长度,用于后续的块读取和写入操作。
CMD17    CMD    READ_SINGLE_BLOCK    从卡中读取一个单独的数据块。
CMD18    CMD    READ_MULTIPLE_BLOCK    连续地从卡中读取多个数据块。
CMD24    CMD    WRITE_BLOCK    向卡写入一个单独的数据块。
CMD25    CMD    WRITE_MULTIPLE_BLOCK    连续地向卡写入多个数据块。
CMD41    CMD    SD_SEND_OP_COND    发送操作条件命令,用于初始化步骤(ACMD41之前的初始化)。
CMD55    CMD    APP_CMD    标记接下来的命令为应用特定命令(ACMD)。
CMD58    CMD    READ_OCR    读取OCR寄存器的内容。
CMD59    CMD    CRC_ON_OFF    开启或关闭CRC校验。
应用特定命令(Application Specific Commands, ACMD)
命令编号    类型    命令名称    描述
ACMD41    ACMD    SD_SEND_OP_COND    发送SD操作条件命令,用于初始化SD卡。
ACMD51    ACMD    SEND_SCR    请求卡发送其配置寄存器(SCR)内容。

---->发送复位命令,将设备置于空闲状态。

	/* CMD0 no response expected */
	Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);
	if (Status != XST_SUCCESS) {
		Status = XST_FAILURE;
		goto RETURN_PATH;
	}

---->通过发送 CMD1 命令与 SD 卡通信,直到卡完成上电初始化并准备好进入操作状态.

 XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL 通知sd卡主机支持HCS高容量和高电压。

cmd1是zynq上的特有命令 类似 sd标准协议中的 cmd 8 和cmd41.

	RespOCR = 0U;
	/* Send CMD1 while card is still busy with power up */
	while ((RespOCR & XSDPS_RESPOCR_READY) == 0U) {

		/* Host High Capacity support & High volage window */
		Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
				XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
		if (Status != XST_SUCCESS) {
			Status = XST_FAILURE;
			goto RETURN_PATH;
		}

		/* Response with card capacity */
		RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
				XSDPS_RESP0_OFFSET);

	}

---->通过解析 OCR 数据中的 HCS 标志位,更新主机实例中的 HCS 标志,如果卡支持高容量模式,则将 InstancePtr->HCS 设置为 1。

	/* Update HCS support flag based on card capacity response */
	if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) {
		InstancePtr->HCS = 1U;
	}

---->通过发送 CMD2 命令获取 SD 卡的 CID 数据,并将其存储到主机实例中。

	/* CMD2 for Card ID */
	Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);
	if (Status != XST_SUCCESS) {
		Status = XST_FAILURE;
		goto RETURN_PATH;
	}

	InstancePtr->CardID[0] =
			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
			XSDPS_RESP0_OFFSET);
	InstancePtr->CardID[1] =
			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
			XSDPS_RESP1_OFFSET);
	InstancePtr->CardID[2] =
			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
			XSDPS_RESP2_OFFSET);
	InstancePtr->CardID[3] =
			XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
			XSDPS_RESP3_OFFSET);

---->通过发送 CMD3 和 CMD9 命令,分别为 SD 卡分配相对卡地址(RCA)并获取卡的特定数据(CSD),RCA 是主机用来唯一标识和寻址卡的一个 16 位值,CSD 包含卡的容量、块大小、读写速度等信息

	/* Set relative card address */
	InstancePtr->RelCardAddr = 0x12340000U;
	Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U);
	if (Status != XST_SUCCESS) {
		Status = XST_FAILURE;
		goto RETURN_PATH;
	}

	Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);
	if (Status != XST_SUCCESS) {
		Status = XST_FAILURE;
		goto RETURN_PATH;
	}

---->从 SD 卡控制器的响应寄存器中读取卡的 CSD 数据,并将其存储到 CSD 数组中,(在发送 CMD9 后,卡会返回其 CSD 数据。这些数据被分成 4 个 32 位寄存器(RESP0 到 RESP3),并通过读取寄存器的方式提取)

	/*
	 * Card specific data is read.
	 * Currently not used for any operation.
	 */
	CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
			XSDPS_RESP0_OFFSET);
	CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
			XSDPS_RESP1_OFFSET);
	CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
			XSDPS_RESP2_OFFSET);
	CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
			XSDPS_RESP3_OFFSET);
    //提取sd卡的版本号
	InstancePtr->Card_Version =  (CSD[3] & CSD_SPEC_VER_MASK) >>18U;

---->根据 CSD 数据中的字段计算 SD 卡的总容量,并将其转换为以 512 字节为单位的扇区数量。这是 SD 卡初始化流程中的重要一步,用于为主机提供卡的容量信息。

	/* Calculating the memory capacity */
	BlkLen = 1 << ((CSD[2] & READ_BLK_LEN_MASK) >> 8U);
	Mult = 1 << (((CSD[1] & C_SIZE_MULT_MASK) >> 7U) + 2U);
	DeviceSize = (CSD[1] & C_SIZE_LOWER_MASK) >> 22U;
	DeviceSize |= (CSD[2] & C_SIZE_UPPER_MASK) << 10U;
	DeviceSize = (DeviceSize + 1U) * Mult;
	DeviceSize =  DeviceSize * BlkLen;

	InstancePtr->SectorCount = (DeviceSize/XSDPS_BLK_SIZE_512_MASK);

3 完成 SD/eMMC 卡的初始化流程中的几个关键步骤,包括更改时钟频率、选择卡、设置块大小以及读取 eMMC 的扩展 CSD(Extended Card Specific Data)。

    Status=XSdPs_Change_ClkFreq(&ps7_EMMC,50000000);
    Status=XSdPs_Select_Card(&ps7_EMMC);
    Status=XSdPs_SetBlkSize(&ps7_EMMC,XSDPS_BLK_SIZE_512_MASK);
    Status=XSdPs_Get_Mmc_ExtCsd(&ps7_EMMC,Emmc_ExtCsd);
  • 通过调用 XSdPs_Change_ClkFreq 函数,将控制器的时钟频率调整到更高的值(50 MHz),以提高数据传输速率。
  • 通过调用 XSdPs_Select_Card 函数,发送 CMD7 命令, 选择RCA指定的卡,将目标卡置于传输状态。
  • 通过调用 XSdPs_SetBlkSize 函数,cmd16 设置传输块大小为 512 字节。
  • 对于 eMMC 卡,通过调用 XSdPs_Get_Mmc_ExtCsd 函数,发送 CMD8 命令以读取扩展 CSD 数据。获取更多关于卡的详细信息。

4 XSdPs_Get_Mmc_ExtCsd()的详细流程

---->配置块的数量为1和块的大小为512 (CSD 只占用一个块),设置 ADMA2 描述符表。

	BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
	BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
	BlkSize &= XSDPS_BLK_SIZE_MASK;
	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_BLK_SIZE_OFFSET, BlkSize);

	XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);

---->缓存一致性设置

	if (InstancePtr->Config.IsCacheCoherent == 0) {
		Xil_DCacheInvalidateRange((INTPTR)ReadBuff, 512U);
	}

---->配置传输模式 传输方向为卡到主机,使能dma

TransferMode = 	XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK;

---->通过发送 CMD8 命令(SEND_EXT_CSD)请求 eMMC 卡返回其扩展 CSD(Extended Card Specific Data)。

	/* Send SEND_EXT_CSD command */
	Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
	if (Status != XST_SUCCESS) {
		Status = XST_FAILURE;
		goto RETURN_PATH;
	}

---->通过轮询方式监控 SD/eMMC 数据传输的状态,确保传输顺利完成或及时处理错误。

/*
	 * Check for transfer complete
	 * Polling for response for now
	 */
	do {
		StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
					XSDPS_NORM_INTR_STS_OFFSET);
		if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
			/* Write to clear error bits */
			XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
					XSDPS_ERR_INTR_STS_OFFSET,
					XSDPS_ERROR_INTR_ALL_MASK);
			Status = XST_FAILURE;
			goto RETURN_PATH;
		}
	} while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);

	/* Write to clear bit */
	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);

总结 sd卡初始化时,发送sd命令顺序 cmd 0 1  2  3  9   7   16   8.

5 XSdPs_WritePolled 函数流程

检查SD卡是否已插入并初始化。
设置块大小(通常为512字节)。
配置DMA传输模式(支持64位地址或32位地址)。
根据块数量发送单块或多块写命令(CMD24 或 CMD25)。
轮询检查传输是否完成,并处理传输错误。

s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
{
	s32 Status;
	u32 PresentStateReg;
	u32 StatusReg;

	if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) ||
				((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
				!= XSDPS_CAPS_EMB_SLOT)) {
		if(InstancePtr->Config.CardDetect != 0U) {
			/* Check status to ensure card is initialized */
			PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
					XSDPS_PRES_STATE_OFFSET);
			if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {
				Status = XST_FAILURE;
				goto RETURN_PATH;
			}
		}
	}

	/* Set block size to 512 if not already set */
	if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
			XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
		Status = XSdPs_SetBlkSize(InstancePtr,
			XSDPS_BLK_SIZE_512_MASK);
		if (Status != XST_SUCCESS) {
			Status = XST_FAILURE;
			goto RETURN_PATH;
		}

	}

	if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) {
		XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt);
	} else {
		XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
		if (InstancePtr->Config.IsCacheCoherent == 0) {
			Xil_DCacheFlushRange((INTPTR)Buff,
				BlkCnt * XSDPS_BLK_SIZE_512_MASK);
		}
	}

	if (BlkCnt == 1U) {
		TransferMode = XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DMA_EN_MASK;

		/* Send single block write command */
		Status = XSdPs_CmdTransfer(InstancePtr, CMD24, Arg, BlkCnt);
		if (Status != XST_SUCCESS) {
			Status = XST_FAILURE;
			goto RETURN_PATH;
		}
	} else {
		TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
			XSDPS_TM_BLK_CNT_EN_MASK |
			XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK;

		/* Send multiple blocks write command */
		Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
		if (Status != XST_SUCCESS) {
			Status = XST_FAILURE;
			goto RETURN_PATH;
		}
	}

	/*
	 * Check for transfer complete
	 * Polling for response for now
	 */
	do {
		StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
					XSDPS_NORM_INTR_STS_OFFSET);
		if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
			/* Write to clear error bits */
			XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
					XSDPS_ERR_INTR_STS_OFFSET,
					XSDPS_ERROR_INTR_ALL_MASK);
			Status = XST_FAILURE;
			goto RETURN_PATH;
		}
	} while((StatusReg & XSDPS_INTR_TC_MASK) == 0U);

	/* Write to clear bit */
	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
			XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);

	Status = XST_SUCCESS;

	RETURN_PATH:
		return Status;
}

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

相关文章:

  • mybaties plus 更新null值进入数据库
  • 【AI编程技术爆发:从辅助工具到生产力革命】
  • 博客园账户注册全流程指南(附常见问题)
  • windows安卓子系统wsa隐藏应用列表的安装激活使用
  • OpenHarmony 5.0版本视频硬件编解码适配
  • 零基础开始学习鸿蒙开发-智能家居APP离线版介绍
  • 基于PLC的采摘机械手(论文+源码)
  • 《Vue Router实战教程》12.不同的历史记录模式
  • 《Python星球日记》第22天:NumPy 基础
  • 安科瑞EMS3.0破解工业企业源网荷储一体化“用能三难”问题 帮助企业高效管理
  • 什么是TensorFlow?
  • OpenGL学习笔记(assimp封装、深度测试、模板测试)
  • 全场景赋能|燕千云打造企业级智能运维平台
  • TensorFlow充分并行化使用CPU
  • 国产Linux系统统信安装redis教程步骤
  • 基于SpringBoot的动物救助中心系统(源码+数据库)
  • Zen 5白色装机优选,华硕X870 AYW GAMING WIFI W主板来了!
  • 网工基础 | 常见英文术语注解
  • 新闻推荐系统(springboot+vue+mysql)含万字文档+运行说明文档
  • 参照Spring Boot后端框架实现序列化工具类
  • [特殊字符] 第十一讲 | 空间回归模型实战:SAR / SEM / GWR逐个击破
  • python办公自动化------word文件的操作
  • xlinx GT传输器学习
  • Spring Cloud 远程调用
  • 初识SpringAI(接入硅基流动deepseek)
  • <C#>在 C# .NET 中,使用 LoggerExtensions方法创建日志
  • 修改Todesk软件显示的设备码的办法
  • 前端请求设置credentials: ‘include‘导致的cors问题
  • 网络安全1
  • Git中git rebase 和 git merge使用及区别