📄 mmc.c
字号:
//*****************************************************************************//// Author : Pascal Stang - Copyright (C) 2004// Modified : Tony Ward, Cyan Technology, March 2006//// This code is distributed under the GNU Public License// which can be found at http://www.gnu.org/licenses/gpl.txt//// TWard March 2006 - Ported to the eCOG1k Microcontroller under CyanIDE//*****************************************************************************#include <ecog.h>#include <ecog1.h>#include "mmc.h"// include project-specific hardware configuration#include "mmcConf.h"#include "spi.h" // include spi bus support// Functionsvoid mmcInit(void){ MMC_CS_Clr = 1; MMC_CS_En = 1; fd.dusart.spi_frame_ctrl.tx_slave_sel = 0; }unsigned int mmcReset (void){ unsigned int retry; unsigned int r1 = 0; int i; retry = 0; LED0_Clr = 1; // Turn off until we succeed. do { // Enable transmit and receive // NB we need internal CS0 signal for us to receive data without running CS Assert rg.dusart.spi_ctrl = DUSART_SPI_CTRL_RX_EN_MASK | DUSART_SPI_CTRL_TX_EN_MASK; // Specs indicate 74 cycles are required (without CS) before reading fd.dusart.spi_frame_ctrl.tx_slave_sel = 1; // Assert CS0 internally for (i = 0; i < 10; i++) spiTransferByte(0xff); rg.dusart.spi_ctrl = DUSART_SPI_CTRL_RX_DIS_MASK | DUSART_SPI_CTRL_TX_DIS_MASK; fd.dusart.spi_frame_ctrl.tx_slave_sel = 0; // De-assert CS0 internally // resetting card, go to SPI mode r1 = mmcSendCommand(MMC_GO_IDLE_STATE, 0);#ifdef MMC_DEBUG printf("MMC_GO_IDLE_STATE: R1=0x%x\r\n", r1);#endif // do retry counter retry++; if (retry > 10) return -1; } while (r1 != 0x01); // When we arrive here, the reset command has been accepted and we need to wait // for the idle state (LSbit) bit to go low retry = 0; do { // initializing card for operation r1 = mmcSendCommand(MMC_SEND_OP_COND, 0); #ifdef MMC_DEBUG printf("MMC_SEND_OP_COND: R1=0x%x\r\n", r1); #endif // do retry counter // Allow a small delay while between retries waiting for intitialisation for (i = 0; i < 30000; i++) nop(); // approximately 25ms retry++; if (retry > 100) return -1; } while (r1); // Okay, we are now alive and the card is initialised // TODO: check card parameters for voltage compliance // before issuing initialize command // turn off CRC checking to simplify communication r1 = mmcSendCommand(MMC_CRC_ON_OFF, 0);#ifdef MMC_DEBUG printf("MMC_CRC_ON_OFF: R1=0x%x\r\n", r1);#endif // set block length to 512 bytes r1 = mmcSendCommand(MMC_SET_BLOCKLEN, 512);#ifdef MMC_DEBUG printf("MMC_SET_BLOCKLEN: R1=0x%x\r\n", r1);#endif LED0_Set = 1; // We are up and running, turn the LED back on // return success return (0);}unsigned int mmcSendCommand(unsigned int cmd, unsigned long arg){ unsigned int r1; // assert chip select spiAssertCS(); // issue the command r1 = mmcCommand(cmd, arg); // release chip select spiDeassertCS(); return (r1);}unsigned int mmcRead(unsigned long sector, unsigned char *buffer){ unsigned int r1; unsigned int i; // assert chip select // NB an additional step is required to enable CS internally spiAssertCS(); // issue command r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector << 9);#ifdef MMC_DEBUG printf("MMC Read Block R1=0x%x\r\n", r1);#endif // check for valid response if(r1 != 0x00) { spiDeassertCS(); return (r1); } // wait for block start while (spiTransferByte(0xFF) != MMC_STARTBLOCK_READ); // read in data for (i = 0; i < 0x200; i++) { *buffer++ = spiTransferByte(0xFF); } // read 16-bit CRC spiTransferByte(0xFF); spiTransferByte(0xFF); // release chip select spiDeassertCS(); // return success return 0;}unsigned int mmcWrite(unsigned long sector, unsigned char *buffer){ unsigned int r1; unsigned int i; // assert chip select spiAssertCS(); // issue command r1 = mmcCommand(MMC_WRITE_BLOCK, sector<<9);#ifdef MMC_DEBUG printf("MMC Write Block R1=0x%x\r\n", r1);#endif // check for valid response if (r1 != 0x00) { return (r1); spiDeassertCS(); } // send dummy spiTransferByte(0xFF); // send data start token spiTransferByte(MMC_STARTBLOCK_WRITE); // write data for (i = 0; i < 0x200; i++) { spiTransferByte(*buffer++); } // write 16-bit CRC (dummy values) spiTransferByte(0xFF); spiTransferByte(0xFF); // read data response token r1 = spiTransferByte(0xFF); if ((r1&MMC_DR_MASK) != MMC_DR_ACCEPT) { spiDeassertCS(); return (r1); }#ifdef MMC_DEBUG printf("Data Response Token=0x%x\r\n", r1);#endif // wait until card not busy while(!spiTransferByte(0xFF)); // release chip select spiDeassertCS(); // return success return (0);}unsigned int mmcCommand(unsigned int cmd, unsigned long arg){ unsigned int r1; unsigned int retry = 0; // send command spiTransferByte(cmd | 0x40); spiTransferByte(arg >> 24); spiTransferByte(arg >> 16); spiTransferByte(arg >> 8); spiTransferByte(arg); spiTransferByte(0x95); // crc valid only for MMC_GO_IDLE_STATE // end command // wait for response // if more than 8 retries, card has timed-out // return the received 0xFF while ((r1 = spiTransferByte(0xFF)) == 0xFF) { if (retry++ > 8) break; } // Add an additonal 8 clock ticks to finish off work (SD card specs) spiTransferByte(0xff); // return response return (r1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -