花了几天写了SD卡裸机驱动,现在还不完善,只支持4G以内的卡,以后再加上;现在经过修改可以写入数据了,亲测没问题.
S3C6410_SDIO.C
#include "s3c6410_system.h"
#include "s3c6410_sdio.h"
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//配置
//块大小寄存器(0通道)BLKSIZE0
#define BLKSIZE0_BLKSIZE 0x0200 //块大小为512字节
//传输模式寄存器(0通道)TRNMOD0
#define TRNMOD0_CCSCON 0 //正常模式
#define TRNMOD0_MUL1SIN0 (0 <
#define TRNMOD0_RD1WT0 (1 <
#define TRNMOD0_ENACMD12 (0 <
#define TRNMOD0_ENBLKCNT (0 <
#define TRNMOD0_ENDMA (0 <
//主机控制寄存器(0通道)HOSTCTL0
#define HOSTCTL0_WIDE8 (0 <
#define HOSTCTL0_DMASEL (0 <
#define HOSTCTL0_OUTEDGEINV (0 <
#define HOSTCTL0_WIDE4 (0 <
//电源控制寄存器(0通道)PWRCON0
#define PWRCON0_SELPWRLVL (7 <
#define PWRCON0_PWRON (1 <
//容限寄存器(0 通道)CAPAREG0
#define CAPAREG0_V18 (1 <
#define CAPAREG0_V30 (0 <
#define CAPAREG0_V33 (1 <
#define CAPAREG0_SUSRES (1 <
#define CAPAREG0_DMA (1 <
#define CAPAREG0_HSPD (1 <
#define CAPAREG0_ADMA2 (0 <
#define CAPAREG0_MAXBLKLEN (0 <
#define CAPAREG0_BASECLK (25 <
#define CAPAREG0_TOUTUNIT (0 <
#define CAPAREG0_TOUTCLK (10 <
//最大电流容限寄存器(0 通道)MAXCURR0
#define MAXCURR0_MAXCURR18 (10 <
#define MAXCURR0_MAXCURR30 (10 <
#define MAXCURR0_MAXCURR33 (10 <
//控制寄存器2 CONTROL2_0
#define CONTROL2_0_ENSTAASYNCCLR (0 <
#define CONTROL2_0_ENCMDCNFMSK (0 <
#define CONTROL2_0_CDINVRXD3 (0 <
#define CONTROL2_0_SELCARDOUT (0 <
#define CONTROL2_0_FLTCLKSEL (8 <
#define CONTROL2_0_ENFBCLKTX (0 <
#define CONTROL2_0_ENFBCLKRX (0 <
#define CONTROL2_0_SDCDSEL (0 <
#define CONTROL2_0_SDSIGPC (0 <
#define CONTROL2_0_ENBUSYCHKTXSTART (0 <
#define CONTROL2_0_DFCNT (0 <
#define CONTROL2_0_ENCLKOUTHOLD (1 <
#define CONTROL2_0_RWAITMODE (0 <
#define CONTROL2_0_DISBUFRD (0 <
//HCLK = 128MHZ EPLL = 24MHZ
#define CONTROL2_0_SELBASECLK (2 <
#define CONTROL2_0_PWRSYNC (0 <
#define CONTROL2_0_ENCLKOUTMSKCON (0 <
#define CONTROL2_0_HWINITFIN (1 <
//时钟控制寄存器(0 通道)CLKCON0
#define CLKCON0_SELFREQ (0x80 <
#define CLKCON0_ENSDCLK (1 <
#define CLKCON0_ENINTCLK (1 <
//超时控制寄存器(0 通道)TIMEOUTCON0
/*******************************************************************************
* Function Name : SDIO_DeInit
* Description : Deinitializes the SDIO peripheral registers to their default
* reset values.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SDIO_DeInit(void)
{
//初始化硬件IO
rGPGCON = 0x2222222; //初始化IO为SDIO模式
rGPGPUD = 0; //禁止上下拉
//时钟控制寄存器配置
SDIO0->CLKCON = CLKCON0_SELFREQ + CLKCON0_ENSDCLK + CLKCON0_ENINTCLK;
//主机控制寄存器配置
SDIO0->HOSTCTL = HOSTCTL0_WIDE8 + HOSTCTL0_DMASEL + HOSTCTL0_OUTEDGEINV + HOSTCTL0_WIDE4;
//容限寄存器配置
SDIO0->CAPAREG = CAPAREG0_V18 + CAPAREG0_V30 + CAPAREG0_V33 + CAPAREG0_SUSRES + CAPAREG0_DMA + CAPAREG0_HSPD + CAPAREG0_ADMA2 +\
CAPAREG0_MAXBLKLEN + CAPAREG0_BASECLK + CAPAREG0_TOUTUNIT + CAPAREG0_TOUTCLK;
//控制寄存器2配置
SDIO0->CONTROL2 = CONTROL2_0_ENSTAASYNCCLR + CONTROL2_0_ENCMDCNFMSK + CONTROL2_0_CDINVRXD3 + CONTROL2_0_SELCARDOUT + CONTROL2_0_FLTCLKSEL + \
CONTROL2_0_ENFBCLKTX + CONTROL2_0_ENFBCLKRX + CONTROL2_0_SDCDSEL + CONTROL2_0_SDSIGPC + CONTROL2_0_ENBUSYCHKTXSTART + \
CONTROL2_0_DFCNT + CONTROL2_0_ENCLKOUTHOLD + CONTROL2_0_RWAITMODE + CONTROL2_0_DISBUFRD + CONTROL2_0_SELBASECLK + \
CONTROL2_0_PWRSYNC + CONTROL2_0_ENCLKOUTMSKCON + CONTROL2_0_HWINITFIN;
//传输模式寄存器配置
SDIO0->TRNMOD = TRNMOD0_CCSCON + TRNMOD0_MUL1SIN0 + TRNMOD0_RD1WT0 + TRNMOD0_ENACMD12 + TRNMOD0_ENBLKCNT + TRNMOD0_ENDMA;
//超时控制寄存器(0 通道)
SDIO0->TIMEOUTCON = 0x0e; //超时设置最大
//电源控制寄存器配置
SDIO0->PWRCON = PWRCON0_SELPWRLVL + PWRCON0_PWRON;
//块间隔寄存器
SDIO0->BLKGAP = 0;
//开启卡插入+卡移除+传输完成+指令完成中断状态+数据超时错误+命令索引错误+指令最后位错误+指令超时错误+指令CRC + 缓冲区读就绪 + 写缓冲区就绪
SDIO_FlagConfig(SDIO_FLAG_CARDREMOVAL | SDIO_FLAG_CARDINSERTION | SDIO_FLAG_TRANSFER | SDIO_FLAG_COMMANDEND | SDIO_FLAG_DATACRC |
SDIO_FLAG_DATATIMEOUT | SDIO_FLAG_COMMANDINDEX | SDIO_FLAG_COMMANDCRC | SDIO_FLAG_COMMANDTIMEOUT | SDIO_FLAG_BUFFREAD | SDIO_FLAG_BUFFWRITE,Enable);
//使能卡插入拔出中断
SDIO_FlagITConfig(SDIO_FLAG_CARDREMOVAL | SDIO_FLAG_CARDINSERTION,Enable);
SDIO_ClearFlag(SDIO_FLAG_ALL); //清除所有中断标志
}
void SDIO_FlagITConfig(u32 SDIO_FLAG, u8 EN)
{
if(EN) //中断使能
SDIO0->INTSEGEN |= SDIO_FLAG;
else
SDIO0->INTSEGEN &= ~SDIO_FLAG;
}
void SDIO_FlagConfig(u32 SDIO_FLAG, u8 EN)
{
if(EN) //状态使能
SDIO0->INTSTSEN |= SDIO_FLAG;
else
SDIO0->INTSTSEN &= ~SDIO_FLAG;
}
/*************************************************************************************************************************
*函数 : void SD_SendCommand(vu8 CmdIdx,vu32 CmdArg,vu8 CmdTyp,vu8 Misc)
*功能 : 向SD卡发送一个命令
*参数 : CmdIdx:指令索引;CmdArg:命令参数;CmdMisc:其它杂项设置,详见说明
*返回 : 无
*依赖 : 底层宏定义
*作者 : 陈鹏
*时间 : 20120507
*最后修改时间: 20120507
*说明 : 写SD命令寄存器;
指令索引:这些位设置为SD存储卡物理层规范中指令格式的第40到45位和SDIO卡规范中指定的指令数(CMD0-63, ACMD0-63)。
杂项: SDIO_Type_Default 一般为0
SDIO_Type_Pend 写总线暂停
SDIO_Type_FS 功能选择
SDIO_Type_IT 中断模式
SDIO_CMDIndexEn SDIO指令索引使能
SDIO_CMDCrcEn SDIO指令CRC校验使能
SDIO_Response_No 无应答
SDIO_Response_Short 短应答 48
SDIO_Response_Long 长应答 136
SDIO_Response_ShortBusy 短应答+检测繁忙情况
*************************************************************************************************************************/
void SDIO_SendCommand(vu8 CmdIdx,vu32 CmdArg,vu8 CmdMisc)
{
u16 temreg = 0;
SDIO_ClearFlag(SDIO_FLAG_ALL); //清除所有状态寄存
temreg = CmdIdx;
temreg <<= 8;
temreg |= CmdMisc;
SDIO0->ARGUMENT = CmdArg; //先写入命令参数
SDIO0->CMDREG = temreg; //再写入命令索引以及类型等参数
while(!(SDIO0->PRNSTS & BIT0)); //等待命令线空忙,也就是开始执行命令
while(SDIO0->PRNSTS & BIT0); //等待命令线空闲,也就是命令执行完毕
}
/*************************************************************************************************************************
*函数 : u32 SD_GetResponse(u8 SDIO_RESP)
*功能 : 获取SD卡的应答
*参数 : Rep:应答数据存放的位置
SDIO_RESP1: Response Register 1
* SDIO_RESP2: Response Register 2
* SDIO_RESP3: Response Register 3
* SDIO_RESP4: Response Register 4
*返回 : 返回应答
*依赖 : 底层宏定义
*作者 : 陈鹏
*时间 : 20120507
*最后修改时间: 20120507
*说明 : 存放应答数据的缓冲区为128BIT;4个32bit;
指令应答。下表27-4为每一个应答描述了从SD总线到寄存器的指令映射。在这个表中,在表中 R[]指出在SD总线上传输的应答数据的范围,
REP[]指出应答寄存器中位的范围。128位应答位的顺序: {RSPREG3, RSPREG2, RSPREG1, RSPREG0}
*************************************************************************************************************************/
u32 SDIO_GetResponse(u8 SDIO_RESP)
{
return (SDIO0->RSPREG[SDIO_RESP]);
}
u32 SDIO_ReadData(void)
{
return SDIO0->BDATA; //从缓冲区读数据
}
void SDIO_WriteData(u32 Data)
{
SDIO0->BDATA = Data;
}
u8 SDIO_GetFlagStatus(u32 SDIO_FLAG)
{
return ((SDIO_STATUS & SDIO_FLAG) ? 1 : 0);
}
void SDIO_ClearFlag(u32 SDIO_FLAG)
{
SDIO_STATUS |= SDIO_FLAG;
}
/*************************************************************************************************************************
* 函数 : void SDIO_SetFIFOInterruptAddress(u8 FIFOxAdd,u8 WordAdd)
* 功能 : 设置FIFO中断触发位置
* 参数 : FIFOxAdd:FIFO地址选择
WordAdd:触发位置选择,单位为字,共512B,也就是1-128字
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120516
* 说明 : 无
*************************************************************************************************************************/
void SDIO_SetFIFOInterruptAddress(u8 FIFOxAdd,u8 WordAdd)
{
if(WordAdd > 128)
WordAdd = 128;
switch (FIFOxAdd)
{
case FIFO_A0:
{
SDIO0->CONTROL3 &= ~(0x1f);
SDIO0->CONTROL3 |= WordAdd;
}break;
case FIFO_A1:
{
SDIO0->CONTROL3 &= ~(0x1f <
SDIO0->CONTROL3 |= WordAdd <
}break;
case FIFO_A2:
{
SDIO0->CONTROL3 &= ~(0x1f <
SDIO0->CONTROL3 |= WordAdd <
}break;
case FIFO_A3:
{
SDIO0->CONTROL3 &= ~(0x1f <
SDIO0->CONTROL3 |= WordAdd <
}break;
default : break;
}
}
/*************************************************************************************************************************
* 函数 : void SDIO_CLKFrequencySelect(u8 SDCLK)
* 功能 : 设置SDIO时钟分频系数
* 参数 : SDCLK:设置SDIO时钟分频系数
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120516
* 说明 : 高速基础时钟为50MHz
低速基础时钟为25MHz
*************************************************************************************************************************/
void SDIO_CLKFrequencySelect(u8 SDCLK)
{
SDIO_SDClkDisable(); //时钟停止
SDIO0->CAPAREG &= ~(0x3f <
SDIO0->CAPAREG |= (50 <
SDIO0->CLKCON &= ~(0xff <
SDIO0->CLKCON |= (SDCLK <
SDIO_SDClkEnable(); //时钟使能
while(!(SDIO0->CLKCON & BIT0)); //等待时钟稳定
}
/*************************************************************************************************************************
* 函数 : void SDIO_SoftwareReset(u32 SDIO_RST)
* 功能 : 设置SDIO软件复位
* 参数 : SDIO_RST:
SDIO_RSTDAT //复位DAT线
SDIO_RSTCMD //复位CMD线
SDIO_RSTALL //复位所有
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120516
* 说明 : 无
*************************************************************************************************************************/
void SDIO_SoftwareReset(u32 SDIO_RST)
{
SDIO0->SWRST |= SDIO_RST; //复位
while(SDIO0->SWRST & SDIO_RST); //等待复位完成
}
/*************************************************************************************************************************
*函数 : void SDIO_SetTimeOutClock(u8 Unit,u8 Frequency)
*功能 : 超时时钟设置
*参数 : Unit:超时时钟单位选择
TIME_OUT_UNIT_KHZ(0):超时时钟单位为KHZ
TIME_OUT_UNIT_MHZ(1):超时时钟单位为MHZ
Frequency:时钟频率:1~63
*返回 : 返回应答
*依赖 : 底层宏定义
*作者 : 陈鹏
*时间 : 20120521
*最后修改时间: 20120521
*说明 : 配置指令超时时间
*************************************************************************************************************************/
void SDIO_SetTimeOutClock(u8 Unit,u8 Frequency)
{
SDIO0->CAPAREG &= ~(0xff); //清除原先设置
if(Unit) //配置超时时钟单位:MHZ
SDIO0->CAPAREG |= (1 <
if(Frequency > 63) //最大只能设置为63
Frequency = 63;
SDIO0->CAPAREG |= Frequency;
}
s3c6410_sdio.h
#ifndef _S3C6410_SDIO_H_
#define _S3C6410_SDIO_H_
#include "s3c6410_system.h"
#define FIFO_A0 0 //FIFO中断地址0
#define FIFO_A1 1 //FIFO中断地址1
#define FIFO_A2 2 //FIFO中断地址2
#define FIFO_A3 3 //FIFO中断地址3
//SDIO总线宽度设置
#define SDIO_BusWide_1b ((u8)0)
#define SDIO_BusWide_4b ((u8)1)
#define SDIO_BusWide_8b ((u8)2)
//SDIO 命令杂项设置
//SDIO响应类型
#define SDIO_Response_No ((u8)0) //无应答
#define SDIO_Response_Long ((u8)1) //长应答 136
#define SDIO_Response_Short ((u8)2) //短应答 48
#define SDIO_Response_ShortBusy ((u8)3) //短应答+检测繁忙情况
//其它设置
#define SDIO_CMDIndexEn ((u8)1 <
#define SDIO_CMDCrcEn ((u8)1 <
#define SDIO_DataSelect ((u8)1 <
//SDIO指令类型CmdTyp
#define SDIO_Type_Default ((u8)0 <
#define SDIO_Type_Pend ((u8)1 <
#define SDIO_Type_FS ((u8)2 <
#define SDIO_Type_IT ((u8)3 <
//SDIO响应寄存器选择
#define SDIO_RESP1 ((u8)0)
#define SDIO_RESP2 ((u8)1)
#define SDIO_RESP3 ((u8)2)
#define SDIO_RESP4 ((u8)3)
/* SDIO Data Block Size ------------------------------------------------------*/
#define SDIO_DataBlockSize_1b ((u16)1)
#define SDIO_DataBlockSize_2b ((u16)2)
#define SDIO_DataBlockSize_4b ((u16)3)
#define SDIO_DataBlockSize_8b ((u16)4)
#define SDIO_DataBlockSize_16b ((u16)16)
#define SDIO_DataBlockSize_32b ((u16)32)
#define SDIO_DataBlockSize_64b ((u16)64)
#define SDIO_DataBlockSize_128b ((u16)128)
#define SDIO_DataBlockSize_256b ((u16)256)
#define SDIO_DataBlockSize_512b ((u16)512)
#define SDIO_DataBlockSize_1024b ((u16)1024)
#define SDIO_DataBlockSize_2048b ((u16)2048)
#define SDIO_DataBlockSize_4096b ((u16)4096)
#define SDIO_DataBlockSize_8192b ((u16)8192)
#define SDIO_DataBlockSize_16384b ((u16)16384)
/* SDIO Flags ----------------------------------------------------------------*/
//SDIO中断状态
#define SDIO_STATUS (SDIO0->INTSTS)
#define SDIO_FLAG_FIFOADDERR3 ((u32)1 <
#define SDIO_FLAG_FIFOADDERR2 ((u32)1 <
#define SDIO_FLAG_FIFOADDERR1 ((u32)1 <
#define SDIO_FLAG_FIFOADDERR0 ((u32)1 <
#define SDIO_FLAG_READWAIT ((u32)1 <
#define SDIO_FLAG_CCS ((u32)1 <
#define SDIO_FLAG_CARD ((u32)1 <
#define SDIO_FLAG_CARDREMOVAL ((u32)1 <
#define SDIO_FLAG_CARDINSERTION ((u32)1 <
#define SDIO_FLAG_BUFFREAD ((u32)1 <
#define SDIO_FLAG_BUFFWRITE ((u32)1 <
#define SDIO_FLAG_DMA ((u32)1 <
#define SDIO_FLAG_BLOCKGAP ((u32)1 <
#define SDIO_FLAG_TRANSFER ((u32)1 <
#define SDIO_FLAG_COMMANDEND ((u32)1 <
#define SDIO_FLAG_ADMA ((u32)1 <
#define SDIO_FLAG_AUTOCMD12 ((u32)1 <
#define SDIO_FLAG_DATAENDBIT ((u32)1 <
#define SDIO_FLAG_DATACRC ((u32)1 <
#define SDIO_FLAG_DATATIMEOUT ((u32)1 <
#define SDIO_FLAG_COMMANDINDEX ((u32)1 <
#define SDIO_FLAG_COMMANDENDBIT ((u32)1 <
#define SDIO_FLAG_COMMANDCRC ((u32)1 <
#define SDIO_FLAG_COMMANDTIMEOUT ((u32)1 <
#define SDIO_FLAG_ALL ((u32)0xffffffff) //所有标志
void SDIO_DeInit(void);
void SDIO_ClockCmd(u8 EN);
void SDIO_SetPowerState(u32 SDIO_PowerState);
void SDIO_FlagITConfig(u32 SDIO_FLAG, u8 EN);
void SDIO_FlagConfig(u32 SDIO_FLAG, u8 EN);
void SDIO_SendCommand(vu8 CmdIdx,vu32 CmdArg,vu8 CmdMisc);
u32 SDIO_GetResponse(u8 SDIO_RESP);
u32 SDIO_ReadData(void);
void SDIO_WriteData(u32 Data);
u8 SDIO_GetFlagStatus(u32 SDIO_FLAG);
void SDIO_ClearFlag(u32 SDIO_FLAG);
void SDIO_SetFIFOInterruptAddress(u8 FIFOxAdd,u8 WordAdd);
void SDIO_SetTimeOutClock(u8 Unit,u8 Frequency);
void SDIO_CLKFrequencySelect(u8 SDCLK);
void SDIO_SoftwareReset(u32 SDIO_RST);//软件复位
//设置需要传输的块数量
#define SDIO_SetTransferBlockCnt(x) (SDIO0->BLKCNT = x)
//获取剩余传输的块的数量
#define SDIO_GetTransferBlockCnt() (SDIO0->BLKCNT)
//设置单次传输的块的大小
#define SDIO_SetTransferBlockSize(x) (SDIO0->BLKSIZE = (x & 0xfff))
//设置为单块传输模式
#define SDIO_SingleBlockMode() (SDIO0->TRNMOD &= ~(BIT5))
//设置为多区段传输模式
#define SDIO_MultipleBlockMode() (SDIO0->TRNMOD |= BIT5)
//自动CMD12命令启动
#define SDIO_AutoCMD12Enable() (SDIO0->TRNMOD |= BIT2)
//自动CMD12命令禁止
#define SDIO_AuotCMD12Disable() (SDIO0->TRNMOD &= ~(BIT2))
//设置SDIO为写数据模式
#define SDIO_WriteMode() (SDIO0->TRNMOD &= ~(BIT4))
//设置SDIO为读数据模式
#define SDIO_ReadMode() (SDIO0->TRNMOD |= BIT4)
//块计数器启动
#define SDIO_BlockCountEnable() (SDIO0->TRNMOD |= BIT1)
//禁止块计数器启动
#define SDIO_BlockCountDisable() (SDIO0->TRNMOD &= ~(BIT1))
//DMA启动
#define SDIO_DMAEnable() (SDIO0->TRNMOD |= BIT0)
//DMA禁止
#define SDIO_DMADisable() (SDIO0->TRNMOD &= ~(BIT0))
//数据线忙
#define SDIO_DATLineActive() (SDIO0->PRNSTS & BIT2)
//指令禁止
#define SDIO_CommandInhibit() (SDIO0->PRNSTS & BIT0)
//高速时钟模式使能
#define SDIO_HighSpeedEnable() (SDIO0->CAPAREG |= BIT21)
//取消高速时钟模式
#define SDIO_HighSpeedDisable() (SDIO0->CAPAREG &= ~BIT21)
//数据线宽度设置为4bit
#define SDIO_SetDataDataWidth_4b() (SDIO0->HOSTCTL |= BIT1)
//数据线宽设置为1bit
#define SDIO_SetDataDataWidth_1b() (SDIO0->HOSTCTL &= ~BIT1)
//总线电压选择3.3V
#define SDIO_SetBusVoltage_3_3V() (SDIO0->PWRCON &= ~(0x7
//总线电源开启
#define SDIO_BusPowerON() (SDIO0->PWRCON |= BIT0)
//总线电压关闭
#define SDIO_BusPowerOFF() (SDIO0->PWRCON &= ~BIT0)
//唤醒发生在SD卡插入
#define SDIO_WakeupOnSDInsertion() (SDIO0->WAKCON |= BIT1
//使能SD时钟
#define SDIO_SDClkEnable() (SDIO0->CLKCON |= BIT2)
//SD时钟停止
#define SDIO_SDClkDisable() (SDIO0->CLKCON &= ~BIT2)
//超时时钟单位设置
#define TIME_OUT_UNIT_KHZ 0 //超时时钟单位为KHZ
#define TIME_OUT_UNIT_MHZ 1 //超时时钟单位为MHZ
//时钟分频系数
#define SDCLK_1_256 ((u8)0x80) //基础时钟256分频
#define SDCLK_1_128 ((u8)0x40) //基础时钟128分频
#define SDCLK_1_64 ((u8)0x20) //基础时钟64分频
#define SDCLK_1_32 ((u8)0x10) //基础时钟32分频
#define SDCLK_1_16 ((u8)0x08) //基础时钟16分频
#define SDCLK_1_8 ((u8)0x04) //基础时钟8分频
#define SDCLK_1_4 ((u8)0x02) //基础时钟4分频
#define SDCLK_1_2 ((u8)0x01) //基础时钟2分频
#define SDCLK_1_1 ((u8)0x00) //基础时钟1分频
//软件复位选择
#define SDIO_RSTDAT BIT2 //复位DAT线
#define SDIO_RSTCMD BIT1 //复位CMD线
#define SDIO_RSTALL BIT0 //复位所有
#endif
sdcard_sdio.c,
/*******************************************************************************
//功能:SDCARD 驱动,SDIO 模式
//作者:陈鹏
//创建时间:2012-05-16 10:32
//修改时间:2012-05-16 10:32
//修订说明:
//声明:源程序借鉴了意法STM32F103X库函数
********************************************************************************/
#include "sdcard_sdio.h"
#include "s3c6410_sdio.h"
#include "s3c6410_system.h"
u8 SDMMC0_MOV_Flag = 0; //sdmmc0卡移除信号有
/*
1.3 寄存器
名称 宽度 描述
CID 128 卡标识号
RCA 16 相对卡地址(Relative card address):本地系统中卡的地
址,动态变化,在主机初始化的时候确定
*SPI 模式中没有
CSD 128 卡描述数据:卡操作条件相关的信息数据
SCR 64 SD 配置寄存器:SD 卡特定信息数据
OCR 32 操作条件寄存器*/
//容量 = BLOCKNR * BLOCK_LEN = (C_SIZE+1)*2^(C_SIZE_MULT+2)*2^(READ_BL_LEN)
#define SD_BlockSize 512 //SD卡块大小
#define SDIO_CMD0TIMEOUT 1000000 //超时计数器大小
#define SDIO_READTIMEOUT 1000000 //读等待超时
#define SDIO_WRITETIMEOUT 2000000 //写等待超时
// SD卡指令表
#define CMD0 0 //卡复位
#define CMD1 1
#define CMD9 9 //命令9 ,读CSD数据
#define CMD10 10 //命令10,读CID数据
#define CMD12 12 //命令12,停止数据传输
#define CMD16 16 //命令16,设置SectorSize 应返回0x00
#define CMD17 17 //命令17,读sector
#define CMD18 18 //命令18,读Multi sector
#define ACMD23 23 //命令23,设置多sector写入前预先擦除N个block
#define CMD24 24 //命令24,写sector
#define CMD25 25 //命令25,写Multi sector
#define ACMD41 41 //命令41,应返回0x00
#define CMD55 55 //命令55,应返回0x01
#define CMD58 58 //命令58,读OCR信息
#define CMD59 59 //命令59,使能/禁止CRC,应返回0x0
/* Mask for errors Card Status R1 (OCR Register) */
#define SD_OCR_ADDR_OUT_OF_RANGE ((u32)0x80000000)
#define SD_OCR_ADDR_MISALIGNED ((u32)0x40000000)
#define SD_OCR_BLOCK_LEN_ERR ((u32)0x20000000)
#define SD_OCR_ERASE_SEQ_ERR ((u32)0x10000000)
#define SD_OCR_BAD_ERASE_PARAM ((u32)0x08000000)
#define SD_OCR_WRITE_PROT_VIOLATION ((u32)0x04000000)
#define SD_OCR_LOCK_UNLOCK_FAILED ((u32)0x01000000)
#define SD_OCR_COM_CRC_FAILED ((u32)0x00800000)
#define SD_OCR_ILLEGAL_CMD ((u32)0x00400000)
#define SD_OCR_CARD_ECC_FAILED ((u32)0x00200000)
#define SD_OCR_CC_ERROR ((u32)0x00100000)
#define SD_OCR_GENERAL_UNKNOWN_ERROR ((u32)0x00080000)
#define SD_OCR_STREAM_READ_UNDERRUN ((u32)0x00040000)
#define SD_OCR_STREAM_WRITE_OVERRUN ((u32)0x00020000)
#define SD_OCR_CID_CSD_OVERWRIETE ((u32)0x00010000)
#define SD_OCR_WP_ERASE_SKIP ((u32)0x00008000)
#define SD_OCR_CARD_ECC_DISABLED ((u32)0x00004000)
#define SD_OCR_ERASE_RESET ((u32)0x00002000)
#define SD_OCR_AKE_SEQ_ERROR ((u32)0x00000008)
#define SD_OCR_ERRORBITS ((u32)0xFDFFE008)
/* Masks for R6 Response */
#define SD_R6_GENERAL_UNKNOWN_ERROR ((u32)0x00002000)
#define SD_R6_ILLEGAL_CMD ((u32)0x00004000)
#define SD_R6_COM_CRC_FAILED ((u32)0x00008000)
#define SD_VOLTAGE_WINDOW_SD ((u32)0x80100000)
#define SD_HIGH_CAPACITY ((u32)0x40000000)
#define SD_STD_CAPACITY ((u32)0x00000000)
#define SD_CHECK_PATTERN ((u32)0x000001AA)
#define SD_MAX_VOLT_TRIAL ((u32)0x0000FFFF)
#define SD_ALLZERO ((u32)0x00000000)
#define SD_WIDE_BUS_SUPPORT ((u32)0x00040000)
#define SD_SINGLE_BUS_SUPPORT ((u32)0x00010000)
#define SD_CARD_LOCKED ((u32)0x02000000)
#define SD_CARD_PROGRAMMING ((u32)0x00000007)
#define SD_CARD_RECEIVING ((u32)0x00000006)
#define SD_DATATIMEOUT ((u32)0x000FFFFF)
#define SD_0TO7BITS ((u32)0x000000FF)
#define SD_8TO15BITS ((u32)0x0000FF00)
#define SD_16TO23BITS ((u32)0x00FF0000)
#define SD_24TO31BITS ((u32)0xFF000000)
#define SD_MAX_DATA_LENGTH ((u32)0x01FFFFFF)
#define SD_HALFFIFO ((u32)0x00000008)
#define SD_HALFFIFOBYTES ((u32)0x00000020)
/* Command Class Supported */
#define SD_CCCC_LOCK_UNLOCK ((u32)0x00000080)
#define SD_CCCC_WRITE_PROT ((u32)0x00000040)
#define SD_CCCC_ERASE ((u32)0x00000020)
/* Following commands are SD Card Specific commands.
SDIO_APP_CMD should be sent before sending these commands. */
#define SDIO_SEND_IF_COND ((u32)0x00000008)
//#define SDIO_MULTIMEDIA_CARD ((u32)0x0)
#define SDIO_SECURE_DIGITAL_CARD ((u32)0x1)
//#define SDIO_SECURE_DIGITAL_IO_CARD ((u32)0x2)
//#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((u32)0x3)
//#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((u32)0x4)
//#define SDIO_HIGH_CAPACITY_SD_CARD ((u32)0x5)
//#define SDIO_HIGH_CAPACITY_MMC_CARD ((u32)0x6)
#define SDIO_INIT_CLK_DIV ((u8)0xB2)
#define SDIO_TRANSFER_CLK_DIV ((u8)0x01) //时钟分频
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static u32 CardType = SDIO_SECURE_DIGITAL_CARD;
static u32 CSD_Tab[4], CID_Tab[4], RCA = 0;
//static u32 DeviceMode = SD_POLLING_MODE;
//static u32 TotalNumberOfBytes = 0, StopCondition = 0;
u32 *SrcBuffer, *DestBuffer;
volatile SD_Error TransferError = SD_OK;
vu32 TransferEnd = 0;
vu32 NumberOfBytes = 0;
//SD卡中断服务程序,用来检测卡的插入与移除的
static void __irq Isr_SDMMC_Card(void);
/* Private function prototypes -----------------------------------------------*/
static SD_Error CmdError(void);
static SD_Error CmdResp1Error(void);
static SD_Error CmdResp7Error(void);
static SD_Error CmdResp3Error(void);
static SD_Error CmdResp2Error(void);
static SD_Error CmdResp6Error(u16 *prca);
static SD_Error SDEnWideBus(u8 EN);
static SD_Error IsCardProgramming(u8 *pstatus);
static SD_Error FindSCR(u16 rca, u32 *pscr);
#define DebugPrintf printf
/*************************************************************************************************************************
* 函数 : SD_Error SD_Init(void)
* 功能 : SD卡初始化
* 参数 : 无
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120524
* 说明 : 初始化SD卡
*************************************************************************************************************************/
SD_Error SD_Init(void)
{
SD_Error errorstatus = SD_OK;
SDIO_SoftwareReset(SDIO_RSTALL); //软件复位所有寄存器
SDIO_DeInit(); //初始化SDIO硬件
SDIO_FlagITConfig(SDIO_FLAG_CARDREMOVAL | SDIO_FLAG_CARDINSERTION,Enable);//使能卡插入拔出中断
Set_IsrAddr(INT_HSMMC0,(vu32)Isr_SDMMC_Card); //设置中断矢量入口
Set_IntEnable(INT_HSMMC0,Enable); //开启SDMMC0中断
errorstatus = SD_SetIdleSta(); //SD卡上电
if (errorstatus != SD_OK) //卡上电发送错误
{
DebugPrintf("SD power up error:(%d)!\n",errorstatus); //调试,打印错误
return(errorstatus); //返回错误
}
errorstatus = SD_InitializeCards();
if (errorstatus != SD_OK)
{
DebugPrintf("SD initialize error(%d)!\n",errorstatus); //调试,打印错误
return(errorstatus);
}
return(errorstatus);
}
/*************************************************************************************************************************
* 函数 : SD_Error SD_SetIdleSta(void)
* 功能 : SD卡上电进入空闲模式,并识别卡
* 参数 : 无
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120516
* 说明 : SD卡上电进入空闲模式
*************************************************************************************************************************/
SD_Error SD_SetIdleSta(void)
{
SD_Error errorstatus = SD_OK;
u32 response = 0, count = 0;
bool validvoltage = FALSE;
u32 SDType = SD_STD_CAPACITY;
u16 i;
SDIO_CLKFrequencySelect(SDCLK_1_64); //设置时钟400KHZ
SDIO_SetTimeOutClock(TIME_OUT_UNIT_KHZ,1); //设置超时时钟频率最低
//发送至少74个时钟,等待SD卡上电成功并同步
for(response = 0;response
//循环发生发送CMD0,无响应,无返回,让SD卡进入空闲模式
for(i = 0;i
{
SDIO_SendCommand(CMD0,0,0);
errorstatus = CmdError(); //判断命令是否执行成功,此命令只要初始化了SDIO就会执行成功
if(errorstatus == SD_OK)
break;
}
if(errorstatus != SD_OK)
{
DEBUG("error!(%d)\n",errorstatus); //调试,打印信息
return(errorstatus);
}
//发送CMD8:SEND_IF_COND;短响应,命令参数:SD_CHECK_PATTERN;返回响应R7
//识别卡版本
SDIO_SendCommand(SDIO_SEND_IF_COND,SD_CHECK_PATTERN,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short);
errorstatus = CmdResp7Error();
if (errorstatus == SD_OK) //返回成功;说明卡为SD Card 2.0 V2.0
{
CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /* SD Card 2.0 */
SDType = SD_HIGH_CAPACITY;
DEBUG("SDIO_STD_CAPACITY_SD_CARD_V2_0!\n"); //调试,打印错误信息
}
else //V1.0 V1.1
{
DEBUG("SD Card V1.1!\n"); //调试,打印信息
CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1; //V1.0 V1.1
SDIO_SendCommand(CMD55,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short);
CmdResp1Error();
}
do
{
//发送CMD55 SDIO_APP_CMD;命令参数:0;返回响应R1,设置RCA为0,短响应
SDIO_SendCommand(SDIO_APP_CMD,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short);
errorstatus = CmdResp1Error();
if (errorstatus != SD_OK)
{
DEBUG("CMD55 error(%d)!\n",errorstatus); //调试,打印错误信息
return(errorstatus);
}
//发送ACM41命令;命令参数:SD_APP_OP_COND(0x80100000);短响应.响应为R3,返回操作条件寄存器RCA
SDIO_SendCommand(SDIO_SD_APP_OP_COND,SD_VOLTAGE_WINDOW_SD | SDType,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short);
errorstatus = CmdResp3Error();
if (errorstatus != SD_OK)
{
DEBUG("ACM41 error(%d)!\n",errorstatus); //调试,打印错误信息
return(errorstatus);
}
response = SDIO_GetResponse(SDIO_RESP1); //获取响应,RESE1
validvoltage = (bool) (((response >> 31) == 1) ? 1 : 0);
count++;
}
while((!validvoltage) && (count
if (count >= SD_MAX_VOLT_TRIAL) //重试次数超出
{
errorstatus = SD_INVALID_VOLTRANGE;
return(errorstatus);
}
if (response &= SD_HIGH_CAPACITY)
{
CardType = SDIO_HIGH_CAPACITY_SD_CARD;
}
return(errorstatus);
}
/*************************************************************************************************************************
* 函数 : SD_Error SD_PowerOFF(void)
* 功能 : SD卡掉电
* 参数 : 无
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120516
* 说明 : SD卡掉电
*************************************************************************************************************************/
SD_Error SD_PowerOFF(void)
{
SD_Error errorstatus = SD_OK;
SDIO_BusPowerOFF(); //关闭总线电源
return(errorstatus);
}
/*************************************************************************************************************************
* 函数 : SD_Error SD_PowerON(void)
* 功能 : SD卡电源开启
* 参数 : 无
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120524
* 说明 : SD卡电源开启
*************************************************************************************************************************/
SD_Error SD_PowerON(void)
{
SD_Error errorstatus = SD_OK;
SDIO_BusPowerON(); //打开总线电源
return(errorstatus);
}
/*************************************************************************************************************************
* 函数 : SD_Error SD_InitializeCards(void)
* 功能 : 将所有的卡进行初始化配置
* 参数 : 无
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
* 时间 : 20120516
* 最后修改时间 : 20120516
* 说明 : 将所有的卡进行初始化配置
*************************************************************************************************************************/
SD_Error SD_InitializeCards(void)
{
SD_Error errorstatus = SD_OK;
u16 rca = 0x01;
//发送CMD2 SDIO_ALL_SEND_CID命令,命令参数:0;长回复,R2
//发送CMD用来获取CID信息的
SDIO_SendCommand(SDIO_ALL_SEND_CID,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Long);
errorstatus = CmdResp2Error(); //获取响应R2
if (errorstatus != SD_OK)
{
DEBUG("error!(%d)\n",errorstatus); //调试,打印错误信息
return(errorstatus);
}
//到每个卡以获取每个卡的唯一标识CID
CID_Tab[0] = SDIO_GetResponse(SDIO_RESP1);
CID_Tab[1] = SDIO_GetResponse(SDIO_RESP2);
CID_Tab[2] = SDIO_GetResponse(SDIO_RESP3);
CID_Tab[3] = SDIO_GetResponse(SDIO_RESP4);
//发送CMD3,SET_REL_ADDR命令,参数0,响应,短响应,R6
//用来获取卡地址
//主机发送CMD3(SEND_RELATIVE_ADDR)要求卡发布一个新的相对卡地址RCA,地址比CID短,在以后的数据传输模式中用来寻址卡。一旦获得RCA后,卡状态变成就绪状态(Stand-by state)
SDIO_SendCommand(SDIO_SET_REL_ADDR,0,SDIO_CMDIndexEn | SDIO_CMDCrcEn | SDIO_Response_Short);
errorstatus = CmdResp6Error(&rca); //获取卡地址
if (errorstatus != SD_OK)
{
DEBUG("error!(%d)!\n",errorstatus); //调试,打印错误信息
return(errorstatus);
}
RCA = rca;//存储卡地址
//发送CMD9 SDIO_SEND_CSD命令,参数:rca地址;长响应,R2;
//给卡发送一个新的RCA,主要是用来设置卡地址的
SDIO_SendCommand(SDIO_SEND_CSD,(u32)rca <
errorstatus = CmdResp2Error();
if (errorstatus != SD_OK)
{
DEBUG("error!(%d)!\n",errorstatus); //调试,打印错误信息
return(errorstatus);
}
//获取CSD
CSD_Tab[0] = SDIO_GetResponse(SDIO_RESP1);
CSD_Tab[1] = SDIO_GetResponse(SDIO_RESP2);
CSD_Tab[2] = SDIO_GetResponse(SDIO_RESP3);
CSD_Tab[3] = SDIO_GetResponse(SDIO_RESP4);
//选中卡,并激活
errorstatus = SD_SelectDeselect((u32)RCA <
if(errorstatus != SD_OK)
{
DEBUG("SelectDeselect error!(%d)!\n",errorstatus); //调试,打印错误信息
return(errorstatus);
}
errorstatus = SD_OK; /* All cards get intialized */
SDIO_CLKFrequencySelect(SDCLK_1_2); //设置时钟
SDIO_SetTimeOutClock(TIME_OUT_UNIT_KHZ,63); //设置超时时钟频率最高
errorstatus = SD_EnableWideBusMode(Enable);
if(errorstatus == SD_OK) //配置SD卡为4线模式
{
DEBUG("SD SDIO 4BIT OK\n");
}
else
{
errorstatus = SD_EnableWideBusMode(Disable);
DEBUG("SD SDIO 4BIT ERROR (%d)\n",errorstatus);
}
SDIO_SetTransferBlockSize(SD_BlockSize);//设置传输块大小为512字节
errorstatus = SD_SetBlockSize(SD_BlockSize);//配置SD卡块大小
if (errorstatus != SD_OK)
{
DEBUG("SD SetBlockSize error(%d)!\n",errorstatus);
return(errorstatus);
}
return(errorstatus);
}
/*************************************************************************************************************************
* 函数 : SD_Error SD_SelectDeselect(u32 addr)
* 功能 : 选中一个卡,并处于传输状态
* 参数 : addr:卡地址
* 返回 : SD_OK:成功,其它见SD Card Error code.
* 依赖 : 底层寄存器操作函数
* 作者 : 陈鹏
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』