📄 mmctest.c
字号:
#include "mmc_base.h"
#define MMCTX 1
#define MMCRX 2
static struct MMC_Card *card;
unsigned long mmc_total_size = 0;
void MMC_config (struct MMC_Cfg *cfg) //czm
{
Uint16 resetMask = 0xF7FF;
// Perform Initialization
// Place controller in reset before changing other values resetie: make the pwr down
MMC_RSET_H (MMC_REG_CON, MMC_MMCCON_DEFAULT);
// enable callback functions based on the MMCIE value
MMC_RSET_H (MMC_REG_CMD, cfg->mmccmd);
MMC_RSET_H (MMC_REG_IE, cfg->mmcie);
MMC_RSET_H (MMC_REG_CTO, cfg->mmccto);
MMC_RSET_H (MMC_REG_DTO, cfg->mmcdto);
MMC_RSET_H (MMC_REG_BLEN, cfg->mmcblen);
MMC_RSET_H (MMC_REG_NBLK, cfg->mmcnblk);
MMC_RSET_H (MMC_REG_BUF, cfg->mmcbuf);
MMC_RSET_H (MMC_REG_CON, (cfg->mmccon & resetMask));
MMC_RSET_H (MMC_REG_CON, (cfg->mmccon | 0x0800)); // Take MMC out of reset //
MMC_RSET_H (MMC_REG_SDIO, 0x2000); // Take MMC out of reset //
};
Uint16
MMC_waitForFlag (Uint16 mask)
{
Uint16 done = 0;
Uint16 status;
do
{
status = MMC_RGET_H (MMC_REG_STAT);
if ((status & mask) != 0)
done = 1;
}
while (done == 0);
return done;
}
Uint16
MMC_sendCmd (Uint16 cmd, Uint16 argh, Uint16 argl, Uint16 waitForRsp)
{
//clear the MMCSTAT register of its previous value
MMC_RSET_H (MMC_REG_STAT, 0xFFFF);
// Format and send command
MMC_RSET_H (MMC_REG_ARGH, argh);
MMC_RSET_H (MMC_REG_ARGL, argl);
MMC_RSET_H (MMC_REG_CMD, cmd);
// Wait for response done
if (waitForRsp)
{
MMC_waitForFlag (MMC_MMCSTAT_EOC | MMC_MMCSTAT_CMD_TO);
if (((MMC_RGET_H (MMC_REG_STAT)) & MMC_MMCSTAT_CMD_TO) != 0)
return 0; // command time-out
}
return 1;
}
void
MMC_sendGoIdle (void)
{
//send the initializing sequence to card
MMC_RSET_H (MMC_REG_CMD, MMC_RGET_H (MMC_REG_CMD) | MMC_INIT);
//clear the controller status register
MMC_RSET_H (MMC_REG_STAT, 0xFFFF);
}
Uint16
MMC_sendOpCond (Uint32 hVddMask)
{
Uint16 bootup = 0;
do{
if (card->cardtype == CARD_TYPE_SD) {
MMC_sendCmd (SD_APP_CMD, MMC_STUFF_BITS, MMC_STUFF_BITS, 1); //0x2137
MMC_sendCmd (MMC_SEND_OP_COND, (Uint16) ((hVddMask >> 16) & 0xFFFFu), ((Uint16) (hVddMask & 0xFFFFu)), 1); //0x1329
}
if (card->cardtype == CARD_TYPE_MMC)
MMC_sendCmd (MMC_SEND_OP_COND,(Uint16) ((hVddMask >> 16) & 0xFFFFu),((Uint16) (hVddMask & 0xFFFFu)), 1);
bootup = MMC_RGET_H (MMC_REG_RSP7);
bootup = bootup >> 15;
bootup &= 1;
}
while (bootup == 0);
return 1;
}
void
MMC_getResponse (Uint16 * regs)
{
// Set all response registers //
regs[0] = MMC_RGET_H (MMC_REG_RSP0);
regs[1] = MMC_RGET_H (MMC_REG_RSP1);
regs[2] = MMC_RGET_H (MMC_REG_RSP2);
regs[3] = MMC_RGET_H (MMC_REG_RSP3);
regs[4] = MMC_RGET_H (MMC_REG_RSP4);
regs[5] = MMC_RGET_H (MMC_REG_RSP5);
regs[6] = MMC_RGET_H (MMC_REG_RSP6);
regs[7] = MMC_RGET_H (MMC_REG_RSP7);
}
void
MMC_getCID (struct MMC_CardId *cid)
{
Uint16 regs[8];
MMC_getResponse (regs);
//CRC
cid->CRC = regs[0] & 0xFE; //7:1
//MDT fields
cid->yearCode = (regs[0] >> 8) & 0xF; // 11:8
cid->monthCode = (regs[0] >> 12) & 0xF; // 12:15
//cid->dayCode = regs[1] & 0xF;//19:16
//PSN
cid->MMCv3uniqueID = (Uint32) ((regs[2] << 16) | regs[1]); //47:16
cid->SDuniqueID = (Uint32) (((regs[3] & 0xFF) << 16) | ((regs[2] << 8) & 0xFFFF) | ((regs[1] >> 8) & 0xFF)); //55:24
cid->serialNumber[3] = regs[1] & 0xFF;
cid->serialNumber[2] = (regs[1] >> 8) & 0xFF;
cid->serialNumber[1] = regs[2] & 0xFF;
cid->serialNumber[0] = (regs[2] >> 8) & 0xFF;
//PRV
cid->fwRev = regs[3] & 0xF; // 51:48
cid->hwRev = (regs[3] >> 4) & 0xF; // 55:52
//PNM 103:56
cid->productName[5] = ((regs[3]) >> 8) & 0xFF;
cid->productName[4] = ((regs[4]) & 0xFF);
cid->productName[3] = ((regs[4]) >> 8) & 0xFF;
cid->productName[2] = ((regs[5]) & 0xFF);
cid->productName[1] = ((regs[5]) >> 8) & 0xFF;
cid->productName[0] = ((regs[6]) & 0xFF);
//OID 119:104
cid->AppID = ((regs[7] & 0xFF) << 8) | ((regs[6] >> 8) & 0xFF); //119:104;
//MID
cid->mfgId = (regs[7] >> 8) & 0xFF;
};
void
MMC_getCSD (struct MMC_CardCsd *csd)
{
Uint16 lo;
Uint16 regs[8];
MMC_getResponse (regs);
csd->crc = regs[0] & 0xFE; //7:1
//csd->ecc = (regs[0] >> 8 ) & 3; // 9:8
csd->tmpWriteProtect = (regs[0] >> 12) & 1; // 12
csd->permWriteProtect = (regs[0] >> 13) & 1; // 13
csd->copy = (regs[0] >> 14) & 1; // 14
csd->writeBlPartial = (regs[1] >> 5) & 1; // 21
csd->writeBlLen = (regs[1] >> 6) & 0xF; // 25:22
csd->r2wFactor = (regs[1] >> 10) & 0x7; // 28:26
csd->defaultEcc = (regs[1] >> 13) & 0x3; // 30:29
csd->wpGrpEnable = (regs[1] >> 15) & 1; // 31
csd->wpGrpSize = (regs[2] & 0x1F); // 36:32
csd->eraseGrpMult = (regs[2] >> 5) & 0x1f; // 41:37
csd->eraseGrpSize = (regs[2] >> 10) & 0x1f; // 46:42
lo = (regs[2] >> 15) & 1; // 49:47
csd->cSizeMult = ((regs[3] & 3) << 1) | lo;
csd->vddWCurrMax = (regs[3] >> 2) & 0x7; // 52:50
csd->vddWCurrMin = (regs[3] >> 5) & 0x7; // 55:53
csd->vddRCurrMax = (regs[3] >> 8) & 0x7; // 58:56
csd->vddRCurrMin = (regs[3] >> 11) & 0x7; // 61:59
lo = (regs[3] >> 14) & 0x3; // 73:62
csd->cSize = ((regs[4] & 0x3FF) << 2) | lo;
mmc_total_size = (1+csd->cSize)*(1 << (csd->cSizeMult+2))*512;
csd->dsrImp = (regs[4] >> 12) & 1; // 76
csd->readBlkMisalign = (regs[4] >> 13) & 1; // 77
csd->writeBlkMisalign = (regs[4] >> 14) & 1; // 78
csd->readBlPartial = (regs[4] >> 15) & 1; // 79
csd->readBlLen = (regs[5]) & 0xf; // 83:80
csd->ccc = (regs[5] >> 4) & 0xfff; // 95:84
csd->tranSpeed = (regs[6]) & 0xff; // 103:96
csd->nsac = (regs[6] >> 8) & 0xff; // 111:104
csd->taac = (regs[7]) & 0xff; // 119:112
csd->mmcProt = (regs[7] >> 10) & 0xf; // 125:122
csd->csdStructure = (regs[7] >> 14) & 0x3; // 127:126
// extra fields for SD card,make no sense for MMC card
csd->eraseBlkLen = (regs[2] >> 14) & 0x1; //46
csd->eraseSectorSize = (regs[2] >> 7) & 0x7F; //39:45
};
void
SD_getCID (struct MMC_CardId *cid)
{
Uint16 regs[8];
MMC_getResponse (regs);
cid->CRC = regs[0] & 0xFE; //7:1
//MDT fields
cid->yearCode = (regs[0] >> 8) & 0xF; // 11:8
cid->monthCode = (regs[0] >> 12) & 0xF; // 15:12
cid->dayCode = regs[1] & 0xF; //19:16
//reserved = //23:20
//PSN
cid->serialNumber[3] = (regs[1] >> 8) & 0xFF;
cid->serialNumber[2] = regs[2] & 0xFF;
cid->serialNumber[1] = (regs[2] >> 8) & 0xFF;
cid->serialNumber[0] = regs[3] & 0xFF;
//PRV
cid->fwRev = (regs[3] >> 8) & 0xF; // 59:56
cid->hwRev = (regs[3] >> 12) & 0xF; // 63:60
//PNM 103:64
cid->productName[5] = ((regs[4]) & 0xFF);
cid->productName[4] = ((regs[4]) >> 8) & 0xFF;
cid->productName[3] = ((regs[5]) & 0xFF);
cid->productName[2] = ((regs[5]) >> 8) & 0xFF;
cid->productName[1] = ((regs[6]) & 0xFF);
cid->productName[0] = '0';
//OID
cid->AppID = ((regs[7] & 0xFF) << 8) | ((regs[6] >> 8) & 0xFF); //119:104;
//MID
cid->mfgId = (regs[7] >> 8) & 0xFF;
};
Uint16
MMC_initNative (void)
{
volatile int j;
Uint32 RCA = 4;
MMC_RSET_H (MMC_REG_STAT, 0xFFFF); //clear controller status register
MMC_RSET_H (MMC_REG_CMD, 0x10); //send the card init sequence
for (j = 0; j < 2000; j++); //Gsyal investegate the optimal time for waits
//OCR validation
MMC_sendOpCond (0x000f0000); //0x007FC000);
for (j = 0; j < 2000; j++); //Gsyal investegate the optimal time for waits
//CID
MMC_sendCmd (MMC_ALL_SEND_CID, MMC_STUFF_BITS, MMC_STUFF_BITS, 1); //cid0x1242
MMC_getCID (&(card->cidptr));
//RCA
MMC_sendCmd (MMC_SET_RELATIVE_ADDR, (RCA & 0xFFFF), MMC_STUFF_BITS, 0); //rca0x2143
card->cardRCA = RCA;
//CSD
MMC_sendCmd (MMC_SEND_CSD, (RCA & 0xFFFF), MMC_STUFF_BITS, 1); //csd0x2209
for (j = 0; j < 8000; j++); //Gsyal investegate the optimal time for waits
MMC_getCSD (&(card->csdptr));
//select card
MMC_sendCmd (MMC_SELECT_CARD, (RCA & 0xFFFF), MMC_STUFF_BITS, 1); //select card 0x2907
return 1;
};
Uint16
SD_initNative (void)
{
int j;
//OCR
MMC_sendOpCond (0x00ff8000);
//CID
MMC_sendCmd (SD_ALL_SEND_CID, MMC_STUFF_BITS, MMC_STUFF_BITS, 1); // CMD2 R2 (0x1202)
for (j = 0; j < 8000; j++); //Gsyal investegate the optimal time for waits
SD_getCID (&(card->cidptr));
//RCA
MMC_sendCmd (SD_SEND_RELATIVE_ADDR, MMC_STUFF_BITS, MMC_STUFF_BITS, 1); // CMD3 R6 (0x1603)
card->cardRCA = MMC_RGET_H (MMC_REG_RSP7);
//CSD
MMC_sendCmd (MMC_SEND_CSD, card->cardRCA & 0xFFFF, MMC_STUFF_BITS, 1); // CMD9 R2 (0x2209)
for (j = 0; j < 8000; j++); //Gsyal investegate the optimal time for waits
MMC_getCSD (&(card->csdptr));
//select card
MMC_sendCmd (MMC_SELECT_CARD, card->cardRCA & 0xFFFF, MMC_STUFF_BITS, 1); // CMD7 R1b (0x2907)
// Set Data Width
MMC_sendCmd (SD_APP_CMD, card->cardRCA & 0xFFFF, MMC_STUFF_BITS, 1); // CMD55 R1 (0x2137)
// Now the Innovator DK don't support 4-bits bus width, wangjun, 2003-05-07
// MMC_sendCmd (SD_SET_BUS_WIDTH, MMC_STUFF_BITS, 0x2, 1); // ACMD6 R1 (0x2106)
// MMC_FSET_H (MMCCON, DBW, 1); //set bus width to 4-bits in controller
return 1;
};
void MMC_module_init (void)
{
struct MMC_Cfg MyCfg;
int i, j, temp;
card = (struct MMC_Card *) malloc (sizeof (struct MMC_Card));
MyCfg.mmccmd = 0x0000;
MyCfg.mmccon = MMCCON_CLK_400K | MMCCON_NATIVE | MMCCON_DW1;
MyCfg.mmcie = 0x0; //MMC_MMCIE_EOCIE |MMC_MMCIE_ENTR_BSYIE|MMC_MMCIE_BLK_RSIE
//|MMC_MMCIE_EXT_BSYIE| MMC_MMCIE_DAT_TOIE |MMC_MMCIE_DATCRC_ERRIE |
// MMC_MMCIE_CMD_TOIE |MMC_MMCIE_CMDCRC_ERRIE |MMC_MMCIE_BUF_AFIE
// |MMC_MMCIE_BUF_AEIE| MMC_MMCIE_OCR_BSYIE;
MyCfg.mmcdto = MMC_MMCDTO_DIS;
MyCfg.mmccto = MMC_MMCCTO_MAX;
MyCfg.mmcblen = MMC_BLEN_512;
MyCfg.mmcnblk = MMC_MMCNBLK_ONE;
MyCfg.mmcbuf = 0x1f00; // AF_level 0x1F=32 16-bit word(64bytes) AE_level =0
MMC_config (&MyCfg);
MMC_sendGoIdle ();
for (i = 0; i < 1000; i++)
for (j = 0; j < 1000; j++)
{
if (temp == 200)
temp = 100;
}
MMC_sendCmd (SD_APP_CMD, MMC_STUFF_BITS, MMC_STUFF_BITS, 1); //ACMD 55 0x2137
if ((MMC_RGET_H (MMC_REG_RSP6)) == 0x0120)
{ //SD Card is present
card->cardtype = CARD_TYPE_SD;
SD_initNative ();
}
else
{ //MMC Card is present
card->cardtype = CARD_TYPE_MMC;
MMC_initNative ();
}
/*transfer state */
if (card->cardtype == CARD_TYPE_MMC)
{ //set the freq to 16Mhz
temp = MMC_RGET_H (MMC_REG_CON);
temp &= 0xFF00;
temp |= MMCCON_CLK_16M;
MMC_RSET_H (MMC_REG_CON, temp);
}
else if (card->cardtype == CARD_TYPE_SD)
{ //set the freq to 24Mhz
temp = MMC_RGET_H (MMC_REG_CON);
temp &= 0xFF00;
temp |= MMCCON_CLK_24M;
MMC_RSET_H (MMC_REG_CON, temp);
}
MMC_RSET_H (MMC_REG_NBLK, 0x0000); // 1 blk (= single mode)
MMC_RSET_H (MMC_REG_BLEN, (512 - 1));
MMC_sendCmd (MMC_SET_BLOCKLEN, MMC_STUFF_BITS, (512), 0); // CMD16 (SET_BLOCKLEN) R1
printf("MMC: total size is %dM(read out by MMC command)\n",mmc_total_size/(1024*1024));
return;
};
#define OMAP_MOD_CONF_CTRL_0 0xfffe1080 /* module configuration control 0 */
#define OMAP_PULL_DWN_CTRL_2 0xfffe1048 /* pulldown control 2 */
#define OMAP_VOLTAGE_CTRL_0 0xfffe1060 /* voltage control 0 */
void MMC_hw_init (void)
{
(*(unsigned int *) (OMAP_VOLTAGE_CTRL_0)) = 0x0007;
(*(unsigned int *) (OMAP_PULL_DWN_CTRL_2)) |= 0x0001F000;
//The spec sheet says this bit is reserved, but this setting is used in WCSSOFT2 for requiring
(*(unsigned int *) (OMAP_MOD_CONF_CTRL_0)) |= 0x00800000;
//(*(unsigned int *) (OMAP_COMP_MODE_CTRL_0)) = 0x0000EAEF;
*(volatile Uint32*)0xFFFE100C = 0x0000EAEF; //1510 mode
*(volatile Uint8*)0x08000005 |= 0x08; //MMC_EN
*(volatile Uint8*)0x08000210 |= 0x22; //IMR2 mmc CD and ext_FPGA int enabled
}
void MMCtest(void)
{
MMC_hw_init();
MMC_module_init();
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -