📄 sdcarddriver.c
字号:
//=============================================================
//语法格式: int DrvSDCWriteMulCommand(unsigned int block)
//实现功能: 启动写扇区操作
//参数: block - 扇区序号
//返回值: 正常退出返回0,非正常退出返回1
//=============================================================
int DrvSDCWriteMulCommand(unsigned int block)
{
unsigned int response[4];
SDCommand(C_SD_CMD7, gui_RCA, response);
*P_SD_ARGUMENT_DATA = gui_RCA;
*P_SD_COMMAND_SETUP = C_SD_CMD13;
while((*P_SD_INT_STATUS & C_SD_CMD_COMPLETE) == 0x00);
response[0] = *P_SD_RESPONSE_DATA;
*P_SD_INT_STATUS = C_SD_CLR_AllBIT;
if(SDCommand(C_SD_CMD25,block<<9,response))
return 1;
return 0;
}
//=============================================================
//语法格式: int DrvSDCWriteMulData(unsigned char *outaddr)
//实现功能: 向扇区写入数据
//参数: outaddr - 保存数据的缓冲区首地址
//返回值: 正常退出返回0,非正常退出返回1
//=============================================================
int DrvSDCWriteMulData(unsigned char *outaddr)
{
unsigned int i;
i = 0;
while((*P_SD_INT_STATUS & C_SD_CARD_BUSY) != 0x00)
{
i++;
if(i == 0xFFFFFF)
return 1;
}
i=(unsigned int) outaddr;
if((i & 0x03) == 0)
{
// USE DMA
*P_DMA_CHANNEL0_CTRL = 0x0000;
*P_DMA_AHB_SA0BA = (unsigned int)outaddr;
*P_DMA_AHB_EA0BA = (unsigned int)outaddr + ( 512 ) - 4;
*P_DMA_APB_SA0 = (unsigned int)P_SD_TX_DATA;
*P_DMA_CHANNEL0_CTRL = C_DMA_MIU_APB|C_DMA_POLLING_MODE|C_DMA_REGULAR_MODE|C_DMA_SINGLE_BUF|C_DMA_32BIT_BURST|C_DMA_CH_EN;
// Loop until DMA interrupt is set
while ((*P_DMA_INT_STATUS & 0x1) == 0)
{
if(!SDDrv_CheckCard)
return 1;
}
// Clear Interrupt and Disable DMA channel
*P_DMA_INT_STATUS = 0x1;
*P_DMA_CHANNEL0_CTRL = 0x0000;
}
else
{
// Do not USE DMA
unsigned int DataCount;
unsigned int Data;
DataCount=512 >> 2; // DataCount = 512 Byte / 4
do
{
if(WaitSDStatus(C_SD_DATABUF_EMPTY))
return 1;
Data=(unsigned int) *outaddr;
outaddr++;
Data |= ((unsigned int) *outaddr)<<8;
outaddr++;
Data |= ((unsigned int) *outaddr)<<16;
outaddr++;
Data |= ((unsigned int) *outaddr)<<24;
outaddr++;
*P_SD_TX_DATA=Data;
DataCount--;
}while(DataCount != 0x00);
}
i = 0;
while((*P_SD_INT_STATUS & C_SD_DATA_COMPLETE) == 0x00)
{
i++;
if( i == 20000)
return 1;
}
*P_SD_INT_STATUS = C_SD_CLR_AllBIT;
return 0;
}
#if 0
//=============================================================
//语法格式: int DrvSDCWriteMulData_INT(unsigned char *outaddr)
//实现功能: DMA方式写扇区初始化
//参数: outaddr - 保存数据的缓冲区首地址
//返回值: 正常退出返回0,非正常退出返回1
//=============================================================
int DrvSDCWriteMulData_INT(unsigned char *outaddr)
{
unsigned int i;
i = 0;
while((*P_SD_INT_STATUS & C_SD_CARD_BUSY) != 0x00)
{
i++;
if(i == 0xFFFFFF)
return 1;
}
// USE DMA
*P_DMA_CHANNEL0_CTRL = 0x0000;
*P_DMA_AHB_SA0BA = (unsigned int)outaddr;
*P_DMA_AHB_EA0BA = (unsigned int)outaddr + (1 << 9) - 4;
*P_DMA_APB_SA0 = 0x88180000;
*P_DMA_CHANNEL0_CTRL = C_DMA_MIU_APB|C_DMA_POLLING_MODE|C_DMA_REGULAR_MODE|C_DMA_SINGLE_BUF|C_DMA_32BIT_BURST|C_DMA_INT_EN|C_DMA_CH_EN;
return 0;
}
#endif
//=============================================================
//语法格式: int DrvSDCWriteMulStop(void)
//实现功能: 停止写扇区操作
//参数: 无
//返回值: 正常退出返回0,非正常退出返回1
//=============================================================
int DrvSDCWriteMulStop(void)
{
unsigned int i;
unsigned int response[4];
i = 0;
while((*P_SD_INT_STATUS & C_SD_CARD_BUSY) != 0x00)
{
i++;
if(i == 0xFFFFFF)
return 1;
}
// Stop the controller
*P_SD_COMMAND_SETUP = C_SD_CTRL_IDLE;
// Loop until controller idle
while(*P_SD_INT_STATUS & C_SD_CTRL_BUSY);
*P_SD_INT_STATUS = C_SD_CTRL_BUSY;
// Stop the card
if(SDCommand(C_SD_CMD12, 0x00000000, response))
return 1;
i = 0;
do {
*P_SD_INT_STATUS=C_SD_CLR_AllBIT;
if(SDCommand(C_SD_CMD13, gui_RCA, response))
return 1;
i++;
if(i == 60000)
return 1;
} while (response[0] != 0x0900);
SDCommand(C_SD_CMD7, gui_RCA, response);
return 0;
}
//=============================================================
//语法格式: int SDDrv_GetMemSize(void)
//实现功能: 获取SD卡容量
//参数: 无
//返回值: SD卡扇区个数
//=============================================================
int SDDrv_GetMemSize(void)
{
return gi_SDCardTotalSector;
}
//=============================================================
//语法格式: int SDDrv_GetMemSize(void)
//实现功能: 获取SD卡速度信息
//参数: 无
//返回值: 正常退出返回0,非正常退出返回1
//=============================================================
int SDDrv_GetSpeed(void)
{
unsigned int response[4], tranunit, timevalue, maxspeed;
unsigned int SpeedTable[]={
0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
};
unsigned int TranTable[]={
1, 10, 100, 1000,
};
SDCommand(C_SD_CMD7, 0x00000000, response);
SDCommandr2(C_SD_CMD9, gui_RCA, response);
timevalue = ((response[0] & 0x00000078)>>3);
tranunit=response[0] & 0x00000007;
maxspeed = SpeedTable[timevalue] * TranTable[tranunit] / 100;
if ((timevalue == 0) || (tranunit > 3))
return 1;
SDCommand(C_SD_CMD7, gui_RCA, response);
return maxspeed;
}
//=============================================================
//语法格式: int SDDrv_Initial(void)
//实现功能: 初始化SD卡
//参数: 无
//返回值: 正常退出返回0,非正常退出返回1
//=============================================================
int SDDrv_Initial(void)
{
int i, loopcnt=0;
unsigned int response[4];
unsigned int tranunit, timevalue;
unsigned int maxspeed;
unsigned int c_size, mult, blocklen;
unsigned int SpeedTable[]={
0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
};
unsigned int TranTable[]={
1, 10, 100, 1000,
};
*P_NAND_GPIO_PULL = 0xf819fc19; // DAT3 Float in, Others PP
*P_SD_INTERFACE_SEL = C_SD_PORT_SEL; // SFTCFG SDCard Enable
*P_SD_CLK_CONF = C_SD_CLK_EN + C_SD_RST_DIS; // SDCard Clock Enable
*P_DMA_CLK_CONF = C_DMA_CLK_EN + C_DMA_RST_DIS; // APBDMA Clock Enable
// *P_CLK_PLLAU_CONF = C_PLLU_CLK_EN + C_PLLA_CLK_EN + C_PLLA_CLK_67M;
if(!SDDrv_CheckCard) // Check if card present
return 1;
// Disable All SD Interrupt
*P_SD_INT_CTRL = 0x0000;
// Step 1, Reset SD Controller
*P_SD_MODE_CTRL = C_BLOCKLEN_512BYTE|C_INIT_CLOCK_SPEED|C_SD_PORT_EN|C_SD_DMA_EN;
// Clear All Command
*P_SD_COMMAND_SETUP = C_SD_CTRL_IDLE;
while (*P_SD_INT_STATUS & 0x1);
// Clear All Status
*P_SD_INT_STATUS = C_SD_CLR_AllBIT;
loopcnt = 0;
// Step 2, Start 74 cycles on SD Clk Bus
*P_SD_COMMAND_SETUP = C_SD_74CLK_START;
if (WaitSDStatus(C_SD_CMD_COMPLETE))
return 1;
*P_SD_INT_STATUS = C_SD_CLR_AllBIT;
// Step 3, Reset Command, Should be no response
SDCommand(C_SD_CMD0, 0x00000000, response);
//////////////////////////////////////////////////////////////////
// SECTION 2. CARD IDEN //
//////////////////////////////////////////////////////////////////
loopcnt = 0;
gi_CardType = SDCARD;
// Step 4, Run ACMD 41 until card finish power up sequence
do
{
if (gi_CardType == SDCARD)
{
if (SDCommand(C_SD_CMD55, 0x00000000, response))
gi_CardType = MMCCARD;
}
if (gi_CardType == SDCARD)
// ACMD 41
SDCommand(C_SD_ACMD41, 0x00200000, response); // SD Card
else
SDCommand(C_SD_CMD1, 0x00200000, response); // MMC Card
// Check until Bit 31 in OCR register is set
loopcnt = loopcnt + 1;
} while (((response[0] & 0x80000000) == 0) && loopcnt < 20000);
if (loopcnt == 20000)
return 1;
// Step 5, CMD 2 Read CID Register
if(SDCommandr2(C_SD_CMD2, 0x00000000, response))
return 1;
if (gi_CardType == SDCARD)
{
// Step 6, CMD 3 Read New RCA, SD will generate RCA itself
if(SDCommand(C_SD_CMD3, 0x00000000, response))
return 1;
gui_RCA = response[0];
} else {
// Step 6, CMD 3 Set New RCA, MMC need to be assigned a new RCA
if(SDCommand(C_SD_CMD3, 0xFFFF0000, response))
return 1;
gui_RCA = 0xFFFF0000;
}
// Read Status
SDCommand(C_SD_CMD13, gui_RCA, response);
if (response[0] != 0x0700)
return 1;
//////////////////////////////////////////////////////////////////
// SECTION 3. SET BUSWIDTH AND CLOCK SPEED //
//////////////////////////////////////////////////////////////////
// Step 7, CMD 9 Read CSD Register
for (i=0;i<4;i++)
response[i] = 0;
if(SDCommandr2(C_SD_CMD9, gui_RCA, response))
return 1;
// Calculate Totoal Memory Size
blocklen = ((response[1] & 0x000F0000)>>16)-8;
c_size = ((response[1] & 0x000003FF)<<2) + (response[2]>>30);
mult = ((response[2] & 0x00030000)>>15) + ((response[2] & 0x0000FFFF)>>15);
gi_SDCardTotalSector = (blocklen*(c_size+1))<<(mult + 2);
timevalue = ((response[0] & 0x00000078)>>3);
tranunit = response[0] & 0x00000007;
if((timevalue == 0) || (tranunit > 3))
return 1;
maxspeed = SpeedTable[timevalue] * TranTable[tranunit] / 100;
if (maxspeed > 13)
//Increase Clock Speed
*P_SD_MODE_CTRL = C_BLOCKLEN_512BYTE|C_MIN_CLOCK_SPEED|C_SD_PORT_EN|C_SD_DMA_EN;
else
//Increase Clock Speed
*P_SD_MODE_CTRL = C_BLOCKLEN_512BYTE|C_MMC_CLOCK_SPEED|C_SD_PORT_EN|C_SD_DMA_EN;
SDCommand(C_SD_CMD13, gui_RCA, response);
SDCommand(C_SD_CMD7, gui_RCA, response);
// Only SD has 4 bits mode
if (gi_CardType == SDCARD)
{
//Short block size to 8 bytes
*P_SD_MODE_CTRL = C_BLOCKLEN_8BYTE|(*P_SD_MODE_CTRL&0xffff);
//ACMD 51
SDCommand(C_SD_CMD55, gui_RCA, response);
if(SDCommandr3(C_SD_ACMD51, gui_RCA, response))
return 1;
if ((response[0] & 0x00000400) != 0x00)
{
//Set Bus width to 4 bits
SDCommand(C_SD_CMD55, gui_RCA, response);
SDCommand(C_SD_ACMD6, 0x00000002, response);
*P_SD_MODE_CTRL = C_BLOCKLEN_512BYTE|C_MIN_CLOCK_SPEED|C_SD_PORT_EN|C_SD_DMA_EN|C_SD_BUS_4BIT;
}
else
*P_SD_MODE_CTRL = C_BLOCKLEN_512BYTE|C_MIN_CLOCK_SPEED|C_SD_PORT_EN|C_SD_DMA_EN;
}
SDCommand(C_SD_CMD13, gui_RCA, response);
*P_SD_MODE_CTRL = C_BLOCKLEN_512BYTE|(*P_SD_MODE_CTRL&0xffff);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -