📄 mmc_hardware.c
字号:
/****************************************************** * * MMC interface routines. * * (C) 2005 - Tom Walsh tom@openhardware.net * *******************************************************/#include <LPC21xx.h>#include <types.h>#include <mmc_hardware.h>#include <spi.h>#include <sysdefs.h>#include <time.h>#include <rdcf2.h>#include <sysdefs.h>#ifdef HAS_MMC#define MMC_CMD_SIZE 8uchar MMCCmd[MMC_CMD_SIZE];uchar cmdReset [] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x95 };uchar cmdInitCard [] = { 0x41, 0x00, 0x00, 0x00, 0x00, 0xFF };uchar cmdSetBlock [] = { CMD16, 0, 0, 2, 0, 0xff };/****************************************************** * * EXT2 routines to detect card insertion / removal *******************************************************//****************************************************** * * spi1Init - transport media to communicate with * the Flash drive. *******************************************************/void spi1Init (void){// setup basic operation of the SPI1 controller. // set pins for SPI1 operation. PINSEL1 = (PINSEL1 & ~SSP_PINMASK) | SSP_PINSEL; // set clock rate to approx 3.93MHz (58.98MHz / 15); SSPCPSR = 2; // just turn on master mode for now. // clock is rising edge, pre-drive data bit before clock. // Most significant bit shifted out first. SSPCR0 = (SSP_DATA_SIZE(8) | SSP_FRAME_FORMAT_SPI); SSPCR1 = SSP_SSE;}/****************************************************** * * selectMMC and unselectMMC * * board specific routines to communicate with MMC. *******************************************************/static unsigned char dummyReader;static void selectMMC (void){// select SPI target and light the LED. IO0CLR = MMC_CS_BIT; // set SS = 1 (off) IO1CLR = LED_MMC_BIT;}static void unselectMMC (void){// unselect SPI target and extinguish the LED. IO0SET = MMC_CS_BIT; // set SS = 1 (off) IO1SET = LED_MMC_BIT;}static void spiPutByte(uchar inBuf){// spit a byte of data at the MMC. SSPDR = (REG16) inBuf; while (SSPSR & SSP_BSY); // dummy read clears SPI BSY flag on LPC2xxx processors. dummyReader = (uchar) SSPDR;}static uchar spiGetByte(void){// read one byte from the MMC card. SSPDR = (REG16) 0xff; while (SSPSR & SSP_BSY); return (uchar) SSPDR;}/*************************************************************** * * SPI_Send * * Send N bytes from buf into SPI * ***************************************************************/static void SPI_Send(const uchar *buf, long Length ){ uchar Dummy; if ( Length == 0 ) return; while ( Length != 0 ) { /* as long as TNF bit's set, TxFIFO isn縯 full, write */ while ( !(SSPSR & 0x02) ); SSPDR = *buf; /* Wait until the Busy bit is cleared */ while ( !(SSPSR & 0x04) ); Dummy = SSPDR; /* Flush the RxFIFO */ Length--; buf++; } return;}/*************************************************************** * * SPI_Read * * Reads N bytes into buffer ****************************************************************/static void SPI_Read (uchar *buf, long Length){int i; for (i=0; i<Length; i++) { SSPDR = (REG16) 0xff; while (SSPSR & SSP_BSY); buf[i] = SSPDR; }}/****************************************************** * * mmcStatus * * get response status byte and see if it matches * what we are looking for. * return True if we DID get what we wanted. *******************************************************/static bool mmcStatus(uchar response){int count = 4000;uchar resultStatus; resultStatus = ~response; while (resultStatus != response && --count) resultStatus = spiGetByte(); return (count != 0); // loop was exited before timeout}/****************************************************** * * mmcInit * * condition MMC for operation * * Returns True if all went well or False if not good. *******************************************************/bool mmcInit(void){unsigned int count;bool result; unselectMMC(); for (count = 0; count < 10; count++) spiPutByte(0xFF); selectMMC(); SPI_Send (cmdReset, 6); if (mmcStatus(StatusIdle) == False) { unselectMMC(); spiGetByte(); return False; } count = 255; do { SPI_Send (cmdInitCard, 6); count--; } while ((!mmcStatus(0x00)) && (count > 0)); unselectMMC(); spiGetByte(); if (count == 0) return False; selectMMC(); SPI_Send (cmdSetBlock, 6); result = mmcStatus(0x00); unselectMMC(); spiGetByte(); return result;}/****************************************************** * * mmcReadBlock * * called with: * sector number to read, target buffer addr * offset into sector and number of bytes read. * * return True on error, False if all went well. *******************************************************/bool mmcReadBlock(long sector, uchar * buf){ sector <<= 1; selectMMC(); MMCCmd [0] = CMD17; MMCCmd [1] = (sector>>16) & 0xff; MMCCmd [2] = (sector>>8) & 0xff; MMCCmd [3] = sector & 0xff; MMCCmd [4] = 0; MMCCmd [5] = 0xff; SPI_Send (MMCCmd, 6); if (mmcStatus(0x00)) { // get the data token for single block read. if (mmcStatus(0xFE)) { SPI_Read (buf, RDCF_SECTOR_SIZE); // read off, and discard, CRC bytes. spiGetByte(); spiGetByte(); } else { unselectMMC(); spiGetByte(); return True; } } else { unselectMMC(); spiGetByte(); return True; } unselectMMC(); spiGetByte(); return False;}/****************************************************** * * getWriteResultCode * * MMC will be busy (0xff), wait until status code * comes back and return that *******************************************************/static uchar getWriteResultCode (void){int count = 60000l;uchar result = 0; while (result == 0 && --count) result = spiGetByte(); return result;}/****************************************************** * * mmcWriteBlock * * called with: * sector to write and source buffer. * this always writes RDCF_SECTOR_SIZE chunks of one sector * * returns True on error, False if all went well. *******************************************************/bool mmcWriteBlock(long sector, const uchar * buf){int result = 0; sector <<= 1; selectMMC(); MMCCmd [0] = CMD24; MMCCmd [1] = (sector>>16) & 0xff; MMCCmd [2] = (sector>>8) & 0xff; MMCCmd [3] = sector & 0xff; MMCCmd [4] = 0; MMCCmd [5] = 0xff; SPI_Send (MMCCmd, 6); if (mmcStatus(0x00)) { // send data token for single block write. spiPutByte(0xFE); SPI_Send (buf, RDCF_SECTOR_SIZE); // dummy the CRC. spiPutByte(0xff); spiPutByte(0xff); // next we see if all went well. result = spiGetByte(); if ((result & 0xf) != StatusDataAccepted) { // something went wrong with block write. unselectMMC(); spiGetByte(); return True; } } else { // failed to get "ok" for CMD24. unselectMMC(); spiGetByte(); return True; } // wait for operation to complete itself. // we wait until the card is no longer busy. result = getWriteResultCode(); // no longer busy, proceed. unselectMMC(); spiGetByte(); return False;}#endif // HAS_MMC// vi:nowrap:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -