📄 sd.c
字号:
/*
*********************************************************
* 头文件
*********************************************************
*/
#include <stdio.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "sd.h"
#define INICLK 300000 //初始频率
#define SDCLK 24000000 //PCLK=49.392MHz
#define MMCCLK 15000000 //PCLK=49.392MHz
#define MAX_DATABUSY_TIMEOUT 0x007FFFFF
#define WORDS_PER_BLOCK 128
#define MAX_RWBUFFER_BLOCKNUM 16
#define Tx_buffer (unsigned int *)0x31700000 //读写缓冲地址
#define Rx_buffer (unsigned int *)0x31800000
#define POL 0
#define INT 1
#define DMA 2
#define Wide ENUM_SD_BUS_4_BIT // 总线位数
/*
*********************************************************
* 变量
*********************************************************
*/
volatile U32 SD_CardIn = 0; //SD卡插入中断标志
volatile U32 TR_end =0; //数据传输完成标志
/*
*********************************************************
* 函数
*********************************************************
*/
int Check_Card_In(void)
{
int CardIn;
U32 save_rGPGCON = rGPGCON;
rGPGCON = (rGPGCON & 0xfffcffff); // CDSD,GPG8 =>In
Delay(50);
if(rGPGDAT & (1<<8))
{
CardIn = 0;
}
else
{
CardIn = 1;
}
rGPGCON = save_rGPGCON;
return CardIn;
}
static void SD_Set_IOPort(void)
{
rGPECON = ((rGPECON & 0xffb003ff) | 0xffeaabff); // SDCLK, SDCMD, SDDAT[3:0]
rGPEUP = (rGPEUP & 0xf83f); // SDCMD, SDDAT[3:0] => PU En.
}
void SD_Config_Irq(void) //Config SD Irq --wangq
{
rGPGCON = (rGPGCON & (0<<16) | (1<<17)); // CDSD,GPG8 =>EINT[16]
rGPGUP = rGPGUP & (~(0x1<<8)); // Enable pullup
rEXTINT2 = (1<<3) + 2; // EINT16 Filter Enable,Falling edge triggered
rEINTFLT2 = (rEINTFLT2 & (0<<7) | 0x7f); // PCLK,Filtering width=0x3f
rEINTMASK = ~(1<<16); // Enable EINT16 interrupt
ClearPending(BIT_EINT8_23);
rINTMSK = ~(BIT_EINT8_23); // Enable EINT8_23 interrupt
//Uart_Printf("Config SD Irq Complete----------!\n");
}
static int Chk_CMDend(int cmd, int be_resp)
{
int finish0;
if(!be_resp) // No response
{
finish0 = rSDICSTA;
while((finish0 & 0x800) != 0x800) // Check cmd end
{
finish0 = rSDICSTA;
}
rSDICSTA = finish0;// Clear cmd end state
return 1;
}
else // With response
{
finish0 = rSDICSTA;
while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x400) )) // Check time/rsp end
// while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x800) )) // Check cmd/rsp end
{
finish0 = rSDICSTA;
}
//Uart_Printf("CMD%d:rSDICSTA=0x%x\n", cmd, rSDICSTA); //YH 0811
if((cmd==1) | (cmd==41)) // CRC no check, CMD9 is a long Resp. command.
{
if( (finish0 & 0xf00) != 0xa00 ) // Check error
{
//Uart_Printf("Error: CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x\n",cmd, rSDICSTA, rSDIRSP0);
rSDICSTA=finish0; // Clear error state
if(((finish0&0x800) == 0x800))
{
return 1; // CMD end
}
if(((finish0&0x400) == 0x400))
{
return 0; // Timeout error
}
}
rSDICSTA = finish0; // Clear cmd & rsp end state
}
else // CRC check
{
if( (finish0&0x1f00) != 0xa00 ) // Check error
{
//Uart_Printf("Error: CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x\n",cmd, rSDICSTA, rSDIRSP0);
rSDICSTA = finish0; // Clear error state
if((finish0 & 0x400) == 0x400)
{
return 0; // Timeout error
}
}
//Uart_Printf("ok: CMD%d:rSDICSTA=0x%x, rSDIRSP0=0x%x\n",cmd, rSDICSTA, rSDIRSP0);
rSDICSTA = finish0;
}
return 1;
}
}
static void CMD0(void)
{
//-- Make card idle state
rSDICARG = 0x0; // CMD0(stuff bit)
rSDICCON = (1<<8) | 0x40; // No_resp, start, CMD0
//-- Check end of CMD0
Chk_CMDend(0, 0);
rSDICSTA = 0x800; // Clear cmd_end(no rsp)
}
static int CMD8(void)//SEND_IF_COND
{
int i = 0;
for (i = 0; i < 50; i++) //CMD8
{
rSDICARG = 0x1AA; //CMD8(SD VHS:2.7V~3.6V)
rSDICCON = (0x1<<9) | (0x1<<8) | 0x48; //sht_resp, wait_resp, start, CMD8
if ( Chk_CMDend(8, 1) & (rSDIRSP0 == 0x1aa) )
{
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 1;
}
Delay(200); // Wait Card power up status
}
return 0;
}
static int CMD2(void)// ALL_SEND_CID
{
int Serial_Num; //SD卡ID
rSDICARG = 0x0; // CMD2(stuff bit)
rSDICCON = (0x1<<10) | (0x1<<9) | (0x1<<8) | 0x42; //lng_resp, wait_resp, start, CMD2
//-- Check end of CMD2
if(!Chk_CMDend(2, 1))
{
return 0; // Fail
}
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
Serial_Num = ((rSDIRSP2&0xffffff) << 8) | ((rSDIRSP3&0xff000000) >> 24);
Uart_Printf("Card Id = 0x%x\n",Serial_Num);
//Uart_Printf("Capacity = %c%c%c\n",(rSDIRSP1&0xff0000)>>16,(rSDIRSP1&0xff00)>>8,rSDIRSP1&0xff);
Uart_Printf("The manufacturing date is %d.%d\n",2000+((rSDIRSP3&0xff000)>>12) ,(rSDIRSP3&0xf00)>>8);
return Serial_Num; // Success
}
static int CMD3(void) // SEND_RCA
{
rSDICARG = 0x0; // CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ)
rSDICCON = (0x1<<9)|(0x1<<8)|0x43; // sht_resp, wait_resp, start, CMD3
//-- Check end of CMD3
if(!Chk_CMDend(3, 1))
{
return 0;
}
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 1;
}
static int Chk_MMC_OCR(void)
{
int i;
//-- Negotiate operating condition for MMC, it makes card ready state
for(i = 0; i < 50; i++) //Negotiation time is dependent on CARD Vendors.
{
//rSDICARG=0xffc000; //CMD1(MMC OCR:2.6V~3.6V)
rSDICARG = 0xff8000; //CMD1(SD OCR:2.7V~3.6V)
rSDICCON = (0x1<<9)|(0x1<<8)|0x41; //sht_resp, wait_resp, start, CMD1
//-- Check end of CMD1
if(Chk_CMDend(1, 1) && (rSDIRSP0>>16)==0x80ff) //YH 0903 [31]:Card Power up status bit (busy)
//if(Chk_CMDend(1, 1) & rSDIRSP0==0x80ff8000)
{
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 0; // Success,MMC
}
}
rSDICSTA = 0xf00; // Clear cmd_end(with rsp)
return 1; // Fail,SD
}
static int CMD55(int iRCA)
{
//--Make ACMD
rSDICARG = iRCA<<16; //CMD7(RCA,stuff bit)
rSDICCON = (0x1<<9) | (0x1<<8) | 0x77; //sht_resp, wait_resp, start, CMD55
//-- Check end of CMD55
if(!Chk_CMDend(55, 1))
{
return 0;
}
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 1;
}
static int Chk_SD_OCR(void) //ACMD41
{
int i;
//-- Negotiate operating condition for SD, it makes card ready state
for(i=0;i<50;i++) //If this time is short, init. can be fail.
{
//-- 检测是否为SDHC
CMD55(0); // Make ACMD
rSDICARG = 0xc0ff8000; //ACMD41(SD OCR:2.7V~3.6V,HCS=1)
//rSDICARG=0xffc000; //ACMD41(MMC OCR:2.6V~3.6V)
rSDICCON = (0x1<<9)|(0x1<<8)|0x69;//sht_resp, wait_resp, start, ACMD41
//-- Check end of ACMD41
if( Chk_CMDend(41, 1) && (rSDIRSP0==0xc0ff8000) )
{
Uart_Printf("SDHC Card...\n");
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 1; // Success
}
//-- 检测是否为SD1.0
CMD55(0); // Make ACMD
rSDICARG = 0x80ff8000; //ACMD41(SD OCR:2.7V~3.6V,HCS=0)
rSDICCON = (0x1<<9) | (0x1<<8) | 0x69;//sht_resp, wait_resp, start, ACMD41
//-- Check end of ACMD41
if( Chk_CMDend(41, 1) && (rSDIRSP0==0x80ff8000) )
{
Uart_Printf("SD1.0 Card...\n",rSDIRSP0);
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 2; // Success
}
Delay(200); // Wait Card power up status
}
Uart_Printf("Error: ACMD41 SDIRSP0=0x%x\n",rSDIRSP0);
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
return 0; // Fail
}
int Card_Select( int iRCA)
{
//-- Card select
int i = 0;
do
{
rSDICARG = iRCA<<16; // CMD7(RCA,stuff bit)
rSDICCON = (0x1<<9) | (0x1<<8) | 0x47; // sht_resp, wait_resp, start, CMD7
i++;
}
//-- Check end of CMD7
while(!Chk_CMDend(7, 1) && (i < 100));
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
if (i == 100)
{
return 0;
}
//--State(transfer) check
if( (rSDIRSP0 & 0x1e00) != 0x800 )
{
return 0;
}
return 1;
}
int Card_Deselect( void)
{
//-- Card deselect
int i = 0;
do
{
rSDICARG = 0<<16; //CMD7(RCA,stuff bit)
rSDICCON = (0x1<<8)|0x47; //no_resp, start, CMD7
i++;
}
//-- Check end of CMD7
while(!Chk_CMDend(7, 0) && (i < 100));
rSDICSTA = 0x800; // Clear cmd_end(no rsp)
if (i == 100)
{
return 0;
}
return 1;
}
static int CMD9(int iRCA) //SEND_CSD
{
Card_Deselect(); // Card deselect
rSDICARG = iRCA<<16; // CMD9(RCA,stuff bit)
rSDICCON = (0x1<<10)|(0x1<<9)|(0x1<<8)|0x49; // long_resp, wait_resp, start, CMD9
//-- Check end of CMD9
if (!Chk_CMDend(9, 1))
{
return 0;
}
if ((rSDIRSP0&0xf0000000)>>28 == 4) //CSD Version 2.0
{
Uart_Printf("Memory Capacity= %dMB\n",( (rSDIRSP2&0xffff0000)>>16 )>>1 );
}
else if ((rSDIRSP0&0xf0000000)>>28 == 0) //CSD Version 1.0
{
Uart_Printf("Memory Capacity= %dMB\n",(((rSDIRSP1&0x3ff)<<2) | (rSDIRSP2&0xc0000000))>>1);
}
//Uart_Printf("CSD register :\n");
//Uart_Printf("SDIRSP0=0x%x\nSDIRSP1=0x%x\nSDIRSP2=0x%x\nSDIRSP3=0x%x\n", rSDIRSP0,rSDIRSP1,rSDIRSP2,rSDIRSP3);
Card_Select(iRCA); // Card select
return 1;
}
static int SetBus(int iRCA,enum_sd_bus_width iWide)
{
int i = 0;
do
{
CMD55(iRCA); // Make ACMD
//-- CMD6 implement
rSDICARG = iWide << 1; //Wide 0: 1bit, 1: 4bit
rSDICCON = (0x1 << 9) | (0x1 << 8) | 0x46; //sht_resp, wait_resp, start, CMD46
i++;
}
while((i < 50) && (!Chk_CMDend(6, 1))); // ACMD6
rSDICSTA = 0xa00; // Clear cmd_end(with rsp)
if (i < 50)
{
if (iWide)
{
Uart_Printf("**** 4bit bus ****\n");
}
else
{
Uart_Printf("**** 1bit bus ****\n");
}
return 1;
}
else
{
return 0;
}
}
static int Set_1bit_bus(int iRCA)
{
int i = 0;
do
{
CMD55(iRCA); // Make ACMD
//-- CMD6 implement
rSDICARG = 0 << 1; //Wide 0: 1bit, 1: 4bit
rSDICCON = (0x1<<9) | (0x1<<8) | 0x46; //sht_resp, wait_resp, start, CMD46
i++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -