📄 mmc.c
字号:
//// $Id: mmc.c 96 2008-10-10 15:29:59Z jcw $// $Revision: 96 $// $Author: jcw $// $Date: 2008-10-10 11:29:59 -0400 (Fri, 10 Oct 2008) $// $HeadURL: http://tinymicros.com/svn_public/arm/lpc2148_demo/trunk/mmc/mmc.c $///************************************************************************* * * Used with ICCARM and AARM. * * (c) Copyright IAR Systems 2005 * * File name : mmc.c * Description : MMC * * History : * 1. Data : July 1, 2005 * Author : Stanimir Bonev * Description : Create * * $Revision: 96 $ * * (C) Joel Winarske, 2006,2007 **************************************************************************/#include <stdio.h>#include "mmc.h"#include "ssp.h"#define MMC_RET_ERROR(Res) do { mmcLastError = Res; return (MmcCardError); } while (0)#define MMC_RET_DATA_ERR(Res) do { mmcLastError = Res; return (MmcDataError); } while (0)#define CSD_GET_TRAN_SPEED_EXP() (mmcSdCsd [ 3] & 0x07)#define CSD_GET_TRAN_SPEED_MANT() ((mmcSdCsd [ 3] & 0xF8) >> 3)#define CSD_GET_NSAC() (mmcSdCsd [ 2])#define CSD_GET_TAAC_EXP() (mmcSdCsd [ 1] & 0x7)#define CSD_GET_TAAC_MANT() ((mmcSdCsd [ 1] & 0xF8) >> 3)#define CSD_GET_R2W_FACTOR() ((mmcSdCsd [12] & 0x1C) >> 2)#define CSD_GET_READ_BL_LEN() (mmcSdCsd [ 5] & 0x0F)#define CSD_GET_C_SIZE() (((mmcSdCsd [ 6] & 0x03) << 10) + (mmcSdCsd [7] << 2) + ((mmcSdCsd [8] & 0xc0) >> 6))#define CSD_GET_C_SIZE_MULT() (((mmcSdCsd [ 9] & 0x03) << 1) + ((mmcSdCsd [10] & 0x80) >> 7))#define CSD_GET_PERM_WRITE_PROTECT() ((mmcSdCsd [14] & 0x20) >> 5)#define CSD_GET_TMP_WRITE_PROTECT() ((mmcSdCsd [14] & 0x10) >> 4)static const U32 mmcTransfExp [] ={ 10000UL, 100000UL, 1000000UL, 10000000UL, 0UL, 0UL, 0UL, 0UL,};static const U32 mmmcAccessTime [] ={ 10000000UL, 1000000UL, 100000UL, 10000UL, 1000UL, 100UL, 10UL, 1UL,};static const U32 mmcCsdMant [] ={ 0UL,10UL,12UL,13UL,15UL, 20UL,25UL, 30UL,35UL, 40UL,45UL, 50UL,55UL, 60UL, 70UL, 80UL,};static const U32 mmcAccessTimeMant [] ={ 0UL,100UL,83UL,77UL,67UL, 50UL,40UL, 33UL,29UL, 25UL,22UL, 20UL,18UL, 17UL, 14UL, 13UL,};static const mmcCommands_t mmcCmd [CMD_END] ={ { 0x40, MmcNoArg, MmcR1 }, // CMD0 { 0x41, MmcNoArg, MmcR1 }, // CMD1 { 0x49, MmcNoArg, MmcR1 }, // CMD9 { 0x4A, MmcNoArg, MmcR1 }, // CMD10 { 0x4C, MmcNoArg, MmcR1 }, // CMD12 { 0x4D, MmcNoArg, MmcR2 }, // CMD13 { 0x50, MmcBlockLen, MmcR1 }, // CMD16 { 0x51, MmcDataAdd, MmcR1 }, // CMD17 { 0x52, MmcDataAdd, MmcR1 }, // CMD18 { 0x58, MmcDataAdd, MmcR1 }, // CMD24 { 0x59, MmcDataAdd, MmcR1 }, // CMD25 { 0x5B, MmcNoArg, MmcR1 }, // CMD27 { 0x5C, MmcDataAdd, MmcR1b}, // CMD28 { 0x5D, MmcDataAdd, MmcR1b}, // CMD29 { 0x5E, MmcDataAdd, MmcR1 }, // CMD30 { 0x60, MmcDataAdd, MmcR1 }, // CMD32 { 0x61, MmcDataAdd, MmcR1 }, // CMD33 { 0x62, MmcDataAdd, MmcR1 }, // CMD34 { 0x63, MmcDataAdd, MmcR1 }, // CMD35 { 0x64, MmcDataAdd, MmcR1 }, // CMD36 { 0x65, MmcDataAdd, MmcR1 }, // CMD37 { 0x66, MmcDummyWord, MmcR1b}, // CMD38 { 0x6A, MmcDummyWord, MmcR1b}, // CMD42 { 0x77, MmcNoArg, MmcR1 }, // CMD55 { 0x78, MmcNoArg, MmcR1 }, // CMD56 { 0x7A, MmcNoArg, MmcR3 }, // CMD58 { 0x7B, MmcDummyWord, MmcR1 }, // CMD59 { 0x69, MmcNoArg, MmcR1 } // ACMD41};static mmcDiskStatus_t mmcDiskStatus;static U32 mmcLastError; static U32 Tnac;static U32 Twr;static U8 mmcSdCsd [16];//////static U32 mmcSendCmd (mmcSpiCmdInd_t commandIndex, U32 arg);static U32 mmcSetBlockLen (U32 length);static void mmcCSDImplement (void);/************************************************************************* * Function Name: mmcSendCmd * Parameters: MmcSpiCmdInd_t commandIndex,U32 arg * * Return: U32 * * Description: MMC commands implemet * *************************************************************************/static U32 mmcSendCmd (mmcSpiCmdInd_t commandIndex, U32 arg){ U32 ch = 0xff; U32 i; // // Chip Select // sspChipSelect (1); // // Send command code // sspTransferByte (mmcCmd [commandIndex].txData); // // Send command's arguments // if (mmcCmd [commandIndex].arg == MmcNoArg) { sspTransferByte (0x00); sspTransferByte (0x00); sspTransferByte (0x00); sspTransferByte (0x00); } else { sspTransferByte (arg >> 24); sspTransferByte (arg >> 16); sspTransferByte (arg >> 8); sspTransferByte (arg); } // // Send CRC // if (commandIndex == CMD0) sspTransferByte (0x95); else sspTransferByte (0xff); for (i = 9; i && (ch == 0xff); --i) ch = sspTransferByte (0xff); if (i == 0) { sspChipSelect (0); return ((U32) -1); } switch (mmcCmd [commandIndex].resp) { case MmcR1b : { U32 busy; for (busy = 0, i = Twr; i && (busy != 0xff); --i) busy = sspTransferByte (0xff); } return (ch); case MmcR1 : return (ch); case MmcR2 : arg = ((U32) ch << 8) & 0x0000ff00; arg |= sspTransferByte (0xff) & 0xff; return (arg); case MmcR3 : default: arg = ((U32) ch << 24) & 0xff000000; arg |= ((U32) sspTransferByte (0xff) << 16) & 0x00ff0000; arg |= ((U32) sspTransferByte (0xff) << 8 ) & 0x0000ff00; arg |= sspTransferByte (0xff) & 0xff; return (arg); }}/************************************************************************* * Function Name: mmcSetBlockLen * Parameters: U32 length * * Return: U32 * * Description: Set Block length Return command's result * *************************************************************************/static U32 mmcSetBlockLen (U32 length){ U32 res = mmcSendCmd (CMD16, length); sspChipSelect (0); return (res);}/************************************************************************* * Function Name: mmcCSDImplement * Parameters: none * * Return: none * * Description: Implemet data from CSD * *************************************************************************/static void mmcCSDImplement (void){ U32 frequency; // // Calculate SPI max clock // frequency = mmcTransfExp [CSD_GET_TRAN_SPEED_EXP ()] * mmcCsdMant [CSD_GET_TRAN_SPEED_MANT ()]; if (frequency > 20000000) frequency = 20000000; frequency = sspSetClockFreq (frequency); if (mmcDiskStatus.diskType == DISKTYPE_MMC) { Tnac = mmmcAccessTime [CSD_GET_TAAC_EXP ()] * mmcAccessTimeMant [CSD_GET_TAAC_MANT ()]; Tnac = frequency / Tnac; Tnac += 1 << (CSD_GET_NSAC () + 4); Tnac *= 10; Twr = Tnac * CSD_GET_R2W_FACTOR (); } else { Tnac = frequency / SD_READ_TIME_OUT; Twr = frequency / SD_WRITE_TIME_OUT; } mmcDiskStatus.blockSize = 1 << CSD_GET_READ_BL_LEN (); mmcDiskStatus.blockNumber = (CSD_GET_C_SIZE () + 1) * (4 << CSD_GET_C_SIZE_MULT ()); mmcDiskStatus.writeProtect = sspHardwareWriteProtected () | CSD_GET_PERM_WRITE_PROTECT () | CSD_GET_TMP_WRITE_PROTECT ();}//////BOOL mmcWriteProtect (void){ return mmcDiskStatus.writeProtect;}BOOL mmcWaitReady (void){ return sspWaitReady () == 0xff;}BOOL mmcCardPresent (void){ return sspHardwareCardPresent ();}/************************************************************************* * Function Name: mmcReadCardInfo * Parameters: U8 *pData, * mmcSpiCmdInd_t command - CMD9, CMD10 are only allowed * * Return: mmcState_t * * Description: Read CSD or CID registers depending on command * *************************************************************************/mmcState_t mmcReadCardInfo (U8 *pData, mmcSpiCmdInd_t command){ U32 i; U32 res; switch (command) { case CMD9 : case CMD10 : break; default: return (MmmcParameterError); } sspChipSelect (0); sspTransferByte (0xff); if ((res = mmcSendCmd (command, 0)) == MMC_OK) { for (i = 8; i ; --i) { if (((res = sspTransferByte (0xff)) | MMC_DATA_ERR_TOKEN) == MMC_DATA_ERR_TOKEN) MMC_RET_DATA_ERR (res); else if (res == MMC_DATA_TOKEN) { for (i = 0; i <16 ; ++i) *pData++ = sspTransferByte (0xff); // // CRC receive // sspTransferByte (0xff); sspTransferByte (0xff); sspChipSelect (0); return (MmcOk); } } } sspChipSelect (0); MMC_RET_ERROR (res);}/************************************************************************* * Function Name: mmcRead * Parameters: U8 *pData, U32 address, U32 length * * Return: mmcState_t * * Description: Read from a MMC * *************************************************************************/mmcState_t mmcRead (U8 *pData, U32 address, U32 length){ U32 res; U32 i; // // Sector number is what is actually passed in, along with the number // of sectors. Convert this to an address and length, in bytes. // address *= mmcDiskStatus.blockSize; length *= mmcDiskStatus.blockSize; // // For synchronization // sspChipSelect (0); sspTransferByte (0xff); res = mmcSendCmd (CMD17, address); if (res == MMC_OK) { for (i = Tnac; i; --i) { res = sspTransferByte (0xff); if ((res | MMC_DATA_ERR_TOKEN) == MMC_DATA_ERR_TOKEN) MMC_RET_DATA_ERR (res); else if (res == MMC_DATA_TOKEN) { sspReceiveBlock (pData, length); // // CRC receive // sspTransferByte (0xff); sspTransferByte (0xff); sspChipSelect (0); return (MmcOk); } } sspChipSelect (0); return (MmcNoResponse); } sspChipSelect (0); MMC_RET_ERROR (res);}/*************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -