373a8c32b2
git-svn-id: file:///srv/dev-disk-by-uuid-17e88007-4d0c-45e0-8757-cacfcc458630/repositories/svn/Diplomarbeit@55 9fe90eed-be63-e94b-8204-d34ff4c2ff93
308 lines
16 KiB
C
308 lines
16 KiB
C
/* ---------------------------------------------------------------------------
|
|
* mmc_transfer.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, May 08, 2008, MMi
|
|
* Creation.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* System include files
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
#include <string.h>
|
|
|
|
#include "LPC23xx.h"
|
|
#include "types.h"
|
|
/* ---------------------------------------------------------------------------
|
|
* Application include files
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
#include "mmc_transfer.h"
|
|
#include "mmc.h"
|
|
#include "dio.h"
|
|
/* ---------------------------------------------------------------------------
|
|
* Local constant and macro definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
#define Card_Page_Size 512
|
|
/* ---------------------------------------------------------------------------
|
|
* Global variable definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
extern UINT32 Tnac;
|
|
extern UINT32 Twr;
|
|
extern DiskCtrlBlk_t MmcDskCtrlBlk;
|
|
|
|
UINT32 dlycnt;
|
|
/* ---------------------------------------------------------------------------
|
|
* Local variable definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
UINT8 ReadFromCard[512] __attribute__ ((section (".dmaram")));
|
|
UINT8 WriteToCard[512] __attribute__ ((section (".dmaram")));
|
|
/* ---------------------------------------------------------------------------
|
|
* Local function definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
|
|
MmcState_t CardRead (pUINT8 pData, UINT32 Address, UINT32 Length)
|
|
{
|
|
UINT32 ArrayIndex = 0;
|
|
UINT32 loopcnt;
|
|
MmcState_t Status = MmcOk;
|
|
|
|
for (loopcnt = 0; loopcnt < Card_Page_Size; loopcnt++)/* Prepare Buffer */
|
|
{
|
|
ReadFromCard[loopcnt] = 0; /* Set all Positions to Zero */
|
|
}
|
|
|
|
/* Error or Wrong Argument Handle Block */
|
|
if (MmcPresent() == FALSE) /* Check if Card is present */
|
|
{
|
|
return (MmcNoPresent); /* Return NoCardPresent State */
|
|
}
|
|
if (checkLength(Length) == FALSE) /* Check Read Length for validity */
|
|
{
|
|
return (MmcMiscompare); /* Return WrongLength State */
|
|
}
|
|
|
|
Address = ((Address / Card_Page_Size) * Card_Page_Size);
|
|
/* Calculate first Address of Page */
|
|
|
|
do /* Loop to handle multible Reads */
|
|
{
|
|
Status = MmcReadBlock((pUINT8)ReadFromCard, Address);
|
|
/* Read 512 from Card */
|
|
memcpy (&(pData[ArrayIndex]), ReadFromCard, Card_Page_Size);
|
|
/* Copy read Content to User Buffer */
|
|
|
|
/* Recalculate Loop Values */
|
|
Length -= Card_Page_Size;
|
|
Address += Card_Page_Size;
|
|
ArrayIndex += Card_Page_Size;
|
|
} while (Length > 0);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
MmcState_t CardWrite (pUINT8 pData, UINT32 Address, UINT32 Length)
|
|
{
|
|
UINT32 ArrayIndex = 0;
|
|
UINT32 loopcnt;
|
|
MmcState_t Status = MmcOk;
|
|
|
|
for (loopcnt = 0; loopcnt < Card_Page_Size; loopcnt++)/* Prepare Buffer */
|
|
{
|
|
WriteToCard[loopcnt] = 0; /* Set all Positions to Zero */
|
|
}
|
|
|
|
/* Error or Wrong Argument Handle Block */
|
|
if (MmcPresent() == FALSE) /* Check if Card is Present */
|
|
{
|
|
return (MmcNoPresent); /* Return NoCardPresent State */
|
|
}
|
|
if (MmcWriteProtect() == TRUE) /* Check if Card is Writeprotected */
|
|
{
|
|
return (MmcProtect); /* Return WriteProtect State */
|
|
}
|
|
if (checkLength(Length) == FALSE) /* Check Read Length for validity */
|
|
{
|
|
return (MmcMiscompare); /* Return WrongLength State */
|
|
}
|
|
if (Address < 0x200) /* Defend Master Boot Sector */
|
|
{
|
|
return (MmcCardError); /* Return Error State */
|
|
}
|
|
|
|
|
|
Address = ((Address / Card_Page_Size) * Card_Page_Size);
|
|
/* Calculate first Address of Page */
|
|
|
|
do
|
|
{
|
|
memcpy (WriteToCard, &(pData[ArrayIndex]), Card_Page_Size);
|
|
/* Copy 512Bytes in send-Buffer */
|
|
Status = MmcWriteBlock((pUINT8)WriteToCard, Address);
|
|
/* Write 512 Bytes to Card */
|
|
|
|
/* Recalculate Loop Values */
|
|
Length -= Card_Page_Size;
|
|
Address += Card_Page_Size;
|
|
ArrayIndex += Card_Page_Size;
|
|
} while (Length > 0);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
inline BOOLEAN checkLength (UINT32 Length)
|
|
{
|
|
if (Length == 0)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
/* Check data length - Must be divisible of Card Block Size */
|
|
if ((Length % MmcDskCtrlBlk.BlockSize) != 0)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
inline MmcState_t MmcReadBlock(pUINT8 pData, UINT32 Add)
|
|
{
|
|
UINT32 Data;
|
|
MmcState_t Status = MmcOk;
|
|
|
|
PCONP |= (1 << 29); /* Turn on MCI Power */
|
|
MCI_DATA_TMR = Tnac; /* Set Read Timeout */
|
|
MCI_CLEAR = 0x000007FF; /* Clear all Interrupt Flags */
|
|
|
|
/* General Purpose DMA (GPDMA) Control Settings for Reading */
|
|
GPDMA_CONFIG = 0x00; /* Disable DMA */
|
|
GPDMA_CH0_LLI = 0; /* No link List available */
|
|
GPDMA_CH0_CTRL = 0x00; /* Reset DMA Control Block */
|
|
GPDMA_CH0_SRC = (UINT32)&MCI_FIFO; /* Set MCI FIFO as Source Adress */
|
|
|
|
GPDMA_CH0_CTRL = (Card_Page_Size & 0x0FFF) /* 512 Byte Transfer Size */
|
|
| (0x04 << 12) /* 32 Bit Source Burst Size */
|
|
| (0x04 << 15) /* 32 Bit Destination Burst Size */
|
|
| (0x02 << 18) /* 32 Bit Source width size */
|
|
| (0x00 << 21) /* 8 Bit Destination width size */
|
|
| (1 << 27) /* Destination index increment */
|
|
| (1U << 31); /* Terminal count interrupt */
|
|
|
|
MCI_DATA_LEN = MmcDskCtrlBlk.BlockSize; /* Set Transfer Blocksize */
|
|
Data = Add; /* Hand over Adress */
|
|
Status = MmcSendCmd(CMD17, &Data); /* Send Write Command to Card */
|
|
|
|
|
|
if (MmcOk != Status) /* If Command Response is not OK: */
|
|
{
|
|
return (Status); /* return Status and exit Function */
|
|
}
|
|
|
|
if (!(Data & READY_FOR_DATA)
|
|
||((Data & CURRENT_STATE) != CARD_TRAN))
|
|
{ /* Check Command Response */
|
|
MmcSendCmd(CMD12, NULL);
|
|
return (MmcCardError);
|
|
}
|
|
|
|
GPDMA_CH0_DEST = (UINT32)pData; /* Set DMA Destination Adress */
|
|
|
|
/* DMA Channel Configuration Block */
|
|
GPDMA_CH0_CFG = 0x00; /* Reset DMA Channel Configuration */
|
|
GPDMA_CH0_CFG = (0x10000)
|
|
| (0x04 << 1) /* Source Device is Peripheral */
|
|
| (0x00 << 6) /* Destination Device is Memory */
|
|
| (0x06 << 11); /* Peripheral to Memory Mode */
|
|
|
|
GPDMA_INT_TCCLR = 0x01; /* Clear all Terminal Interrupts */
|
|
GPDMA_CONFIG = 0x01; /* enable GPDMA after setup Channel */
|
|
while ((GPDMA_CONFIG & 0x01)!= 0x01); /* Poll Enable bit until set */
|
|
GPDMA_CH0_CFG |= (1 << 0); /* enable DMA Channel */
|
|
|
|
MCI_DATA_CTRL = (0x0001) /* Data Transfer enable */
|
|
| (0x01 << 1) /* From Card to Controller */
|
|
| (0x00 << 2) /* Block Data Transfer */
|
|
| (0x01 << 3) /* DMA enabled */
|
|
| (0x09 << 4); /* BlockSize 2^9 = 512 Byte */
|
|
for(dlycnt = 10; dlycnt > 0; dlycnt--);
|
|
|
|
while (MCI_STATUS & (1 << 13)); /* Poll RxActive until read finish */
|
|
GPDMA_CH0_CFG &=~(1 << 0); /* Disable DMA channel */
|
|
MCI_DATA_CTRL = 0; /* Reset Data Control Register */
|
|
for(dlycnt = 10; dlycnt > 0; dlycnt--);
|
|
|
|
/* Interrupt Handling Block */
|
|
if (GPDMA_RAW_INT_ERR_STAT & (1 << 0)) /* Channel requests Interrupt */
|
|
{
|
|
GPDMA_INT_ERR_CLR |= (1 << 0); /* clear Flag, terminate transfer */
|
|
return (MmcDmaError);
|
|
}
|
|
|
|
/* Error Handling Block */
|
|
if (MCI_STATUS & (1 << 3)) /* Timeout Error */
|
|
{
|
|
MCI_CLEAR = 1UL << 3; /* Clear Timeout Bit */
|
|
return (MmcNoResponse); /* Return with Error Message */
|
|
}
|
|
if (MCI_STATUS & (1 << 9)) /* StartBit not detected in Wide */
|
|
{ /* Bus Mode on every four Lines */
|
|
MCI_CLEAR = 1UL << 9; /* Clear StartBitError bit */
|
|
return (MmcCardError); /* Return with Error Message */
|
|
}
|
|
if (MCI_STATUS & (1 << 1)) /* DATA CRC Error */
|
|
{
|
|
MCI_CLEAR = 1UL << 1; /* Clear Data CRC Error Bit */
|
|
return (MmcCardError); /* Return with Error Message */
|
|
}
|
|
if (MCI_STATUS & (1 << 5)) /* Read FIFO Overrun Error */
|
|
{
|
|
MCI_CLEAR = 1UL << 5; /* Clean FIFO Overrun Error Bit */
|
|
return (MmcCardError); /* Return with Error Message */
|
|
}
|
|
|
|
MCI_CLEAR = (1UL << 8) /* Clear DATA END and DATA BLOCK END*/
|
|
| (1UL << 10);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
inline MmcState_t MmcWriteBlock(const UINT8 * pData, UINT32 Add)
|
|
{
|
|
UINT32 Data;
|
|
|
|
|
|
MmcState_t Status = MmcOk;
|
|
|
|
PCONP |= (1 << 29); /* Turn on MCI Power */
|
|
MCI_DATA_TMR = Twr; /* Set write Timeout */
|
|
MCI_CLEAR = 0x000007FF; /* Clear all related flags */
|
|
|
|
/* General Purpose DMA (GPDMA) Control Settings for Writing */
|
|
GPDMA_CONFIG = 0x00; /* Disable DMA */
|
|
GPDMA_CH0_LLI = 0; /* No link List */
|
|
GPDMA_CH0_CTRL = 0x00; /* Reset DMA Control Block */
|
|
GPDMA_CH0_DEST = (UINT32)&MCI_FIFO; /* Set MCI FIFO as Destination */
|
|
|
|
GPDMA_CH0_CTRL = (Card_Page_Size & 0x0FFF) /* 512 Byte Transfer Size */
|
|
| (0x04 << 12) /* 32 Bit Source Burst Size */
|
|
| (0x04 << 15) /* 32 Bit Destination Burst Size */
|
|
| (0x00 << 18) /* 8 bit Source width Size */
|
|
| (0x02 << 21) /* 32 Bit Destination width Size */
|
|
| (1 << 26) /* Source index increment */
|
|
| (1U << 31); /* Terminal count interrupt enable */
|
|
|
|
|
|
MCI_DATA_LEN = MmcDskCtrlBlk.BlockSize; /* Set Transfer Blocksize */
|
|
Data = Add; /* Hand over Adress */
|
|
Status = MmcSendCmd(CMD24, &Data); /* Send Write Command */
|
|
|
|
if (MmcOk != Status) /* If Command Response is NOT OK */
|
|
{
|
|
return (Status); /* Return with Error Message */
|
|
}
|
|
|
|
if (!(Data & READY_FOR_DATA)
|
|
|| ((Data & CURRENT_STATE) != CARD_TRAN))
|
|
{ /* Check Command Response */
|
|
MmcSendCmd(CMD12, NULL);
|
|
return (MmcCardError);
|
|
}
|
|
|
|
GPDMA_CH0_SRC = (UINT32)pData; /* Set DMA Source address */
|
|
|
|
/* DMA Channel Configuration Block */
|
|
GPDMA_CH0_CFG = 0x00; /* Reset DMA Channel Configuration */
|
|
GPDMA_CH0_CFG = (0x10000)
|
|
| (0x00 << 1) /* Source Device is Memory */
|
|
| (0x04 << 6) /* Destination is Peripheral */
|
|
| (0x05 << 11); /* Memory to Peripheral Mode */
|
|
|
|
GPDMA_INT_TCCLR = 0x01; /* Clear all Terminal Interrupts */
|
|
GPDMA_CONFIG = 0x01; /* Enable GPDMA after Setup Channel */
|
|
while ((GPDMA_CONFIG & 0x01)!= 0x01); /* Poll Enable Bit */
|
|
GPDMA_CH0_CFG |= (1 << 0); /* enable DMA Channel */
|
|
|
|
MCI_DATA_CTRL = (0x0001) /* Data Transfer enable */
|
|
| (0x00 << 1) /* From Controller to Card */
|
|
| (0x00 << 2) /* Block Data Transfer */
|
|
| (0x01 << 3) /* DMA enabled */
|
|
| (0x09 << 4); /* BlockSize 2^9 = 512 Byte */
|
|
|
|
for(dlycnt = 10; dlycnt > 0; dlycnt--);
|
|
|
|
while (MCI_STATUS & (1 << 12)); /* Poll TxActive until write finish */
|
|
|
|
GPDMA_CH0_CFG &=~(1 << 0); /* Disable DMA Channel */
|
|
|
|
/* Interrupt Handle Block */
|
|
if (GPDMA_RAW_INT_ERR_STAT & (1 << 0)) /* Channel requests Interrupt */
|
|
{
|
|
GPDMA_INT_ERR_CLR |= (1 << 0); /* clear Flag, terminate transfer */
|
|
return (MmcDmaError);
|
|
}
|
|
|
|
MCI_DATA_CTRL = 0; /* Reset DATA Control Register */
|
|
for(dlycnt = 10; dlycnt > 0; dlycnt--);
|
|
|
|
/* Error Handling Block */
|
|
if (MCI_STATUS & (1 << 3)) /* Timeout Error */
|
|
{
|
|
MCI_CLEAR = 1UL << 3; /* Clear Timeout Bit */
|
|
return (MmcNoResponse); /* Return with Error Message */
|
|
}
|
|
if (MCI_STATUS & (1 << 9)) /* StartBit not detected in Wide */
|
|
{ /* Bus Mode on every four Lines */
|
|
MCI_CLEAR = 1UL << 9; /* Clear StartBitError bit */
|
|
return (MmcCardError); /* Return with Error Message */
|
|
}
|
|
if (MCI_STATUS & (1 << 1)) /* DATA CRC Error */
|
|
{
|
|
MCI_CLEAR = 1UL << 1; /* Clear Data CRC Error Bit */
|
|
return (MmcCardError); /* Return with Error Message */
|
|
}
|
|
if (MCI_STATUS & (1 << 4)) /* Write FIFO Underrun Error */
|
|
{
|
|
MCI_CLEAR = 1UL << 4; /* Clean FIFO Underrun Error Bit */
|
|
return (MmcCardError); /* Return with Error Message */
|
|
}
|
|
|
|
MCI_CLEAR = (1UL << 8) /* Clear DATA END and DATA BLOCK END*/
|
|
| (1UL << 10);
|
|
|
|
return (Status);
|
|
}
|
|
|