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

📄 sdhal.c

📁 SD卡驱动程序。周立功单片机公司开发板提供的标准例程。
💻 C
📖 第 1 页 / 共 3 页
字号:
	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;
			break;	                                        /* 响应已成功接收到,退出循环 */
		}
		else if ((CmdRespStatus & MCI_CMD_SENT) && (ExpectResp == EXPECT_NO_RESP))
		{                                                   /* 该命令无须响应 */
			MCIClear = MCI_CMD_SENT;
			return SD_NO_ERR;                               /* 返回命令*/
		}		
	}
	
	if ((MCIRespCmd & 0x3F) != ExpectCmdData)
	{
	    /* 响应为非R1, 而是R2或R3, 则无须检查响应命令是否与发送的相符合 */
		if ((ExpectCmdData != SEND_OP_COND) && (ExpectCmdData != SEND_APP_OP_COND) 
			 && (ExpectCmdData != ALL_SEND_CID) && (ExpectCmdData != SEND_CSD))
		{
			return SD_ERR_CMD_RESP;                         /* 返回响应错误 */
		}
	}

    /* 下面读取短响应内容及长响应内容 */
	if ((ExpectResp == EXPECT_SHORT_RESP) && (resplen == 1))
	{                                                       
		*CmdResp = MCIResponse0;                            /* 读取短响应内容 */
	}
	else if ((ExpectResp == EXPECT_LONG_RESP) && (resplen == 4))
	{
		*CmdResp = MCIResponse0;                            /* 读取长响应内容 */
		*(CmdResp+1) = MCIResponse1;
		*(CmdResp+2) = MCIResponse2;
		*(CmdResp+3) = MCIResponse3;
	}	
	
	return SD_NO_ERR;	                                    /* 响应正确. */
}



/**********************************

 下面部分为 MCI 中断处理相关函数

***********************************/


/*******************************************************************************************************************
** 函数名称: MCI_DataEndProcess()				
**
** 功能描述: MCI 数据结束处理函数
********************************************************************************************************************/
void MCI_DataEndProcess(void)
{
#if MCI_DMA_ENABLED
    if (lpc_mci.CurTran == MCI_CUR_SEND)
    {
        while ( !(DMACRawIntTCStatus & 0x01) );
	    DMACIntTCClear |= 0x01;
		lpc_mci.RxTxFlag = SD_NO_ERR;                       /* DMA 接收块数据成功 */
    }
    else
    {
        while ( !(DMACRawIntTCStatus & 0x02) );
		DMACIntTCClear |= 0x02;
		lpc_mci.RxTxFlag = SD_NO_ERR;                       /* DMA 发送块数据成功 */
    }
    
    #if SD_UCOSII_EN
	    OSSemPost(lpc_mci.psds->pSemSdmmcRW);               /* 使等待函数就绪 */
    #endif	

#else
   
    MCIClear |= MCI_DATA_BLK_END;
    if ((lpc_mci.SendCnt >= SD_BLOCKSIZE) || 
        (lpc_mci.RecCnt >= SD_BLOCKSIZE))	   
	{                                                       /* 块数据已收/发成功 */
	    lpc_mci.RxTxFlag = SD_NO_ERR;
	    #if SD_UCOSII_EN
	    	OSSemPost(lpc_mci.psds->pSemSdmmcRW);
		#endif
	} 

#endif	    
	MCIDataCtrl = 0;			                            /* 数据控制寄存器清0  */
}


/*******************************************************************************************************************
** 函数名称: MCI_TxActiveProcess()				
**
** 功能描述: MCI 发送数据处理函数
********************************************************************************************************************/
void MCI_TxActiveProcess(void)
{
	INT32U DataWord, blockSize,i;
	
	MCIClear |= MCI_TX_ACTIVE;
    if (lpc_mci.SendCnt < SD_BLOCKSIZE )
	{
	    blockSize = 0;
		if (MCIStatus & MCI_TX_FIFO_EMPTY)                  /* FIFO全空 */   
	        blockSize = FIFO_SIZE * 4;                      
		else if (MCIStatus & MCI_TX_HALF_EMPTY)             /* FIFO半空 */
		   	blockSize = (FIFO_SIZE / 2) * 4; 
		else if (!(MCIStatus & MCI_TX_FIFO_FULL))           /* FIFO全满 */
	     	blockSize = 1 * 4; 
		   
		for (i = 0; i < blockSize; i += 4)
    	{                                                   /* 循环向FIFO中写入数据 */
    		DataWord = ((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt]) + 
    		           (((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt + 1]) << 8) +
    		           (((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt + 2]) << 16) +
    		           (((INT32U)lpc_mci.pSendBuf[lpc_mci.SendCnt + 3]) << 24);
    		MCIFIFO = DataWord;                             /* 向FIFO写入一个32位的数据 */
    		lpc_mci.SendCnt += 4;
    		if (lpc_mci.SendCnt >= (SD_BLOCKSIZE))
     			break;	
    	}     	
    }
}


/*******************************************************************************************************************
** 函数名称: MCI_RxActiveProcess()				
**
** 功能描述: MCI 接收数据处理函数
********************************************************************************************************************/
void MCI_RxActiveProcess(void)
{
	INT32U DataWord, blockSize, i;
	
    if (lpc_mci.RecCnt < SD_BLOCKSIZE )
	{
	    blockSize = 0;
	    if (!(MCIStatus & MCI_RX_FIFO_FULL))                 /* FIFO全满 */          
	   	  	blockSize = FIFO_SIZE * 4; 
	   	else if (MCIStatus & MCI_RX_HALF_FULL)               /* FIFO半满 */
	   		blockSize = (FIFO_SIZE/2) * 4; 
	   	else if (MCIStatus & MCI_RX_FIFO_EMPTY)              /* FIFO全空 */
	   		blockSize = 1 * 4; 
	   	
	   	for ( i = 0; i < blockSize; i += 4 )
	   	{                                                    /* 循环从FIFO中读取数据 */
		    while (!(MCIStatus & MCI_RX_DATA_AVAIL));
		    DataWord = MCIFIFO;                              /* 从FIFO中读取一个32位的数据 */
		    lpc_mci.pRecBuf[lpc_mci.RecCnt] = DataWord & 0xFF;
		    lpc_mci.pRecBuf[lpc_mci.RecCnt + 1] = (DataWord >> 8) & 0xFF; 
		    lpc_mci.pRecBuf[lpc_mci.RecCnt + 2] = (DataWord >> 16) & 0xFF;
		    lpc_mci.pRecBuf[lpc_mci.RecCnt + 3] = (DataWord >> 24) & 0xFF;
		    lpc_mci.RecCnt += 4;                             /* 计数器计数 */
            if (lpc_mci.RecCnt >= (SD_BLOCKSIZE))
     			break;		    
	    }
	}

}


/*******************************************************************************************************************
** 函数名称: MCI_DataInterruptProcess()				
**
** 功能描述: 这部分是处理读写卡的关键部分. 对于FIFO中断没有处理, 本函数主要使用 TX_ACTIVE 和 RX_ACTIVE 处理块读写.
********************************************************************************************************************/
void MCI_DataInterruptProcess( void )
{
	INT32U Status  = MCIStatus;

 	if (Status &  MCI_DATA_END)                              /* 数据结束中断 */
 		MCIClear = Status | MCI_DATA_END;
	
	if (Status & MCI_DATA_BLK_END)                           /* 数据块结束中断 */
	{
	    MCI_DataEndProcess();
	    return;
	}
		
#if !MCI_DMA_ENABLED	
	if (MCIStatus & MCI_TX_ACTIVE)
        MCI_TxActiveProcess();                               /* 发送数据中断处理 */

	if (MCIStatus & MCI_RX_ACTIVE)
        MCI_RxActiveProcess();                               /* 接收数据中断处理 */
#endif        
}


/*******************************************************************************************************************
** 函数名称: MCI_DataErrorProcess()				
**
** 功能描述: MCI 错误处理函数: 当MCI有错误产生时, 该函数被调用
********************************************************************************************************************/
void MCI_DataErrorProcess( void )
{
	INT32U Status = MCIStatus;
	
    if (Status & MCI_DATA_CRC_FAIL)
		lpc_mci.RxTxFlag = SD_ERR_DATA_CRC16;                /* 收/发数据块时发生CRC校验错误 */         

	if (Status & MCI_DATA_TIMEOUT)
	{
        if (lpc_mci.CurTran == MCI_CUR_SEND)
            lpc_mci.RxTxFlag = SD_ERR_TIMEOUT_WRITE;         /* 发送数据超时错误 */
        else    
            lpc_mci.RxTxFlag = SD_ERR_TIMEOUT_READ;          /* 接收数据超时错误 */
    }
    	
	if (Status & MCI_TX_UNDERRUN)                            /* 发送数据时FIFO下溢错误 */
	    lpc_mci.RxTxFlag = SD_ERR_HARDWARE;

	if (Status & MCI_RX_OVERRUN)                             /* 接收数据时FIFO上溢错误 */
	    lpc_mci.RxTxFlag = SD_ERR_HARDWARE;

	if ( Status &  MCI_START_BIT_ERR )                       /* 宽总线模式下所有数据信号线上没有检测到起始位 */
	    lpc_mci.RxTxFlag = SD_ERR_DATA_STARTBIT;
	
#if SD_UCOSII_EN
	OSSemPost(lpc_mci.psds->pSemSdmmcRW);                    /* 使等待函数就绪 */
#endif
}


/*******************************************************************************************************************
** 函数名称: MCI_Exception	或 MCI_Handler		
**
** 功能描述: MCI 中断处理函数
********************************************************************************************************************/
#if SD_UCOSII_EN
void  MCI_Exception(void)
#else
__irq __arm void MCI_Handler(void)
#endif
{	   
    INT32U Status = MCIStatus;                              /* 读取MCI当前状态 */

    if (Status & CMD_INT_MASK)
	{                                                       /* 命令中断处理 */
		MCIClear = Status & CMD_INT_MASK;
	}
	else if (MCIStatus & DATA_ERR_INT_MASK)
	{                                                       /* 数据错误中断处理 */
		MCI_DataErrorProcess();                 
		MCIClear |= DATA_ERR_INT_MASK;                      /* 清除数据错误中断位 */
	}
	else if (MCIStatus & DATA_INT_MASK)
	{                                                       /* 数据中断处理 */
		MCI_DataInterruptProcess();
		//MCIClear |= DATA_INT_MASK;
	}
    else if (MCIStatus & FIFO_INT_MASK)
	{
		;
	}
	
	VICVectAddr = 0;		                                /* 应答中断控制器 */
}







⌨️ 快捷键说明

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