📄 mmc.c
字号:
//////////////////////////////////////////////////////
// 2410 for MMC & SD
//
//
//
// ldqmoon
// 2008-6-10
//
#include "def.h"
#include "2410lib.h"
#include "file_sys_cfg.h"
#include "2410addr.h"
#include "mmc.h"
#define INICLK 400000 //400000
#define NORCLK 5000000 //5000000
#define POL 0
#define INT 1
#define DMA 2
int Wide=0; // 0:1bit, 1:4bit
int MMC=0; // 0:SD , 1:MMC
int Maker_ID;
char Product_Name[7];
int Serial_Num;
volatile int RCA;
volatile unsigned int rd_cnt;
volatile unsigned int wt_cnt;
//#define SD_INFO
#ifdef _ALL_SD_CMDS_
uHILO32 OCR_REG;
#endif
uchar _FF_buff[512];
#ifndef _BytsPerSec_512_
uHILO16 BPB_BytsPerSec;
#endif
uchar BPB_SecPerClus;
uHILO16 BPB_RsvdSecCnt;
uHILO16 BPB_RootEntCnt;
uHILO16 BPB_FATSz16;
uchar BPB_FATType;
uHILO32 BS_VolSerial;
uchar BS_VolLab[12];
uint _FF_PART_ADDR;
U32 _FF_ROOT_ADDR;
#ifdef _DIRECTORIES_SUPPORTED_
ulong _FF_DIR_ADDR;
#endif
uint _FF_FAT1_ADDR;
U32 _FF_FAT2_ADDR;
uint FirstDataSector;
uchar _FF_error;
ulong _FF_buff_addr;
uint clus_0_addr, _FF_n_temp;
uint c_counter;
U8 _FF_FULL_PATH[_FF_PATH_LENGTH];
U32 DataClusTot;
// 准备系统fat
uchar initialize_media(void)
{
//uchar data_temp;
uchar n;
ulong _FF_RootDirSectors;
uHILO16 PT_SecStart;
uchar BPB_NumFATs;
uHILO32 BPB_TotSec;
#ifndef _BytsPerSec_512_
BPB_BytsPerSec.ival = 512; // Initialize sector size to 512 (all SD cards have a 512 sector size)
#endif
_FF_n_temp = 0;
if(!Mmc_Init())
{
return 0;
}
if (_FF_read(0x0, _FF_buff)==0)
{
#ifdef _DEBUG_ON_
printf(_FF_RErr_str);
#endif
//_FF_error = INIT_ERR;
return (0);
}
if (!((_FF_buff[510]==0x55)&&(_FF_buff[511]==0xAA)))
{
#ifdef _DEBUG_ON_
printf(_FF_InvParTbl_str);
#endif
//_FF_error = INV_PARTTABLE_ERR;
Uart_Printf("INV_PARTTABLE_ERR; wrong\n");
return (0);
}
if (((_FF_buff[0]==0xEB)&&(_FF_buff[2]==0x90))||(_FF_buff[0]==0xE9))
PT_SecStart.ival = 0;
else if (_FF_buff[0x1BF])
{
PT_SecStart.cval.HI = _FF_buff[0x1C7];
PT_SecStart.cval.LO = _FF_buff[0x1C6];
}
else if (_FF_buff[0x1CF])
{
PT_SecStart.cval.HI = _FF_buff[0x1D7];
PT_SecStart.cval.LO = _FF_buff[0x1D6];
}
else if (_FF_buff[0x1DF])
{
PT_SecStart.cval.HI = _FF_buff[0x1E7];
PT_SecStart.cval.LO = _FF_buff[0x1E6];
}
else if (_FF_buff[0x1EF])
{
PT_SecStart.cval.HI = _FF_buff[0x1F7];
PT_SecStart.cval.LO = _FF_buff[0x1F6];
}
else
{
#ifdef _DEBUG_ON_
printf(_FF_InvParTbl_str);
#endif
//_FF_error = INV_PARTENTRY_ERR;
Uart_Printf("INV_PARTTABLE_ERR; wrong 2\n");
return (0);
}
_FF_PART_ADDR = (ulong) PT_SecStart.ival;
if (PT_SecStart.ival)
{
if (_FF_read(_FF_PART_ADDR, _FF_buff)==0)
{
#ifdef _DEBUG_ON_
printf(_FF_RErr_str);
#endif
//_FF_error = INIT_ERR;
Uart_Printf("INIT_ERR wrong 22 \n");
return (0);
}
}
#ifdef _DEBUG_ON_
printf(_FF_BSec_str, _FF_buff[0],_FF_buff[1],_FF_buff[2],_FF_buff[510],_FF_buff[511]);
#endif
// Get the number of Bytes per Sector (should be 512)
#ifdef _BytsPerSec_512_
if((_FF_buff[0xC] != 0x2) || (_FF_buff[0xB]))
return (0);
#else
BPB_BytsPerSec.cval.LO = _FF_buff[0xB];
BPB_BytsPerSec.cval.HI = _FF_buff[0xC];
#endif
// Get the number of Sectors per Cluster
BPB_SecPerClus = _FF_buff[0xD];
// Get the number of Reserved Sectors
BPB_RsvdSecCnt.cval.LO = _FF_buff[0xE];
BPB_RsvdSecCnt.cval.HI = _FF_buff[0xF];
// Get the number of FATs (should be 2)
BPB_NumFATs = _FF_buff[0x10];
// Get the number of Root Directory entries (should be 512)
BPB_RootEntCnt.cval.LO = _FF_buff[0x11];
BPB_RootEntCnt.cval.HI = _FF_buff[0x12];
// Get the FATSz16 value
BPB_FATSz16.cval.LO = _FF_buff[0x16];
BPB_FATSz16.cval.HI = _FF_buff[0x17];
// Get the number of Total Sectors available
BPB_TotSec.ival.HI = 0;
BPB_TotSec.cval.LO = _FF_buff[0x13];
BPB_TotSec.cval.ML = _FF_buff[0x14];
if (BPB_TotSec.lval==0)
{ // If the read value is 0, stored in a different location, read from other location
BPB_TotSec.cval.LO = _FF_buff[0x20];
BPB_TotSec.cval.ML = _FF_buff[0x21];
BPB_TotSec.cval.MH = _FF_buff[0x22];
BPB_TotSec.cval.HI = _FF_buff[0x23];
}
// Get the volume's Serial number
BS_VolSerial.cval.LO = _FF_buff[0x27];
BS_VolSerial.cval.ML = _FF_buff[0x28];
BS_VolSerial.cval.MH = _FF_buff[0x29];
BS_VolSerial.cval.HI = _FF_buff[0x2A];
// Store the Volume's label
for (n=0; n<11; n++)
BS_VolLab[n] = _FF_buff[0x2B+n];
BS_VolLab[11] = 0; // Terminate the string
// Calculate the Primary FAT table's Address
_FF_FAT1_ADDR = _FF_PART_ADDR + BPB_RsvdSecCnt.ival;
// Calculate the Secondary FAT table's Address
_FF_FAT2_ADDR = _FF_FAT1_ADDR + BPB_FATSz16.ival;
// Calculate the Address of the Root Directory
_FF_ROOT_ADDR = ((ulong) BPB_NumFATs * (ulong) BPB_FATSz16.ival) + (ulong) BPB_RsvdSecCnt.ival;
_FF_ROOT_ADDR += _FF_PART_ADDR;
// Calculate the number of Total data Clusters
#ifdef _BytsPerSec_512_
_FF_RootDirSectors = (((ulong) BPB_RootEntCnt.ival << 5) + 511) >> 9;
#else
_FF_RootDirSectors = (((ulong) BPB_RootEntCnt.ival << 5) + BPB_BytsPerSec.ival - 1) / BPB_BytsPerSec.ival;
#endif
FirstDataSector = (BPB_NumFATs * BPB_FATSz16.ival) + BPB_RsvdSecCnt.ival + _FF_RootDirSectors;
DataClusTot = (BPB_TotSec.lval - FirstDataSector) / BPB_SecPerClus;
clus_0_addr = 0; // Reset Empty Cluster table location
c_counter = 1;
_FF_buff_addr = 0;
#ifdef SD_INFO
Uart_Printf("DataClusTot=%d\n", DataClusTot);
#endif
if (DataClusTot < 4085) // FAT12
BPB_FATType = 0x32;
else if (DataClusTot < 65525) // FAT16
BPB_FATType = 0x36;
else
{
BPB_FATType = 0;
//_FF_error = FAT_ERR;
Uart_Printf("FAT_ERR wrong\n");
return (0);
}
#ifdef _DIRECTORIES_SUPPORTED_
_FF_DIR_ADDR = _FF_ROOT_ADDR; // Set current directory to root address
#endif
_FF_FULL_PATH[0] = 0x5C; // a '\'
_FF_FULL_PATH[1] = 0;
#ifdef _DEBUG_ON_
#ifdef _BytsPerSec_512_
printf(_FF_BS_PA_str, (_FF_PART_ADDR<<9));
printf(_FF_BPB_BPS_str, 0x200);
#else
printf(_FF_BS_PA_str, (_FF_PART_ADDR*BPB_BytsPerSec.ival));
printf(_FF_BPB_BPS_str, BPB_BytsPerSec.ival);
#endif
printf(_FF_BPB_SPC_str, BPB_SecPerClus);
printf(_FF_BPB_RSC_str, BPB_RsvdSecCnt.ival);
printf(_FF_BPB_NFAT_str, BPB_NumFATs);
printf(_FF_BPB_REC_str, BPB_RootEntCnt.ival);
printf(_FF_BPB_Fz16_str, BPB_FATSz16.ival);
printf(_FF_BPB_TS16_str, BPB_TotSec.lval);
printf(_FF_BPB_FT_str);
#endif
if ((BPB_FATType != 0x32) && (BPB_FATType != 0x36))
{
#ifdef _DEBUG_ON_
printf(_FF_ERR_str);
#endif
return(0);
}
#ifdef _DEBUG_ON_
else
printf(_FF_1C_str, BPB_FATType);
printf(_FF_CCnt_str, DataClusTot);
#ifdef _BytsPerSec_512_
printf(_FF_RAddr_str, _FF_ROOT_ADDR<<9);
printf(_FF_F2Addr_str, _FF_FAT2_ADDR<<9);
#else
printf(_FF_RAddr_str, _FF_ROOT_ADDR*BPB_BytsPerSec.ival);
printf(_FF_F2Addr_str, _FF_FAT2_ADDR*BPB_BytsPerSec.ival);
#endif
printf(_FF_RDSec_str, _FF_RootDirSectors);
printf(_FF_FDSec_str, FirstDataSector);
#endif
return (1);
}
// 初始化 mmc
S8 Mmc_Init(void)
{
//-- SD controller & card initialize
int i;
RCA=0;
MMC=0;
rGPEUP = 0xf83f; // The pull up
rGPECON = 0xaaaaaaaa;
/* Important notice for MMC test condition */
/* Cmd & Data lines must be enabled pull up resister */
rSDIPRE=PCLK/(2*INICLK)-1; // 400KHz
rSDICON=(1<<4)|(1<<1)|1; // Type B, FIFO reset, clk enable
rSDIBSIZE=0x200; // 512byte(128word)
rSDIDTIMER=0xffff; // Set timeout count
for(i=0;i<0x1000;i++); // Wait 74SDCLK for MMC card
//Uart_Printf("rSDIRSP0=0x%x\n",rSDIRSP0);
CMD0();
#ifdef SD_INFO
Uart_Printf("\nIn idle\n");
#endif
//-- Check MMC card OCR
if(Chk_MMC_OCR())
{
Uart_Printf("\nIn MMC ready\n");
MMC=1;
goto RECMD2;
}
//Uart_Printf("MMC check end!!\n");
//-- Check SD card OCR
if(Chk_SD_OCR())
{
#ifdef SD_INFO
Uart_Printf("\nIn SD ready\n");
#endif
}
else
{
#ifdef SD_INFO
Uart_Printf("\nInitialize fail\nNo Card assertion\n");
#endif
return 0;
}
RECMD2:
//-- Check attaced cards, it makes card identification state
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))
goto RECMD2;
//rSDICSTA=0xa00; // Clear cmd_end(with rsp)
#ifdef SD_INFO
Uart_Printf("\nEnd id\n");
#endif
RECMD3:
//--Send RCA
rSDICARG=MMC<<16; // 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))
goto RECMD3;
//rSDICSTA=0xa00; // Clear cmd_end(with rsp)
//--Publish RCA
if(MMC)
RCA=1;
else
RCA=( rSDIRSP0 & 0xffff0000 )>>16;
#ifdef SD_INFO
Uart_Printf("RCA=0x%x\n",RCA);
#endif
//--State(stand-by) check
if( rSDIRSP0 & 0x1e00!=0x600 ) // CURRENT_STATE check
goto RECMD3;
#ifdef SD_INFO
Uart_Printf("\nIn stand-by\n");
#endif
// rSDIPRE=PCLK/(2*NORCLK)-1; // Normal clock=25MHz
rSDIPRE=PCLK/(3*NORCLK)-1;
Card_sel_desel(1); // Select
if(!MMC)
Set_4bit_bus();
else
Set_1bit_bus();
return 1;
}
S8 Mmc_Read_Sector(U32 addr,U8 *Buffer)
{
int status;
int i;
U32 Rx_buffer[128];
rd_cnt=0;
#ifdef SD_INFO
Uart_Printf("addr is 0x%x", addr);
#endif
rSDICON |= rSDICON|(1<<1); // FIFO reset
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -