/* --------------------------------------------------------------------------- * 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 #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); }