📄 mmc.c
字号:
case MMC_SEND_OP_COND : WriteStr_uart0("MMC_SEND_OP_COND");
break;
case MMC_ALL_SEND_CID : WriteStr_uart0("MMC_ALL_SEND_CID");
break;
case MMC_SET_RELATIVE_ADDR : WriteStr_uart0("MMC_SET_RELATIVE_ADDR");
break;
case MMC_SWITCH : WriteStr_uart0("MMC_SWITCH");
break;
case MMC_SEND_CSD : WriteStr_uart0("MMC_SEND_CSD");
break;
case MMC_SEND_CID : WriteStr_uart0("MMC_SEND_CID");
break;
case MMC_READ_DAT_UNTIL_STOP : WriteStr_uart0("MMC_READ_DAT_UNTIL_STOP");
break;
case MMC_STOP_TRANSMISSION : WriteStr_uart0("MMC_STOP_TRANSMISSION");
break;
case MMC_SEND_STATUS : WriteStr_uart0("MMC_SEND_STATUS");
break;
case MMC_GO_INACTIVE_STATE : WriteStr_uart0("MMC_GO_INACTIVE_STATE");
break;
case MMC_SET_BLOCKLEN : WriteStr_uart0("MMC_SET_BLOCKLEN");
break;
case MMC_READ_SINGLE_BLOCK : WriteStr_uart0("MMC_READ_SINGLE_BLOCK");
break;
case MMC_READ_MULTIPLE_BLOCK : WriteStr_uart0("MMC_READ_MULTIPLE_BLOCK");
break;
case MMC_WRITE_DAT_UNTIL_STOP : WriteStr_uart0("MMC_WRITE_DAT_UNTIL_STOP");
break;
case MMC_SET_BLOCK_COUNT : WriteStr_uart0("MMC_SET_BLOCK_COUNT");
break;
case MMC_WRITE_BLOCK : WriteStr_uart0("MMC_WRITE_BLOCK");
break;
case MMC_WRITE_MULTIPLE_BLOCK : WriteStr_uart0("MMC_WRITE_MULTIPLE_BLOCK");
break;
case MMC_PROGRAM_CSD : WriteStr_uart0("MMC_PROGRAM_CSD");
break;
case MMC_SET_WRITE_PROT : WriteStr_uart0("MMC_SET_WRITE_PROT");
break;
case MMC_CLR_WRITE_PROT : WriteStr_uart0("MMC_CLR_WRITE_PROT");
break;
case MMC_SEND_WRITE_PROT : WriteStr_uart0("MMC_SEND_WRITE_PROT");
break;
case MMC_TAG_SECTOR_START : WriteStr_uart0("MMC_TAG_SECTOR_START");
break;
case MMC_TAG_SECTOR_END : WriteStr_uart0("MMC_TAG_SECTOR_END");
break;
case MMC_UNTAG_SECTOR : WriteStr_uart0("MMC_UNTAG_SECTOR");
break;
case MMC_TAG_ERASE_GROUP_START : WriteStr_uart0("MMC_TAG_ERASE_GROUP_START");
break;
case MMC_TAG_ERARE_GROUP_END : WriteStr_uart0("MMC_TAG_ERARE_GROUP_END");
break;
case MMC_UNTAG_ERASE_GROUP : WriteStr_uart0("MMC_UNTAG_ERASE_GROUP");
break;
case MMC_ERASE : WriteStr_uart0("MMC_ERASE");
break;
case MMC_LOCK_UNLOCK : WriteStr_uart0("MMC_LOCK_UNLOCK");
break;
case MMC_APP_CMD : WriteStr_uart0("MMC_APP_CMD");
break;
case MMC_GEN_CMD : WriteStr_uart0("MMC_GEN_CMD");
break;
case MMC_READ_OCR : WriteStr_uart0("MMC_READ_OCR");
break;
case MMC_CRC_ON_OFF : WriteStr_uart0("MMC_CRC_ON_OFF");
break;
default : WriteStr_uart0("MMC_UNKNOWN_COMMAND ");
sprintf(s, "[%u]", cmd);
WriteStr_uart0(s);
break;
}
WriteStr_uart0(" ..");
#endif
#ifdef mmc_use_crc
crc = 0; // initialize the crc
#endif
// memset(&cmd_buf, 0, sizeof(cmd_buf));
cmd_buf[0] = 0x40 | cmd;
cmd_buf[1] = arg >> 24;
cmd_buf[2] = arg >> 16;
cmd_buf[3] = arg >> 8;
cmd_buf[4] = arg >> 0;
for (i = 0; i < sizeof(cmd_buf) - 1; i++)
{
b = cmd_buf[i]; // get command byte
SPI_SendByte(b); // send command byte
#ifdef mmc_use_crc
crc = mmc_update_crc7(crc, b); // calculate the crc while the byte is being sent
#endif
b = SPI_WaitForTxGetRx(); // wait for the byte to be sent
}
#ifdef mmc_use_crc
crc = (crc << 1) | 0x01;
#else
crc = 0xff;
if (cmd == MMC_GO_IDLE_STATE) crc = 0x95;
#endif
cmd_buf[sizeof(cmd_buf) - 1] = crc; // the calculated crc byte
SPI_SendByte(crc); // send command crc byte
#ifdef mmc_debug1
for (i = 0; i < sizeof(cmd_buf); i++)
{
sprintf(s, " %02X", cmd_buf[i]);
WriteStr_uart0(s);
}
#endif
#ifdef mmc_debug
WriteStr_uart0("\r\n");
#endif
b = SPI_WaitForTxGetRx(); // wait for crc byte to be sent
return mmc_get_response(0xff, false, res_time); // wait for response (ie, anything but a 0xff)
}
static int mmc_send_cmd2(_u8 cmd, _u32 arg, int attempts, bool stuff_byte)
{
T_MMC_Info *mmc_info = (T_MMC_Info*)&MMC_Info;
int i, j;
#ifdef mmc_debug
char s[48];
#endif
if (attempts < 1) attempts = 1;
#ifdef mmc_debug
sprintf(s, "\r\nmax attempts: %u ..\r\n", j);
WriteStr_uart0(s);
#endif
for (j = attempts; j > 0; j--)
{
i = mmc_send_cmd(cmd, arg, mmc_info->spi_sclk_speed >> 13); // send command - monitor next 'nn' bytes for a non 0xff byte
if (i < 0) continue; // time-out/error
if (stuff_byte) SPI_8(0xff); // stuff byte
if (i == 0x00) return mmc_ok; // success!
if (!stuff_byte) SPI_8(0xff); // stuff byte
#ifdef mmc_debug
mmc_show_r1("mmc error:", i);
#endif
}
// timeout/error
if (i < 0)
return i;
else
return mmc_err_fail;
}
static int mmc_get_status(void)
{ // read the MMC status register (R1 & R2)
int i;
_u8 r1, r2;
#ifdef mmc_debug
char s[48];
#endif
#ifdef mmc_debug
WriteStr_uart0("\r\n");
#endif
i = mmc_send_cmd(MMC_SEND_STATUS, 0, 40); // send command
if (i < 0)
{ // time-out/error
#ifdef mmc_debug
WriteStr_uart0("mmc_get_status_error\r\n");
#endif
return i;
}
r1 = (_u8)i; // save R1 result
r2 = SPI_8(0xff); // read R2 result
SPI_8(0xff);
#ifdef mmc_debug1
sprintf(s, "mmc_res: %0.2X\r\n", r2);
WriteStr_uart0(s);
#endif
#ifdef mmc_debug
sprintf(s, "mmc status .. R1: %0.2X .. R2: %0.2X\r\n", r1, r2);
WriteStr_uart0(s);
mmc_show_r1("mmc status:", r1);
mmc_show_r2("mmc status:", r2);
#endif
return (((int)r2 << 8) | r1); // return the 2 status bytes as a word
}
static int mmc_write_data(_u8 cmd, _u32 arg, void *buffer, int data_length)
{ // write a block of data to the MMC (registers, sectors etc)
T_MMC_Info *mmc_info = (T_MMC_Info*)&MMC_Info;
int i;
#ifdef mmc_use_crc
_u16 crc;
#endif
_u16 w;
_u8 b;
_u8 *buf;
#ifdef mmc_debug1
int j = 0;
char s[48];
#endif
if (!mmc_inserted()) return mmc_err_not_inserted; // mmc not inserted
if (data_length < 1) return mmc_err_invalid_data_size; // hmmmm
// **********************
// get current status before we attempt the data write - just to check the MMC is in a ready state
w = mmc_get_status();
if (w != 0)
{
#ifdef mmc_debug
WriteStr_uart0("mmc_write_data_error 1\r\n");
#endif
return mmc_err_invalid_state;
}
// **********************
// send command
i = mmc_send_cmd2(cmd, arg, 5, false); // send command
if (i < 0)
{ // time-out/error
#ifdef mmc_debug
WriteStr_uart0("mmc_write_data_error 2\r\n");
#endif
return i;
}
// *********************
// send data token
#ifdef mmc_debug1
sprintf(s, "mmc_send: %0.2X (data token)\r\n", MMC_STRT_SINGLE_BLK_WR);
WriteStr_uart0(s);
#endif
b = SPI_8(MMC_STRT_SINGLE_BLK_WR); // send data token byte
#ifdef mmc_debug1
sprintf(s, "mmc_res: %0.2X\r\n", b);
WriteStr_uart0(s);
#endif
// *********************
// write data to MMC
#ifdef mmc_use_crc
crc = 0; // init our crc
#endif
buf = (_u8*)buffer;
for (i = data_length; i > 0; i--)
{
// if (!mmc_inserted()) return mmc_err_not_inserted; // mmc not inserted
b = *buf++; // get data byte
SPI_SendByte(b); // send the data byte
#ifdef mmc_use_crc
crc = mmc_update_crc16(crc, b); // calculate our crc while the byte is being sent
#endif
#ifdef mmc_debug1
if (j <= 0)
{
WriteStr_uart0("mmc_send:");
j = 0;
}
sprintf(s, " %0.2X", b);
WriteStr_uart0(s);
j++;
if (j >= 32)
{
WriteStr_uart0("\r\n");
j = 0;
}
#endif
b = SPI_WaitForTxGetRx(); // wait for byte to be sent and get rx'ed byte
if (b != 0xff)
{ // error ????
}
}
#ifdef mmc_debug1
if (j > 0)
{
WriteStr_uart0("\r\n");
j = 0;
}
#endif
#ifdef mmc_use_crc
w = crc; // proper crc word
#else
w = 0xffff; // blank crc word
#endif
#ifdef mmc_debug1
sprintf(s, "mmc_send: %0.2X %0.2X (crc)\r\n", w >> 8, w & 0x00ff);
WriteStr_uart0(s);
#endif
w = SPI_16(w); // send crc word
// *********************
// get response
i = mmc_get_response(0xff, false, mmc_info->spi_sclk_speed >> 9); // wait for a non 0xff byte
// wait for upto 15ms
i = (i >> 1) & 0x07;
#ifdef mmc_debug
switch (i)
{
case MMC_DR_ACCEPT : WriteStr_uart0("(Data accepted)\r\n");
break;
case MMC_DR_REJECT_CRC : WriteStr_uart0("(Data rejected due to a CRC error)\r\n");
break;
case MMC_DR_REJECT_WRITE_ERROR : WriteStr_uart0("(Data Rejected due to a Write Error)\r\n");
break;
default : WriteStr_uart0("(Unknown write data response)\r\n");
break;
}
#endif
if (i != MMC_DR_ACCEPT)
{ // error
SPI_8(0xff);
#ifdef mmc_debug
WriteStr_uart0("mmc write data error 3\r\n");
#endif
return mmc_err_write;
}
// *********************
// wait until MMC has finished writing the data.
// we are waiting for the mmc/sd to write the data to it's NAND flash that we sent to it's internal buffer
// i = mmc_get_response(0x00, false, mmc_info->spi_sclk_speed >> 4); // wait for a non 0x00 byte
// // wait for upto 500ms
i = mmc_get_response(0x00, false, mmc_info->max_write_timeout_count); // wait for a non 0x00 byte
SPI_8(0xff);
if (i < 0 || i == 0x00)
{ // time out/card not inserted
#ifdef mmc_debug
if (i == 0x00)
WriteStr_uart0("mmc_write_data_error time-out\r\n");
else
WriteStr_uart0("mmc_write_data_error 4\r\n");
#endif
return mmc_err_write;
}
// *********************
return mmc_ok;
}
static int mmc_read_data(_u8 cmd, _u32 arg, void *buffer, int data_length)
{ // read data from the MMC (registers, sectors etc)
T_MMC_Info *mmc_info = (T_MMC_Info*)&MMC_Info;
register int i;
register _u8 b1;
register _u8 *buf;
_u16 crc2, w;
#ifdef mmc_use_crc
register _u16 crc1;
#endif
#ifdef mmc_debug
char s[56];
#ifdef mmc_debug1
int j = 0;
#endif
#endif
if (!mmc_inserted()) return mmc_err_not_inserted; // mmc not inserted
if (data_length <= 0) return mmc_err_invalid_data_size; // hmmmm
// **********************
// get current status before we start a read off
w = mmc_get_status();
if (w != 0)
{
#ifdef mmc_debug
WriteStr_uart0("mmc_read_data_error 1\r\n");
#endif
return mmc_err_invalid_state;
}
// **********************
// send command
i = mmc_send_cmd2(cmd, arg, 5, false); // send command
if (i < 0)
{ // time-out/error
#ifdef mmc_debug
WriteStr_uart0("mmc_read_data_error 2\r\n");
#endif
return i;
}
// **********************
// wait for data token.
// we are waiting for the mmc/sd to read the sector data from it's NAND flash into it's own internal buffer.
// i = mmc_get_response(0xff, false, mmc_info->spi_sclk_speed >> 5); // wait for a non 0xff byte
// // wait for upto 250ms
i = mmc_get_response(0xff, false, mmc_info->max_read_timeout_count); // wait for a non 0xff byte
if (i != MMC_SINGLE_BLK_RD)
{ // timeout/error
SPI_8(0xff);
#ifdef mmc_debug
if (i >= 0)
{
if (i & MMC_DE_MISALIGN) WriteStr_uart0("mmc MISALIGN\r\n");
if (i & MMC_DE_ADDR_OUT_OF_RANGE) WriteStr_uart0("mmc ADDR OUT-OF_RANGE\r\n");
if (i & MMC_DE_CARD_EEC_FAIL) WriteStr_uart0("mmc CARD ECC FAIL\r\n");
if (i & MMC_DE_CARD_ERROR) WriteStr_uart0("mmc CARD ERROR\r\n");
if (i & MMC_DE_EX_ERROR) WriteStr_uart0("mmc EX ERROR\r\n");
}
WriteStr_uart0("mmc_read_data_error 3\r\n");
#endif
if (i < 0)
return i;
else
return mmc_err_read;
}
// **********************
// read the data out of the mmc/sd
#ifdef mmc_use_crc
crc1 = 0; // init our crc
#endif
buf = (_u8*)buffer;
SPI_SendByte(0xff); // send a null byte
for (i = data_length; i > 0; i--)
{
// if (!mmc_inserted()) return mmc_err_not_inserted; // mmc not inserted
// while (!(S0SPSR & S0SPSR_SPIF)); // wait for byte to be sent
// b1 = S0SPDR; // get the rx'ed byte
b1 = SPI_WaitForTxGetRx(); // wait for byte to be sent and get rx'ed byte
// S0SPDR = 0xff; // send byte
SPI_SendByte(0xff); // send a null byte
*buf++ = b1; // save rx'ed data byte
#ifdef mmc_use_crc
crc1 = mmc_update_crc16(crc1, b1); // calculate our crc while the byte is being sent
#endif
#ifdef mmc_debug1
if (j <= 0)
{
WriteStr_uart0("mmc_read:");
j = 0;
}
sprintf(s, " %0.2X", b1);
WriteStr_uart0(s);
j++;
if (j >= 32)
{
WriteStr_uart0("\r\n");
j = 0;
}
#endif
}
#ifdef mmc_debug1
if (j > 0) WriteStr_uart0("\r\n");
#endif
crc2 = (_u16)SPI_WaitForTxGetRx() << 8; // wait for byte to be sent and get rx'ed byte
crc2 |= (_u16)SPI_8(0xff); // send byte, wait for it to be sent and get rx'ed byte
#ifdef mmc_debug1
sprintf(s, "mmc_read: %0.2X %0.2X (crc)\r\n", crc2 >> 8, crc2 & 0x00ff);
WriteStr_uart0(s);
#endif
b1 = SPI_8(0xff);
#ifdef mmc_use_crc
if (crc1 != crc2)
{ // crc mismatch
#ifdef mmc_debug
sprintf(s, "mmc crc16 error .. our crc: %0.4X there crc: %0.4X\r\n", crc1, crc2);
WriteStr_uart0(s);
#endif
return mmc_err_crc;
}
#endif
// **********************
return mmc_ok;
}
static int mmc_idle_state(void)
{ // put the MMC in idle state
T_MMC_Info *mmc_info = (T_MMC_Info*)&MMC_Info;
int i, j;
#ifdef mmc_debug
char s[48];
#endif
j = mmc_info->spi_sclk_speed >> 11;
if (j < 1) j = 1;
#ifdef mmc_debug
sprintf(s, "\r\nmax attempts: %u\r\n", j);
WriteStr_uart0(s);
#endif
for ( ; j > 0; j--)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -