⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.c

📁 最新的LPC214X MMC驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
////  $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 + -