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

📄 sdhal.c

📁 SmartARM2400系列开发板全套资料
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************Copyright (c)**************************************************
**                               Guangzhou ZLG-MCU Development Co.,LTD.
**                                      graduate school
**                                 http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name:			sdhal.c
** Last modified Date:	2007-5-20
** Last Version:		V2.0
** Descriptions:		SD/MMC卡读写模块: 硬件抽象层 ---- SD总线硬件相关的操作函数
**
**
**------------------------------------------------------------------------------------------------------
** Created by:			Ming Yuan Zheng
** Created date:		2005-1-6
** Version:				V1.0
** Descriptions:		The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:			
** Modified date:		
** Version:				
** Descriptions:		
**
**------------------------------------------------------------------------------------------------------
** Modified by: 
** Modified date:
** Version:	
** Descriptions: 
**
********************************************************************************************************/

#include "sdconfig.h"


#if SDBUS_MODE_EN

#if LPC24xx_MCI_DMA_EN
INT32U *src_addr; 
INT32U *dest_addr;
#endif
 

/* mci_struct 结构体成员 RxTxFlag 取值 */
#define  MCI_RESET_FLAG             0xFF
#define  MCI_CUR_REC                0x01
#define  MCI_CUR_SEND               0x02

/* MCI数据传输结构体 */
typedef struct MCI_STRUCT
{
    INT8U CurTran;              // 当前数据传输类型, 可为MCI_CUR_REC或MCI_CUR_SEND
    INT8U RxTxFlag;             // 数据接收/发送标志, 用于标识接收/发送执行结果

    INT8U *pRecBuf;             // 接收数据缓冲区指针
    INT8U *pSendBuf;            // 发送数据缓冲区指针
    INT32U RecCnt;              // 接收数据计数器
    INT32U SendCnt;             // 发送数据计数器
    
    sd_struct *psds;            // 当前sd_struct结构体指针
}mci_struct;

volatile mci_struct lpc_mci;    // mci_struct结构体变量



void SD_PowerOff(void);
void MCI_Delay(INT16U val);
void MCI_SendCmd(INT32U CmdIndex, INT32U Argument, INT32U ExpectResp, INT32U AllowTimeout );
INT8U MCI_GetCmdResp(INT32U ExpectCmdData, INT32U ExpectResp, INT8U resplen, INT32U *CmdResp);

	/**********************************************
		
		硬件抽象层接口函数实现文件
	
	***********************************************/

/*******************************************************************************************************************
** 函数名称: SdHal_Initialize()				
**
** 功能描述: 初始化访问卡的硬件条件		
**
** 输   入: sd_struct *sds:  卡信息结构体
**							  	
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 主要工作: 1. 先给卡下电, 再给卡上电;     2. 设置访问卡的速度小于或等于 400KHz;
**
**           3. 使 CMD 线处于开漏状态;      4. 初始化相关硬件寄存器为适当的状态
********************************************************************************************************************/
INT8U SdHal_Initialize(sd_struct *sds)
{
    // 卡下电并延时
    SD_PowerOff(); 
	MCI_Delay(1);				            

	// 卡上电并初始化MCI相关引脚
	SD_POWER_ON();
    PCONP |= (1 << 28);					    /* 使能MCI控制器工作时钟 */	

    MCI_CLK_PIN();                          /* 配置MCI接口各功能引脚 */    
	MCI_CMD_PIN();
	MCI_DAT0_PIN();              
	MCI_DAT1_PIN();              
	MCI_DAT2_PIN();              
	MCI_DAT3_PIN();
	
	SD_INSERT_GPIO();                       /* 配置卡插入检测引脚 */
	SD_INSERT_IN();  
	               
	SD_WP_GPIO();                           /* 配置卡写保护检测引脚 */   
	SD_WP_IN();      
	           
    MCIPower = 0x02;
	MCI_Delay(1);                           /* 延时 */ 
    MCIPower |= 0x01;
    MCIPower |= (1 << 6 );	                /* CMD线处于开漏状态 */
  	
	// 设置访问卡时钟小于 400KHz
	SdHal_SetMCIClock(sds, SD_RATE_SLOW); 

	// 清空 MCI 相关寄存器		
    MCICommand = 0;						    
	MCIClear = 0x7FF;						/* 清空MCI状态寄存器 */
	MCIDataCtrl = 0;						
    MCIMask0 = 0;							/* 屏蔽所有 MCI 中断 */
	
#if LPC24xx_MCI_DMA_EN
	PCONP |= (1 << 29);   	                /* 使能 GPDMA 时钟 */
#endif

	return SD_NO_ERR;
}												


/*******************************************************************************************************************
** 函数名称: SD_PowerOff()				
**
** 功能描述: 给卡下电, 将	
**
** 输   入: 无
**							  	
** 输   出: 无
**
** 返 回 值: 无
********************************************************************************************************************/
void SD_PowerOff(void)
{
	SD_POWER_GPIO();
	SD_POWER_OUT();
	SD_POWER_OFF();							/* 关闭 SD 卡电源  turn off power of sd card */
	
    MCI_CLK_GPIO();                         /* 配置MCI接口各功能引脚 */    
	MCI_CMD_GPIO();
	MCI_DAT0_GPIO();              
	MCI_DAT1_GPIO();              
	MCI_DAT2_GPIO();              
	MCI_DAT3_GPIO();
		
    MCI_CLK_OUT();                          /* 配置MCI接口各功能引脚 */    
	MCI_CMD_OUT();
	MCI_DAT0_OUT();              
	MCI_DAT1_OUT();              
	MCI_DAT2_OUT();              
	MCI_DAT3_OUT();	
	
    MCI_CLK_CLR();                          /* 配置MCI接口各功能引脚 */    
	MCI_CMD_CLR();
	MCI_DAT0_CLR();              
	MCI_DAT1_CLR();              
	MCI_DAT2_CLR();              
	MCI_DAT3_CLR();	
	
	PCONP &= ~(1 << 28);					/* 关闭工作时钟 */	
	MCIPower = 0x00;                        /* 配置电源控制寄存器 */
    MCIClock = 0;
    //MCIClock &= ~(1 << 8);                  /* 关闭MCICLK时钟 */	
}


/*******************************************************************************************************************
** 函数名称: SdHal_OpenDrainCmd()				
**
** 功能描述: 设置 CMD 信号线的开漏状态 	
**
** 输   入: sd_struct *sds  : 卡信息结构体
**           INT8U bOpenDrain: > 0: CMD 信号线开漏;  = 0: CMD 信号线处于非开漏 
**          							  	
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 主要工作: 1. 初始化相关硬件寄存器;  2. 先给卡下电, 再上电;  3. 设置访问卡的速度小于或等于 400KHz
**
**           4. 使 CMD 线处于开漏状态
********************************************************************************************************************/
void SdHal_OpenDrainCmd(sd_struct *sds, INT8U bOpenDrain)
{
    if (bOpenDrain)
        MCIPower |= (1 << 6 );	            /* CMD线处于开漏状态 */      
    else
        MCIPower &= ~(1 << 6 );	            /* CMD线处于非开漏状态 */      
}


/*******************************************************************************************************************
** 函数名称: SdHal_SendCmd()				
**
** 功能描述: 发送一个SD/MMC命令, 并获得响应			
**
** 输   入: sd_struct *sds:  卡信息结构体, 仅使用sds->card_posnum成员用于区分卡座
			 INT8U cmd:       命令索引(命令的[5:0]位)
**		     INT32U argument: 命令参数
**			 INT8U resptype:  响应类型, 取值可以为R0(即不需要响应), R1, R1B, R2, R3, R6 
**			 INT8U resplen:   响应长度, 
**                            当响应为R0时, 取值为0(对应resp指针也可为空).
**                            当响应为R1,R1B,R3,R6时, 取值4; 
**                            当响应为R2时, 取值为16(R2的bit[127:0]).
**							  	
** 输   出: INT32U *resp:    响应内容, bit127在resp[0]的bit32
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_SendCmd(sd_struct *sds, INT8U cmd, INT32U argument, INT8U resptype, INT32U *resp, INT8U resplen)
{
    INT32U ExpectResp, i;
    INT32U ret;
    
    if (resptype == R0)
    {
        ExpectResp = EXPECT_NO_RESP;                        /* 卡无须响应本命令 */
    } 
    else if ((resptype == R1) || (resptype == R1B) || (resptype == R3) || (resptype == R6))
    {
        ExpectResp = EXPECT_SHORT_RESP;                     /* 短响应 */
    }  
    else if (resptype == R2)
    {
        ExpectResp = EXPECT_LONG_RESP;                      /* 长响应 */
    } 
    else 
    {
        return SD_ERR_CMD_RESPTYPE;							/* 错误的响应类型 */
    }
                
    MCI_SendCmd(cmd, argument, ExpectResp, 0);				/* 发送命令并获取响应 */
    ret = MCI_GetCmdResp(cmd, ExpectResp, resplen, resp);
    if (ret != SD_NO_ERR)
        return ret;
       
    for (i = 0; i < 0x200; i++);	                        /* 延时, 确保 MCICommand 寄存器在规定时间内不再次被写入 */
  
    return ret;
}


/*******************************************************************************************************************
** 函数名称: SdHal_EnableMCIBusWidth()				
**
** 功能描述: 使能SD/MMC主控器是否使能宽总线		
**
** 输   入: sd_struct *sds: 卡信息结构体, 仅使用sds->card_posnum成员用于区分卡座
**           INT32U bWidth : > 0:  使能宽总线;     0: 禁止宽总线     
**							  	
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
void SdHal_EnableMCIBusWidth(sd_struct *sds, INT32U bWidth)
{
	if (bWidth != 0)
		MCIClock |= (1 << 11);
	else
		MCIClock &= ~(1 << 11);
}


/*******************************************************************************************************************
** 函数名称: SdHal_SetMCIClock()				
**
** 功能描述: 设置读写SD/MMC卡时钟		
**
** 输   入: sd_struct *sds  :  卡信息结构体
**           INT32U ClockRate:	要求的时钟速度.  取值SD_RATE_SLOW   时, 设置访问卡速度小于 400KHz		
**			  	                                 取值SD_RATE_NORMAL 时, 设置访问卡速度为卡的最大速度或主控器的最大速度
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
**
** 注    意: 本函数有责任在ClockRate取不同的值时, 计算出相应的 sds->clkval 值, 必须大于0. 
**
********************************************************************************************************************/
void SdHal_SetMCIClock(sd_struct *sds, INT32U ClockRate)
{
    INT32U i;
    INT32 div = 0;
    
    sds->host_clkval = 400000;
    PCLKSEL1 &= ~(0x03 << 24);                          
    PCLKSEL1 |= 0x01 << 24;                             /* MCICLK = Fcclk */
     
	if (ClockRate == SD_RATE_SLOW)
	{
		div = MCLKDIV_SLOW;	                            /* 设置时钟小于等于400KHz */
		sds->host_clkval = Fcclk / (div + 1) / 2;       /* MCI 总线周期频率 = MCLK / (2 * (div + 1)) */
	}
	else if (ClockRate == SD_RATE_NORMAL) 
	{
	    //div = Fcclk / sds->card_transpeed / 2 - 1;    /* 根据卡数据的最大传输速度计算分频值 */ 	    
	    //if (div < 0)     div = 0;
	    //if (div > 254)   div = 254;   
	    div = MCLKDIV_NORMAL;	
	        		               
		sds->host_clkval = Fcclk / (div + 1) / 2;       /* MCI 总线周期频率 = MCLK / (2 * (div + 1)) */
	}
	
	MCIClock &= ~0xFF;
	MCIClock = (1 << 8) | (1 << 9) | div;
	for (i = 0; i < 0x10; i++);	                        /* 在下次写MCIClock前, 延时 3MCLK + 2PCLK */
}


/*******************************************************************************************************************
** 函数名称: SdHal_CheckCard()				
**
** 功能描述: 检测卡是否完全插入卡座中
**
** 输   入: sd_struct *sds:  卡信息结构体
**	         
** 输   出: 无
**
** 返 回 值: 1: 卡完全插入	   0: 卡没有完全插入
********************************************************************************************************************/
INT8U SdHal_CheckCard(sd_struct *sds)
{
	if (SD_INSERT_STATUS() != 0)
		return 0;								/* 未完全插入 */
	else
		return 1;								/* 完全插入 */
}


/*******************************************************************************************************************
** 函数名称: SdHal_CheckCardWP()				
**
** 功能描述: 检测卡写保护
**
** 输   入: sd_struct *sds:  卡信息结构体
**	         
** 输   出: 无
**
** 返 回 值: 1: 卡已写保护	  0: 卡未写保护
********************************************************************************************************************/
INT8U SdHal_CheckCardWP(sd_struct *sds)
{
	if (SD_WP_STATUS() != 0)
		return 1;								/* 写保护 */
	else
		return 0;								/* 未写保护 */
}



/*******************************************************************************************************************
** 函数名称: SdHal_BeforeReadBlock()				
**
** 功能描述: 在发送读单块命令之前, 给硬件控制器做一些事情的机会
**
** 输   入: sd_struct *sds  :  卡信息结构体 
**	         
** 输   出: 无
**
** 返 回 值: 0:   正确    >0:   错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdHal_BeforeReadBlock(sd_struct *sds)
{	
    MCIMask0 |= (DATA_RX_INT_MASK) | (FIFO_INT_MASK);	    /* 仅使能接收中断 */

	MCIClear = 0x7FF;							            /* 清空清零寄存器的所有标志 */
	MCIDataCtrl = 0;							            /* 数据控制寄存器清0  */
			 
	MCIDataTimer = sds->timeout_read;                       /* 读数据块超时值 */
	MCIDataLength = SD_BLOCKSIZE;				            /* 块长度 */
    MCIFifoCnt = 0;                                         /* 清空接收FIFO计数器*/

⌨️ 快捷键说明

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