⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdhal.c

📁 SmartARM2400系列开发板全套资料
💻 C
📖 第 1 页 / 共 3 页
字号:
    
    lpc_mci.RecCnt = 0;                                     /* 初始化mci_struct结构体全局变量lpc_mci */
    lpc_mci.RxTxFlag = MCI_RESET_FLAG;
    lpc_mci.psds = sds;    
    lpc_mci.CurTran = MCI_CUR_REC; 
         
	return SD_NO_ERR;
}


/*******************************************************************************************************************
** 函数名称: SdHal_ReadBlock()				
**
** 功能描述: 在发送读单块命令之后, 由硬件控制器实现读取数据
**
** 输   入: sd_struct *sds  :  卡信息结构体 
**	         
** 输   出: INT8U *recbuf: 接收缓冲区, 大小为512字节
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_ReadBlock(sd_struct *sds, INT8U *recbuf)
{
	INT32U DataCtrl = 0;
	INT8U ret;
			
	lpc_mci.pRecBuf = recbuf;	

#if LPC24xx_MCI_DMA_EN
    // DMA 控制器初始化
	DMA_Init(1, P2M);                                                           
	DMACC1Configuration |= 0x10001 | (0x04 << 1) | (0x00 << 6) | (0x06 << 11);
	
	// 设置数据控制寄存器: 读,块传输,DMA传输,块长度
	DataCtrl |= ((1 << 0) | (1 << 1) | (1 << 3) | (SD_BLOCKSIZE_NBITS << 4));	    
#else
    // 设置数据控制寄存器: 读,块传输,块长度
	DataCtrl |= ((1 << 0) | (1 << 1) | (SD_BLOCKSIZE_NBITS << 4));
#endif
	
#if SD_UCOSII_EN
    OS_ENTER_CRITICAL();
    MCIDataCtrl = DataCtrl;						                /* 启动数据传输 */
    OSSemPend(sds->pSemSdmmcRW, sds->timeout_read_os, &ret);    /* 进入等待状态 */
    if (ret == OS_NO_ERR)   
        ret = lpc_mci.RxTxFlag;                                 /* 返回数据接收结果 */                            
    else if (ret == OS_TIMEOUT)
        ret = SD_ERR_TIMEOUT_READ;                              /* 接收数据超时 */            
    else
        ret = SD_ERR_WAIT_WRSEM;                                /* 等待信号量失败 */
    
    OS_EXIT_CRITICAL();
#else	
    MCIDataCtrl = DataCtrl;                                     /* 启动数据传输 */
	do
	{                                                           /* 等待数据接收 */
	    if (lpc_mci.RxTxFlag == SD_NO_ERR)
	        break;                                              /* 数据接收成功 */
	}while (lpc_mci.RxTxFlag == MCI_RESET_FLAG);
	
	ret = lpc_mci.RxTxFlag;                                     /* 返回接收结果 */
#endif	

	MCIMask0 &= ~((DATA_RX_INT_MASK) | (FIFO_INT_MASK));        /* 仅禁止接收中断 */

#if LPC24xx_MCI_DMA_EN
    src_addr = (INT32U *)DMA_SRC;                               /* 取得 DMA 源地址 */         
	dest_addr = (INT32U *)DMA_DST;                              /* 取得 DMA 目标地址 */    
    if (ret == SD_NO_ERR)
        memcpy(recbuf, dest_addr, 512);                         /* 返回接收到的数据 */
#endif

    return ret;
}



/*******************************************************************************************************************
** 函数名称: SdHal_BeforeWriteBlock()				
**
** 功能描述: 在发送写单块命令之前, 给硬件控制器做一些事情的机会
**
** 输   入: 无 
**	         
** 输   出: INT8U *recbuf: 接收缓冲区, 大小为512字节
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_BeforeWriteBlock(sd_struct *sds)
{
	MCIMask0 = DATA_TX_INT_MASK | (FIFO_INT_MASK);	      /* 仅使能TX中断 */

	MCIClear = 0x7FF;							          /* 清空清零寄存器的所有标志 */
	MCIDataCtrl = 0;							          /* 数据控制寄存器清0 */
		 
	MCIDataTimer = sds->timeout_write;                    /* 写入写数据超时值 */
	MCIDataLength = SD_BLOCKSIZE;				          /* 数据块的长度 */
    MCIFifoCnt = 0;  
    
    lpc_mci.psds = sds;                                   /* 初始化lpc_mci结构体变量成员 */  
    lpc_mci.RxTxFlag = MCI_RESET_FLAG; 
    lpc_mci.SendCnt = 0;
    lpc_mci.CurTran = MCI_CUR_SEND;   
	return SD_NO_ERR;
}


/*******************************************************************************************************************
** 函数名称: SdHal_WriteBlock()				
**
** 功能描述: 在发送写单块命令之后, 由硬件控制器向卡发送数据
**
** 输   入: 无 
**	         
** 输   出: INT8U *recbuf: 接收缓冲区, 大小为512字节
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_WriteBlock(sd_struct *sds, INT8U *sendbuf)
{
	INT32U DataCtrl = 0;
	INT8U ret;
	
#if LPC24xx_MCI_DMA_EN
    src_addr = (INT32U *)DMA_SRC;                           
	dest_addr = (INT32U *)DMA_DST;
	//memcpy(sendbuf, src_addr, 512);
	memcpy(src_addr, sendbuf, 512);                              /* 复制要写入的数据到DMA源地址 */

	DMA_Init(0, M2P);                                            /* DMA控制器初始化 */
	DMACC0Configuration |= 0x00001 | (0x00 << 1) | (0x04 << 6) | (0x05 << 11);
	
	/* 设置数据控制寄存器: 写, 块传输, DMA, 数据长度 */
	DataCtrl |= ((1 << 0) | (1 << 3) | (SD_BLOCKSIZE_NBITS << 4));               
#else
 	lpc_mci.pSendBuf = sendbuf;
 	
 	/* 设置数据控制寄存器: 读, 块传输, 数据长度 */
 	DataCtrl |= ((1 << 0) | (SD_BLOCKSIZE_NBITS << 4));
#endif 	


#if SD_UCOSII_EN
    OS_ENTER_CRITICAL();
    MCIDataCtrl = DataCtrl;                                      /* 启动数据传输 */
    OSSemPend(sds->pSemSdmmcRW, sds->timeout_write_os, &ret);    /* 进入等待状态 */
    if (ret == OS_NO_ERR)
	    ret = lpc_mci.RxTxFlag;                                  /* 返回写块数据结果 */
    else if (ret == OS_TIMEOUT)
        ret = SD_ERR_TIMEOUT_WRITE;                              /* 返回等待超时 */
    else
        ret = SD_ERR_WAIT_WRSEM;                                 /* OSSemPend()执行失败 */
    
    OS_EXIT_CRITICAL();
#else
    MCIDataCtrl = DataCtrl;                                      /* 启动数据传输 */
	do
	{
	    if (lpc_mci.RxTxFlag == SD_NO_ERR)
	        break;                                               /* 发送数据成功 */   
	}while (lpc_mci.RxTxFlag == MCI_RESET_FLAG);
	
	ret = lpc_mci.RxTxFlag;                                      /* 返回发送数据执行结果 */
#endif

	MCIMask0 &= ~(DATA_TX_INT_MASK | FIFO_INT_MASK);	         /* 仅禁止TX中断 */
  
	return ret;
}


/*******************************************************************************************************************
** 函数名称: SDMMC_WaitReadyforData()				
**
** 功能描述: 等待卡可接收数据(等待卡中有空的接收缓冲区), 即等待卡状态寄存器的 bit8 为1, 
**
** 输   入: sd_struct *sds  : SD/MMC卡信息结构体 
**	         
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_WaitReadyforData(sd_struct *sds)
{    
    return (SdHal_WaitBusy(sds, BUSY_TYPE_RDY_DATA));
}


#define   SD_UCOSII_SMALLWAIT		256				            /* 运行于UCOS-II时的小等待时间(避免OSTimeDly(1)降低系统性能) */
#define   CMD13_CLK_NUM             160                         /* 一个CMD13大约需要160个clk */   

/*******************************************************************************************************************
** 函数名称: SdHal_WaitBusy()				
**
** 功能描述: 等待卡编程或擦除结束, 即等待卡状态由编程状态变为传输状态: prg --> tran
**
** 输   入: sd_struct *sds  : SD/MMC卡信息结构体 
**	         INT32U BusyType : 等待忙类型, 取值为: SD_WAIT_WRITE 和 SD_WAIT_ERASE
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_WaitBusy(sd_struct *sds, INT32U busytype)
{
    INT8U ret;
    INT32U status, timeout = 0, cnt = 0;
    INT32U stmask = CARD_STATUS_CURRENT_STATE;                
    INT32U stwait = CARD_STATUS_PRG;                            /* 等待时, 卡处于编程状态 */
    
    if (busytype == BUSY_TYPE_RDY_DATA)
    {
        timeout = sds->timeout_write / CMD13_CLK_NUM;           /* 写超时等待时间 */
        stmask = CARD_STATUS_RDY_DATA;
        stwait = 0;                                             /* 等待时, 卡的接收缓冲区未就绪 */
    }
    else if (busytype == BUSY_TYPE_PROG)
        timeout = sds->timeout_write / CMD13_CLK_NUM;           /* 擦除超时等待时间 */
    else if (busytype == BUSY_TYPE_ERASE)
        timeout = sds->timeout_erase / CMD13_CLK_NUM;
            
#if SD_UCOSII_EN 
    timeout = SD_UCOSII_SMALLWAIT;                              /* 先进行快速查询, 再每隔1 os tick查询 */
#endif

    do	
	{	
		ret = SdCmd_Send_Status(sds, &status);                  /* 读取卡的状态 */
		if (ret != SD_NO_ERR)
			return ret;
			
	    if (!SdHal_CheckCard(sds))                              /* 检测卡是否拔出 */
 		    return SD_ERR_NO_CARD; 	
			
		cnt++;			
	}while(((status & stmask) == stwait) && (cnt < timeout));

#if SD_UCOSII_EN
	if (cnt >= timeout)
	{                                                           /* 很少等待后卡仍忙 */
  		if ((busytype == BUSY_TYPE_RDY_DATA) || (busytype == BUSY_TYPE_PROG))
  			timeout = sds->timeout_write_os;
  		else
  			timeout = sds->timeout_erase_os;   
			
		cnt = 0;
   		do
   		{ 	
   			OSTimeDly(1);                                       /* 操作系统挂起1 tick */
   			
		    ret = SdCmd_Send_Status(sds, &status);              /* 读取卡的状态 */
		    if (ret != SD_NO_ERR)
		    	return ret;
			
	        if (!SdHal_CheckCard(sds))                          /* 检测卡是否拔出 */
 		        return SD_ERR_NO_CARD; 	   			
   			
   			cnt++;
    	}while(((status & stmask) == stwait) && (cnt < timeout));
	}
#endif	
	
	return SD_NO_ERR;
}


/*******************************************************************************************************************
** 函数名称: MCI_Delay()				
**
** 功能描述: 延时函数	
**
** 输   入: INT16U val:  延时值, 1大约相当于5ms
**							  	
** 输   出: 无
**
** 返 回 值: 无 
********************************************************************************************************************/
void MCI_Delay(INT16U val)
{
#if !SD_UCOSII_EN
    INT16U i,j;
    for (i = 0; i < val; i++)
        for (j = 0; j < 0xC000; j++);
#else
    OSTimeDly(val); 
#endif   
}


/*******************************************************************************************************************
** 函数名称: MCI_SendCmd()				
**
** 功能描述: 发送命令给卡, 但不获取响应
**
** 输   入: INT32U CmdIndex    : 命令索引
**           INT32U Argument    : 命令参数
**           INT32U ExpectResp  : 期望得到的回复 
**           INT32U AllowTimeout: 是否允许超时
**	         
** 输   出: 无
**
** 返 回 值: 无
********************************************************************************************************************/
void MCI_SendCmd(INT32U CmdIndex, INT32U Argument, INT32U ExpectResp, INT32U AllowTimeout)
{
    INT32U CmdData = 0, i;
	INT32U CmdStatus;
		
	while ((CmdStatus = MCIStatus) & MCI_CMD_ACTIVE)    /* 命令正在处理中 */
	{
		MCICommand = 0;                                 
		MCIClear = CmdStatus | MCI_CMD_ACTIVE;          /* 清除相关状态 */
		for(i = 0; i < 0x20; i++);
	}	
		
	CmdData |= (CmdIndex & 0x3F);	                    /* 命令索引只有bit0 ~ bit5 有效 */
	if (ExpectResp == EXPECT_NO_RESP)			        /* 无响应类型 */
	{
		CmdData &= ~((1 << 6) | (1 << 7));		        /* 清除短响应和长响应位 */
	}
	else if (ExpectResp == EXPECT_SHORT_RESP)	        /* 希望得到短响应 */
	{
		CmdData |= (1 << 6);
	}
	else if (ExpectResp == EXPECT_LONG_RESP)	        /* 希望得到长响应 */
	{
		CmdData |= (1 << 6) | (1 << 7);
	}

	if (AllowTimeout)			                        /* 是否允许超时中断 */
		CmdData |= (1 << 8);
	else
		CmdData &= ~(1 << 8);

	CmdData |= (1 << 10);		                        /* 使能发送命令 */
	MCIArgument = Argument;	                            /* 命令参数     */
	MCICommand = CmdData;                               /* 启动命令发送 */
}


/*******************************************************************************************************************
** 函数名称: MCI_GetCmdResp()				
**
** 功能描述: 从卡获取响应, 该函数与MCI_SendCmd()成对使用
**
** 输   入: INT32U ExpectCmdData: SD/MMC 命令码
**           INT32U ExpectResp   : 希望的响应, 取值为: EXPECT_NO_RESP, EXPECT_SHORT_RESP, EXPECT_LONG_RESP
**           INT8U  resplen      : 响应长度
**           
**	         
** 输   出: INT32U *CmdResp     : 响应内容, 长度为resplen
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U MCI_GetCmdResp(INT32U ExpectCmdData, INT32U ExpectResp, INT8U resplen, INT32U *CmdResp)
{
	INT32U LastCmdIndex;
	INT32U CmdRespStatus = 0;

	while (1)
	{                                                       /* 不断循环等待卡的响应 */
		CmdRespStatus = MCIStatus;
		if (CmdRespStatus & (MCI_CMD_TIMEOUT))
		{                                                   /* 超时错误, 超时周期固定为64个MCICLK时钟周期 */
		    MCIClear = CmdRespStatus | MCI_CMD_TIMEOUT;
			MCICommand = 0;                                 /* 清空命令寄存器及参数寄存器 */
			MCIArgument = 0xFFFFFFFF;
			return SD_ERR_CMD_TIMEOUT;                      /* 返回响应命令超时错误 */
		}
		
		if (CmdRespStatus & MCI_CMD_CRC_FAIL)
		{                                                   /* CRC校验失败错误 */
			MCIClear = CmdRespStatus | MCI_CMD_CRC_FAIL;
			LastCmdIndex = MCICommand & 0x003F;
			if ((LastCmdIndex == SEND_OP_COND) || (LastCmdIndex == SEND_APP_OP_COND) 
					|| (LastCmdIndex == STOP_TRANSMISSION))
			{                                               /* 忽略命令 SEND_OP_COND和STOP_TRANSMISSION的CRC校验 */
				MCICommand = 0;
				MCIArgument = 0xFFFFFFFF;	 
				break;
			}
			else
				return SD_ERR_CMD_RESPCRC;                  /* 返回响应命令CRC校验失败错误 */
		}
		else if (CmdRespStatus & MCI_CMD_RESP_END)
		{
			MCIClear = CmdRespStatus | MCI_CMD_RESP_END;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -