Added Software projects
git-svn-id: file:///srv/dev-disk-by-uuid-17e88007-4d0c-45e0-8757-cacfcc458630/repositories/svn/Diplomarbeit@55 9fe90eed-be63-e94b-8204-d34ff4c2ff93
This commit is contained in:
@@ -0,0 +1,810 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
* mmc.c (c) 2008 Micro-key bv
|
||||
* ---------------------------------------------------------------------------
|
||||
* Micro-key bv
|
||||
* Industrieweg 28, 9804 TG Noordhorn
|
||||
* Postbus 92, 9800 AB Zuidhorn
|
||||
* The Netherlands
|
||||
* Tel: +31 594 503020
|
||||
* Fax: +31 594 505825
|
||||
* Email: support@microkey.nl
|
||||
* Web: www.microkey.nl
|
||||
* ---------------------------------------------------------------------------
|
||||
* Description:
|
||||
* ---------------------------------------------------------------------------
|
||||
* Version(s): 0.1, Apr 22, 2008, MMi
|
||||
* Creation.
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* System include files
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
/* Compiler Includes */
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "LPC23xx.h"
|
||||
#include "types.h"
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Application include files
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
#include "mmc.h"
|
||||
#include "mmc_transfer.h"
|
||||
#include "dio.h"
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Local constant and macro definitions
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
#define MMC_GLOBAL
|
||||
|
||||
#define __no_init
|
||||
|
||||
#define CSD_GET_TRAN_SPEED_EXP() (MmcSdCsd[ 0]&0x07)
|
||||
#define CSD_GET_TRAN_SPEED_MANT() ((MmcSdCsd[ 0]&0xF8)>>3 )
|
||||
#define CSD_GET_NSAC() (MmcSdCsd[ 1] )
|
||||
#define CSD_GET_TAAC_EXP() (MmcSdCsd[ 2]&0x7)
|
||||
#define CSD_GET_TAAC_MANT() ((MmcSdCsd[ 2]&0xF8)>>3 )
|
||||
#define CSD_GET_R2W_FACTOR() ((MmcSdCsd[15]&0x1C)>>2 )
|
||||
#define CSD_GET_READ_BL_LEN() (MmcSdCsd[ 6]&0x0F)
|
||||
#define CSD_GET_C_SIZE() (((MmcSdCsd[ 5]&0x03)<<10) + (MmcSdCsd[4]<<2) + ((MmcSdCsd[11]&0xc0)>>6))
|
||||
#define CSD_GET_C_SIZE_MULT() (((MmcSdCsd[10]&0x03)<<1 ) +((MmcSdCsd[9]&0x80)>>7))
|
||||
#define CSD_GET_PERM_WRITE_PROTECT() ((MmcSdCsd[13]&0x20)>>5 )
|
||||
#define CSD_GET_TMP_WRITE_PROTECT() ((MmcSdCsd[13]&0x10)>>4 )
|
||||
|
||||
volatile UINT32 i;
|
||||
|
||||
|
||||
#define SpcInquiryRemovableMedium 0x80
|
||||
#define SpcInquiryStandartVersion 5
|
||||
#define SizeOfInquiryDescMmcDsk 36
|
||||
|
||||
const UINT32 MmcTransfExp[] =
|
||||
{ 10000UL, 100000UL, 1000000UL, 10000000UL, 0UL, 0UL, 0UL, 0UL,
|
||||
};
|
||||
|
||||
const UINT32 MmmcAccessTime [] =
|
||||
{ 1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL,
|
||||
};
|
||||
|
||||
const UINT32 MmcCsdMant[] =
|
||||
{ 0UL, 10UL, 12UL, 13UL, 15UL, 20UL, 25UL, 30UL, 35UL, 40UL, 45UL, 50UL,
|
||||
55UL, 60UL, 70UL, 80UL,
|
||||
};
|
||||
|
||||
const MmcCommads_t MmcCmd[CMD_END] =
|
||||
{ /* {TxData, Arg, Resp} */
|
||||
{ 0x00, MmcNoArg, MmcNoResp }, /* CMD0 */
|
||||
{ 0x01, MmcOcr, MmcR3 }, /* CMD1 */
|
||||
{ 0x02, MmcNoArg, MmcR2 }, /* CMD2 */
|
||||
{ 0x03, MmcRelAddr, MmcR1 }, /* CMD3 */
|
||||
{ 0x07, MmcRelAddr, MmcR1 }, /* CMD7 */
|
||||
{ 0x09, MmcRelAddr, MmcR2 }, /* CMD9 */
|
||||
{ 0x0A, MmcRelAddr, MmcR2 }, /* CMD10 */
|
||||
{ 0x0C, MmcNoArg, MmcR1b }, /* CMD12 */
|
||||
{ 0x0D, MmcRelAddr, MmcR1 }, /* CMD13 */
|
||||
{ 0x10, MmcBlockLen, MmcR1 }, /* CMD16 */
|
||||
{ 0x11, MmcDataAdd, MmcR1 }, /* CMD17 */
|
||||
{ 0x12, MmcDataAdd, MmcR1 }, /* CMD18 */
|
||||
{ 0x18, MmcDataAdd, MmcR1 }, /* CMD24 */
|
||||
{ 0x19, MmcDataAdd, MmcR1 }, /* CMD25 */
|
||||
{ 0x1B, MmcOcr, MmcR1 }, /* CMD27 */
|
||||
{ 0x1C, MmcDataAdd, MmcR1b }, /* CMD28 */
|
||||
{ 0x1D, MmcDataAdd, MmcR1b }, /* CMD29 */
|
||||
{ 0x1E, MmcDataAdd, MmcR1 }, /* CMD30 */
|
||||
{ 0x20, MmcDataAdd, MmcR1 }, /* CMD32 */
|
||||
{ 0x21, MmcDataAdd, MmcR1 }, /* CMD33 */
|
||||
{ 0x22, MmcDataAdd, MmcR1 }, /* CMD34 */
|
||||
{ 0x23, MmcDataAdd, MmcR1 }, /* CMD35 */
|
||||
{ 0x24, MmcDataAdd, MmcR1 }, /* CMD36 */
|
||||
{ 0x25, MmcDataAdd, MmcR1 }, /* CMD37 */
|
||||
{ 0x26, MmcNoArg, MmcR1b }, /* CMD38 */
|
||||
{ 0x2A, MmcNoArg, MmcR1b }, /* CMD42 */
|
||||
{ 0x37, MmcRelAddr, MmcR1 }, /* CMD55 */
|
||||
{ 0x38, MmcNoArg, MmcR1 }, /* CMD56 */
|
||||
{ 0x06, MmcDataAdd, MmcR1 }, /* ACMD46 */
|
||||
{ 0x29, MmcDataAdd, MmcR3 }, /* ACMD41 */
|
||||
};
|
||||
|
||||
const UINT8 MmcDskInquiry[]__attribute__((aligned (4)))=
|
||||
{
|
||||
SbcDirectAccess, /* 0 PERIPHERAL QUALIFIER AND DEVICE*/
|
||||
SpcInquiryRemovableMedium, /* 1 RMB */
|
||||
SpcInquiryStandartVersion, /* 2 VERSION */
|
||||
0x02, /* 3 NORMACA HISUP RESPONSE FORMAT */
|
||||
36-4, /* 4 ADDITIONAL LENGTH (n-4) */
|
||||
0x00, /* 5 SCCS */
|
||||
/* for parallel SCSI only */
|
||||
0x00, /* 6 BQUE ENCSERV VS MULTIP MCHNGR Obsolete Obsolete ADDR16 */
|
||||
0x00, /* 7 RELADR Obsolete WBUS16† SYNC† LINKED Obsolete CMDQUE VS*/
|
||||
'I','A','R',' ','S','y','s','.', /* 8 - 15 VENDOR IDENTIFICATION */
|
||||
/* 16 - 31 PRODUCT IDENTIFICATION */
|
||||
'L','P','C','2','3','7','8',' ','S','t','o','r','a','g','e',' ',
|
||||
'1','.','0','0', /* 32 - 35 PRODUCT REVISION LEVEL */
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Global variable definitions
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
static UINT32 CardRCA;
|
||||
UINT32 MmcLastError;
|
||||
UINT32 dlycnt;
|
||||
UINT32 Tnac;
|
||||
UINT32 Twr;
|
||||
|
||||
UINT8 MmcSdCsd[16]__attribute__ ((aligned (4)));
|
||||
static BOOLEAN bMmcPermWriteProtect;
|
||||
BOOLEAN bMmcChanged;
|
||||
|
||||
DiskCtrlBlk_t MmcDskCtrlBlk;
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Local variable definitions
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Local function definitions
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Function returns TRUE if Card is inserted, FALSE if Card is removed */
|
||||
inline BOOLEAN MmcPresent(void)
|
||||
{
|
||||
return (!(MMC_CP_FIO & MMC_CP_MASK));
|
||||
}
|
||||
|
||||
|
||||
/* Function returns TRUE is WriteProtection is activated, FALSE if
|
||||
* Protection is off. If no Card is inserted, Function will also return
|
||||
* TRUE. This results from the physical Switch Connection (See Datasheet).
|
||||
* Usage of this Function only makes Sense with previous TRUE-Return
|
||||
* from MmcPresent.
|
||||
*/
|
||||
inline BOOLEAN MmcWriteProtect(void)
|
||||
{
|
||||
if (!(MMC_WP_FIO & MMC_WP_MASK))
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 MmcSetClockFreq (UINT32 Frequency)
|
||||
{
|
||||
UINT32 Pclk = SYS_GetFPclk(MCI_PCLK_OFFSET);
|
||||
UINT32 Div;
|
||||
Frequency <<= 1;
|
||||
|
||||
for(Div = 1; Div <= 256; ++Div)
|
||||
{
|
||||
if((Frequency * Div)> Pclk)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
MCI_CLOCK = ((Div - 1) & 0xFF); /* Set Clock Devider (Bit 0-7) */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
MCI_CLOCK |= (1 << 8); /* enable Clock (Bit 8) */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
MCI_CLOCK |= (1 << 9); /* Set PowerSave (Bit 9) */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
|
||||
return(Pclk/(Div<<1)); /* Return real frequency */
|
||||
}
|
||||
|
||||
void MmcInit(void)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
MMC_CP_DIR &= ~MMC_CP_MASK; /* Set CP to Input */
|
||||
MMC_CP_MODE &=~(1 << 24); /* Neither PullUp nor PullDown */
|
||||
MMC_CP_MODE |= (1 << 25);
|
||||
|
||||
MMC_WP_DIR &= ~MMC_WP_MASK; /* Set WP to Input */
|
||||
MMC_WP_MODE &=~(1 << 22); /* Neither PullUp nor PullDown */
|
||||
MMC_WP_MODE |= (1 << 23);
|
||||
|
||||
|
||||
PCLKSEL1 |= (1 << 24); /* set divider to /1 (Bit 24&25) */
|
||||
PCLKSEL1 &=~(1 << 25);
|
||||
|
||||
PCONP |= 0x30000000; /* Set Power up */
|
||||
|
||||
PINSEL1 &=~(1 << 6); /* Assign Pin 0.19 (Bit 6&7) */
|
||||
PINSEL1 |= (1 << 7);
|
||||
PINSEL1 &=~(1 << 8); /* Assign Pin 0.20 (Bit 8&9) */
|
||||
PINSEL1 |= (1 << 9);
|
||||
PINSEL1 &=~(1 << 10); /* Assign Pin 0.21 (Bit 10&11) */
|
||||
PINSEL1 |= (1 << 11);
|
||||
PINSEL1 &=~(1 << 12); /* Assign Pin 0.22 (Bit 12&13) */
|
||||
PINSEL1 |= (1 << 13);
|
||||
PINSEL4 &=~(1 << 22); /* Assign Pin 2.11 (Bit 22&23) */
|
||||
PINSEL4 |= (1 << 23);
|
||||
PINSEL4 &=~(1 << 24); /* Assign Pin 2.12 (Bit 24&25) */
|
||||
PINSEL4 |= (1 << 25);
|
||||
PINSEL4 &=~(1 << 26); /* Assign Pin 2.13 (Bit 26&27) */
|
||||
PINSEL4 |= (1 << 27);
|
||||
|
||||
|
||||
PINMODE1 &=~(1 << 6) & ~(1 << 7); /* Set PullUp Pin 0.19 (Bit 6&7) */
|
||||
PINMODE1 &=~(1 << 8) & ~(1 << 9); /* Set PullUp Pin 0.20 (Bit 8&9) */
|
||||
PINMODE1 &=~(1 << 10) & ~(1 << 11); /* Set PullUp Pin 0.21 (Bit 10&11) */
|
||||
PINMODE1 &=~(1 << 12) & ~(1 << 13); /* Set PullUp Pin 0.22 (Bit 12&13) */
|
||||
|
||||
|
||||
MCI_COMMAND = 0; /* Clear MCI Command Register */
|
||||
MCI_DATA_CTRL = 0; /* Clear MCI Data Control Register */
|
||||
MCI_CLEAR = 0x7FF; /* Clear all pending interrupts. */
|
||||
|
||||
/* Power up, switch on VCC for the Flash Card - Wait shortly */
|
||||
MCI_POWER = 0x02;
|
||||
for (i = 0; i < 50000; i++);
|
||||
|
||||
|
||||
MCI_POWER |= 0x01; /* Power on the Flash Card. */
|
||||
for (i = 0; i < 50000; i++); /* Wait shortly */
|
||||
|
||||
MmcPowerDown();
|
||||
|
||||
GPDMA_SYNC = 0; /* DMA sync enable */
|
||||
GPDMA_INT_ERR_CLR = 3; /* Clear DMA Error Interrupts */
|
||||
GPDMA_INT_TCCLR = 3; /* Clear DMA Interrupts */
|
||||
|
||||
}
|
||||
|
||||
void MmcPowerDown(void)
|
||||
{
|
||||
SCS |= (1 << 3); /* Init Power State (Bit 3) */
|
||||
MCI_POWER = 0;
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
MCI_MASK0 = 0; /* Disable all interrupts for now */
|
||||
MCI_MASK1 = 0;
|
||||
MCI_COMMAND = 0;
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
MCI_DATA_CTRL = 0;
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
MCI_CLEAR = 0x7FF;
|
||||
|
||||
MCI_CLOCK &=~(1 << 11); /* clear all pending interrupts */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
|
||||
MmcSetClockFreq(IdentificationModeClock); /* ClkFreq Ident Mode< 400kHz */
|
||||
}
|
||||
|
||||
|
||||
MmcState_t MmcSendCmd(MmcSpiCmdInd_t ComdInd, pUINT32 pArg)
|
||||
{
|
||||
UINT32 Status;
|
||||
union
|
||||
{
|
||||
UINT32 Data;
|
||||
struct
|
||||
{
|
||||
UINT32 CMDINDEX : 6;
|
||||
UINT32 RESPONSE : 1;
|
||||
UINT32 LONGRSP : 1;
|
||||
UINT32 INTERRUPT : 1;
|
||||
UINT32 PENDING : 1;
|
||||
UINT32 ENABLE : 1;
|
||||
UINT32 :21;
|
||||
};
|
||||
} Command;
|
||||
|
||||
/* The Command engine has to be Disabled when modifying the Argument
|
||||
* of the Peripheral
|
||||
*/
|
||||
while ((MCI_STATUS << 11) == TRUE) /* While a Command is in Progress */
|
||||
{
|
||||
MCI_COMMAND = 0; /* Clear MCI Command Register */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
}
|
||||
Command.Data = 0;
|
||||
|
||||
/* Copy Command-specific Index-Argument from MmcCmd LookUp Table to
|
||||
* Command struct
|
||||
*/
|
||||
Command.CMDINDEX = MmcCmd[ComdInd].TxData;
|
||||
if (pArg != NULL) /* Set Command Response depending on*/
|
||||
{ /* asked Argument */
|
||||
switch (MmcCmd[ComdInd].Resp)
|
||||
{
|
||||
case MmcR2:
|
||||
Command.LONGRSP = 1;
|
||||
case MmcR1:
|
||||
case MmcR1b:
|
||||
case MmcR3:
|
||||
Command.RESPONSE = 1;
|
||||
case MmcNoResp:;
|
||||
}
|
||||
}
|
||||
Command.ENABLE = 1;
|
||||
|
||||
if (MmcCmd[ComdInd].Arg != MmcNoArg) /* If Argument exists */
|
||||
{
|
||||
MCI_ARGUMENT = *pArg; /* Copy Argument to MCI Argument Reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
MCI_ARGUMENT = 0;
|
||||
}
|
||||
|
||||
MCI_COMMAND = Command.Data; /* Send Command to Card */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
while ((Status = MCI_STATUS & 0x000000C5) == 0);/* Wait command respond */
|
||||
|
||||
MCI_CLEAR = Status; /* Clear actual Status */
|
||||
|
||||
if (Status & (1UL << 2)) /* If Command TimeOut occourses */
|
||||
{
|
||||
MCI_COMMAND = 0; /* reset Command Register */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
return (MmcNoResponse); /* Return with Error Message */
|
||||
}
|
||||
if (Status & (1UL << 0)) /* Command CRC Error */
|
||||
{
|
||||
switch (MCI_COMMAND & 0x3F) /* Ignore CRC Error for following */
|
||||
{ /* Commands */
|
||||
case 1: /* CMD1 */
|
||||
case 41: /* ACMD42 */
|
||||
case 12: /* CMD12 */
|
||||
MCI_COMMAND = 0;
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
MCI_ARGUMENT = 0xFFFFFFFF;
|
||||
break;
|
||||
default: /* No CRC Error Ignoring */
|
||||
MCI_COMMAND = 0;
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
return (MmcCardError);
|
||||
}
|
||||
}
|
||||
|
||||
if (pArg != NULL)
|
||||
{
|
||||
switch (MmcCmd[ComdInd].Resp) /* Handle Command Response */
|
||||
{
|
||||
case MmcNoResp:
|
||||
break;
|
||||
case MmcR3:
|
||||
*pArg = MCI_RESP0;
|
||||
break;
|
||||
case MmcR2:
|
||||
*pArg++ = MCI_RESP0;
|
||||
*pArg++ = MCI_RESP1;
|
||||
*pArg++ = MCI_RESP2;
|
||||
*pArg++ = MCI_RESP3;
|
||||
break;
|
||||
default:
|
||||
if (MmcCmd[ComdInd].TxData != (MCI_RESP_CMD & 0x3F)) /* Bit 0-5*/
|
||||
{
|
||||
return (MmcCardError);
|
||||
}
|
||||
*pArg = MCI_RESP0;
|
||||
}
|
||||
}
|
||||
MCI_COMMAND = 0;
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
return (MmcOk);
|
||||
}
|
||||
|
||||
UINT32 Status;
|
||||
MmcState_t MmcInitMedia(void)
|
||||
{
|
||||
UINT32 i;
|
||||
UINT32 res;
|
||||
UINT32 loopcnt;
|
||||
volatile UINT32 Dly;
|
||||
UINT8 MmcSdCid[16];
|
||||
BOOLEAN CardDetected = FALSE;
|
||||
|
||||
Tnac = 1;
|
||||
if (MmcPresent() == FALSE) /* If no Card inserted */
|
||||
{
|
||||
if (MCI_POWER & 0x3) /* Is Power up? */
|
||||
{
|
||||
MmcPowerDown(); /* Set to power down state */
|
||||
}
|
||||
return (MmcNoPresent); /* Return with Error Message */
|
||||
}
|
||||
|
||||
MmcPowerDown(); /* Power Down */
|
||||
MmcDly_1ms(100);
|
||||
|
||||
MCI_POWER &=~(1 << 0); /* power up (Bit 1) */
|
||||
MCI_POWER |= (1 << 1);
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
while ((MCI_POWER & 0x3) != 0x2);
|
||||
|
||||
MCI_POWER |= (1 << 0); /* power reserved (Bit 0) */
|
||||
MCI_POWER &=~(1 << 1);
|
||||
MmcDly_1ms(100);
|
||||
MCI_POWER &=~(1 << 6); /* Disable OpenDrain Mode */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
|
||||
MCI_POWER = 0x02; /* Power up (Bit 1) */
|
||||
for (loopcnt = 0; loopcnt < 50000; loopcnt++);
|
||||
|
||||
MCI_POWER |= 0x01; /* Power on the Flash Card */
|
||||
for (loopcnt = 0; loopcnt < 50000; loopcnt++);
|
||||
|
||||
if (MmcSendCmd(CMD0, NULL) != MmcOk) /* Send Cmd0, Reset Card */
|
||||
{
|
||||
return (MmcNoResponse);
|
||||
}
|
||||
|
||||
MCI_POWER |= 0x40; /* Set OpenDrain output control */
|
||||
|
||||
MmcDskCtrlBlk.DiskType = DiskMMC; /* Determinate Card type SD or MMC */
|
||||
for (i=100; i; --i) /* Try detecting several Times */
|
||||
{
|
||||
MCI_POWER &=~(1 << 6); /* Disable OpenDrain Mode */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
res = 0;
|
||||
if (((Status = MmcSendCmd(CMD55, &res)) == MmcOk) && (res & 0x100))
|
||||
{ /* Send Notification for ACMD41 */
|
||||
res = OcrReg;
|
||||
if ((MmcSendCmd(ACMD41, &res) == MmcOk) && (res & 0x80000000))
|
||||
/* Activates Init Process (only SD) */
|
||||
{ /* Gets here when SD Card detected */
|
||||
CardDetected = TRUE;
|
||||
MmcDskCtrlBlk.DiskType = DiskSD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* If Cmd55 fails */
|
||||
{
|
||||
MCI_POWER |= (1 << 6); /* enable OpenDrain Mode */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
res = OcrReg;
|
||||
if (MmcSendCmd(CMD1, &res) == MmcOk && (res & 0x80000000))
|
||||
/* CMD1 for MMC Init sequence */
|
||||
{ /* Gets here when MMC Card detected */
|
||||
CardDetected = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MmcDly_1ms(50);
|
||||
} /* end Card Detection */
|
||||
|
||||
if (CardDetected == FALSE) /* If no Card recognized */
|
||||
{
|
||||
return (MmcNoResponse); /* Return with Error Message */
|
||||
}
|
||||
if (MmcSendCmd(CMD2, (pUINT32)MmcSdCid) != MmcOk) /* Read CID from Card */
|
||||
{
|
||||
return (MmcNoResponse); /* Return with Error Message */
|
||||
}
|
||||
|
||||
/* Set address */
|
||||
CardRCA = (MmcDskCtrlBlk.DiskType == DiskMMC) ? 0x00010000 : 0x00000000;
|
||||
if (MmcSendCmd(CMD3, &CardRCA) != MmcOk)
|
||||
{
|
||||
return (MmcNoResponse);
|
||||
}
|
||||
if (MmcDskCtrlBlk.DiskType == DiskSD)
|
||||
{
|
||||
CardRCA &= 0xFFFF0000;
|
||||
}
|
||||
else
|
||||
{
|
||||
CardRCA = 0x00010000;
|
||||
}
|
||||
|
||||
MCI_POWER &=~(1 << 6); /* Disable OpenDrain Mode */
|
||||
for(dlycnt = 10; dlycnt > 0;dlycnt--);
|
||||
|
||||
|
||||
/* Read Card specific Data from Card */
|
||||
MmcSdCsd[0] = 0;
|
||||
MmcSdCsd[1] = 0;
|
||||
MmcSdCsd[2] = CardRCA >> 16;
|
||||
MmcSdCsd[3] = CardRCA >> 24;
|
||||
if (MmcSendCmd(CMD9, (pUINT32)MmcSdCsd) != MmcOk)
|
||||
{
|
||||
return (MmcNoResponse);
|
||||
}
|
||||
|
||||
MmcCsdImplemet(); /* Implement CSD data */
|
||||
|
||||
res = CardRCA;
|
||||
if (MmcSendCmd(CMD7, &res) != MmcOk) /* Select Card */
|
||||
{
|
||||
return (MmcNoResponse);
|
||||
}
|
||||
res = CardRCA;
|
||||
if (MmcOk != MmcSendCmd(CMD13, &res)) /* Send Card Status Register */
|
||||
{
|
||||
return (MmcNoResponse);
|
||||
} else if (!(res & READY_FOR_DATA) || ((res & CURRENT_STATE)
|
||||
!= CARD_TRAN))
|
||||
{
|
||||
return (MmcCardError);
|
||||
}
|
||||
|
||||
if (MmcDskCtrlBlk.DiskType == DiskSD)
|
||||
{
|
||||
MCI_CLOCK |= (1 << 11); /* Use wide bus for SD */
|
||||
for (loopcnt = 0; loopcnt < 100; loopcnt++);
|
||||
|
||||
res = CardRCA;
|
||||
if (((Status = MmcSendCmd(CMD55, &res)) != MmcOk) || !(res & 0x100))
|
||||
/* Send Notification for ACMD6 */
|
||||
{
|
||||
return (MmcCardError);
|
||||
}
|
||||
|
||||
res = 2;
|
||||
if (MmcSendCmd(ACMD6, &res) != MmcOk) /* Set bus width 4bits */
|
||||
{
|
||||
return (MmcCardError);
|
||||
}
|
||||
}
|
||||
|
||||
res = MmcDskCtrlBlk.BlockSize;
|
||||
if (MmcSendCmd(CMD16, &res)) /* Set Block size */
|
||||
{
|
||||
return (MmcNoResponse);
|
||||
}
|
||||
|
||||
return (MmcOk);
|
||||
}
|
||||
|
||||
UINT32 Tets;
|
||||
void MmcCsdImplemet(void)
|
||||
{
|
||||
UINT32 Freq;
|
||||
UINT64 Tmp;
|
||||
// Calculate SPI max clock
|
||||
Freq = MmcTransfExp[CSD_GET_TRAN_SPEED_EXP()] * MmcCsdMant[CSD_GET_TRAN_SPEED_MANT()];
|
||||
Freq = MmcSetClockFreq(Freq);
|
||||
if (MmcDskCtrlBlk.DiskType == DiskMMC)
|
||||
{
|
||||
// Calculate Time outs for MMC cards
|
||||
Tmp = MmmcAccessTime[CSD_GET_TAAC_EXP()] * MmcCsdMant[CSD_GET_TAAC_MANT()];
|
||||
Tmp /= 10000; // us
|
||||
// Freq [Hz], Tmp[1 us], *10
|
||||
Tmp = (Freq*Tmp)/100000LL;
|
||||
// NSAC*100*10
|
||||
Tmp += 1000*CSD_GET_NSAC();
|
||||
// Max time out
|
||||
Tnac = Tmp;
|
||||
Twr = Tmp * (1<<CSD_GET_R2W_FACTOR());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculate Time outs for SD cards
|
||||
// Freq [Hz], RD_TIME_OUT[ms]
|
||||
Tmp = Freq/1000;
|
||||
Tnac = Tmp * RD_TIME_OUT;
|
||||
Twr = Tmp * WR_TIME_OUT;
|
||||
}
|
||||
// Calculate Block size and Block Number
|
||||
MmcDskCtrlBlk.BlockSize = 1<<CSD_GET_READ_BL_LEN();
|
||||
MmcDskCtrlBlk.BlockNumb = (CSD_GET_C_SIZE()+1)*(4<<CSD_GET_C_SIZE_MULT());
|
||||
// Set Write Protect
|
||||
bMmcPermWriteProtect = CSD_GET_PERM_WRITE_PROTECT() |\
|
||||
CSD_GET_TMP_WRITE_PROTECT();
|
||||
MmcDskCtrlBlk.WriteProtect = MmcWriteProtect() |\
|
||||
bMmcPermWriteProtect;
|
||||
}
|
||||
|
||||
|
||||
inline MmcState_t MmcVerify(const UINT8 * pData, UINT32 Add, UINT32 Length)
|
||||
{
|
||||
|
||||
__no_init static UINT8 TempBuffer[2048]__attribute__ ((section (".dmaram")));
|
||||
/* maximum block length is 2048 */
|
||||
MmcState_t Status = MmcOk;
|
||||
UINT32 i = 0;
|
||||
|
||||
while (Length)
|
||||
{
|
||||
Status = MmcReadBlock(TempBuffer, Add);
|
||||
if (Status != MmcOk)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < MmcDskCtrlBlk.BlockSize; ++i)
|
||||
{
|
||||
if (TempBuffer[i] != *pData++)
|
||||
{
|
||||
return (MmcMiscompare);
|
||||
}
|
||||
}
|
||||
Length -= MmcDskCtrlBlk.BlockSize;
|
||||
Add += MmcDskCtrlBlk.BlockSize;
|
||||
}
|
||||
return (Status);
|
||||
}
|
||||
|
||||
|
||||
UINT32 MmcGetLastError(void)
|
||||
{
|
||||
return(MmcLastError);
|
||||
}
|
||||
|
||||
void MmcStatusUpdate(void)
|
||||
{
|
||||
UINT32 Data = CardRCA;
|
||||
// Update WP state
|
||||
MmcDskCtrlBlk.WriteProtect = MmcWriteProtect() |\
|
||||
bMmcPermWriteProtect;
|
||||
if (!MmcPresent())
|
||||
{
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
|
||||
MmcPowerDown();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((MmcDskCtrlBlk.DiskStatus != DiskCommandPass))
|
||||
{
|
||||
switch (MmcInitMedia())
|
||||
{
|
||||
case MmcOk:
|
||||
MmcDskCtrlBlk.DiskStatus = DiskCommandPass;
|
||||
MmcDskCtrlBlk.MediaChanged = TRUE;
|
||||
break;
|
||||
case MmcCardError:
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotReady;
|
||||
break;
|
||||
default:
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (MmcSendCmd(CMD13, &Data) != MmcOk)
|
||||
{
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotReady;
|
||||
}
|
||||
else if (!(Data & READY_FOR_DATA))
|
||||
{
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotReady;
|
||||
}
|
||||
else if ((Data & CURRENT_STATE) == CARD_TRAN)
|
||||
{
|
||||
MmcDskCtrlBlk.DiskStatus = DiskCommandPass;
|
||||
}
|
||||
else
|
||||
{
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotReady;
|
||||
}
|
||||
}
|
||||
|
||||
void MmcDiskInit(void)
|
||||
{
|
||||
MmcDskCtrlBlk.BlockNumb =0;
|
||||
MmcDskCtrlBlk.BlockSize =0;
|
||||
MmcLastError = 0;
|
||||
// Init SPI
|
||||
MmcInit();
|
||||
// Media Init
|
||||
switch (MmcInitMedia())
|
||||
{
|
||||
case MmcOk:
|
||||
MmcCsdImplemet();
|
||||
MmcDskCtrlBlk.DiskStatus = DiskCommandPass;
|
||||
MmcDskCtrlBlk.MediaChanged = TRUE;
|
||||
break;
|
||||
case MmcCardError:
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotReady;
|
||||
break;
|
||||
default:
|
||||
MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MMC_DISK_INFO
|
||||
UINT32 MmcDiskInfo (pUINT8 pData, DiskInfoType_t DiskInfoType)
|
||||
{
|
||||
pMmc3FormatCapResponse_t pFormatCapacity;
|
||||
switch (DiskInfoType)
|
||||
{
|
||||
case DiskInquiry:
|
||||
memcpy(pData,MmcDskInquiry,SizeOfInquiryDescMmcDsk);
|
||||
return(SizeOfInquiryDescMmcDsk);
|
||||
case DiskFormatCapacity:
|
||||
pFormatCapacity = (pMmc3FormatCapResponse_t)pData;
|
||||
memset(pFormatCapacity,0,sizeof(Mmc3FormatCapResponse_t));
|
||||
pFormatCapacity->CapacityListLength = sizeof(Mmc3FormatCapDescriptor_t);
|
||||
if (MmcDskCtrlBlk.DiskStatus != DiskCommandPass)
|
||||
{
|
||||
pFormatCapacity->MaximumDescriptor.DescriptorType = FormattedMedia;
|
||||
pFormatCapacity->MaximumDescriptor.BlockLength[0] = (MmcDskCtrlBlk.BlockSize >> 16) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.BlockLength[1] = (MmcDskCtrlBlk.BlockSize >> 8) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.BlockLength[2] = (MmcDskCtrlBlk.BlockSize ) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[0] = (MmcDskCtrlBlk.BlockNumb >> 24) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[1] = (MmcDskCtrlBlk.BlockNumb >> 16) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[2] = (MmcDskCtrlBlk.BlockNumb >> 8) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[3] = (MmcDskCtrlBlk.BlockNumb ) & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pFormatCapacity->MaximumDescriptor.DescriptorType = NoMediaPresent;
|
||||
pFormatCapacity->MaximumDescriptor.BlockLength[0] = (2048 >> 16) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.BlockLength[1] = (2048 >> 8) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.BlockLength[2] = (2048 ) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[0] = (0xFFFFFFFF >> 24) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[1] = (0xFFFFFFFF >> 16) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[2] = (0xFFFFFFFF >> 8) & 0xFF;
|
||||
pFormatCapacity->MaximumDescriptor.NumberofBlocks[3] = (0xFFFFFFFF ) & 0xFF;
|
||||
}
|
||||
return(sizeof(Mmc3FormatCapResponse_t));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
pDiskCtrlBlk_t MmcGetDiskCtrlBkl(void)
|
||||
{
|
||||
return (&MmcDskCtrlBlk);
|
||||
}
|
||||
|
||||
UINT32 SYS_GetFSclk(void)
|
||||
{
|
||||
UINT32 Mul = 1, Div = 1, Osc, Fsclk;
|
||||
if (PLLSTAT & (1 << 25))
|
||||
{
|
||||
// when PLL is connected
|
||||
Mul = (PLLSTAT & 0x7FFF) +1;
|
||||
Div = ((PLLSTAT >> 16) & 0xFF) +1;
|
||||
}
|
||||
|
||||
// Find clk source
|
||||
switch (CLKSRCSEL & 0x3)
|
||||
{
|
||||
case 0:
|
||||
Osc = I_RC_OSC_FREQ;
|
||||
break;
|
||||
case 1:
|
||||
Osc = MAIN_OSC_FREQ;
|
||||
break;
|
||||
case 2:
|
||||
Osc = RTC_OSC_FREQ;
|
||||
break;
|
||||
default:
|
||||
Osc = 0;
|
||||
}
|
||||
// Calculate system frequency
|
||||
Fsclk = Osc*Mul*2;
|
||||
Fsclk /= Div*(CCLKCFG+1);
|
||||
return (Fsclk);
|
||||
}
|
||||
|
||||
UINT32 SYS_GetFPclk(UINT32 Periphery)
|
||||
{
|
||||
UINT32 Fpclk;
|
||||
pUINT32 pReg = (pUINT32)((Periphery < 32) ? &PCLKSEL0 : &PCLKSEL1);
|
||||
|
||||
Periphery &= 0x1F; // %32
|
||||
Fpclk = SYS_GetFSclk();
|
||||
// find peripheral appropriate periphery divider
|
||||
switch ((*pReg >> Periphery) & 3)
|
||||
{
|
||||
case 0:
|
||||
Fpclk /= 4;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
Fpclk /= 2;
|
||||
break;
|
||||
default:
|
||||
Fpclk /= 8;
|
||||
}
|
||||
return (Fpclk);
|
||||
}
|
||||
|
||||
void Dly100us(void *arg)
|
||||
{
|
||||
volatile UINT32 Dly = (UINT32)arg, Dly100;
|
||||
for (; Dly; Dly--)
|
||||
for (Dly100 = 500; Dly100; Dly100--)
|
||||
;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user