]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/lpc18xx/ff_sddisk.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / portable / lpc18xx / ff_sddisk.c
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/lpc18xx/ff_sddisk.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/lpc18xx/ff_sddisk.c
new file mode 100644 (file)
index 0000000..aa5b728
--- /dev/null
@@ -0,0 +1,532 @@
+/*\r
+ * FreeRTOS+FAT build 191128 - Note:  FreeRTOS+FAT is still in the lab!\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ * Authors include James Walmsley, Hein Tibosch and Richard Barry\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * https://www.FreeRTOS.org\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+\r
+/* LPC18xx includes. */\r
+#include "chip.h"\r
+#include "board.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+#include "portmacro.h"\r
+\r
+/* FreeRTOS+FAT includes. */\r
+#include "ff_sddisk.h"\r
+#include "ff_sys.h"\r
+\r
+#include "hr_gettime.h"\r
+\r
+/* Misc definitions. */\r
+#define sdSIGNATURE                    0x41404342UL\r
+#define sdHUNDRED_64_BIT               ( 100ull )\r
+#define sdBYTES_PER_MB                 ( 1024ull * 1024ull )\r
+#define sdSECTORS_PER_MB               ( sdBYTES_PER_MB / 512ull )\r
+#define sdIOMAN_MEM_SIZE               4096\r
+#define xSDCardInfo                            ( sd_mmc_cards[ 0 ] )\r
+#define sdAligned( pvAddress ) ( ( ( ( size_t ) ( pvAddress ) ) & ( sizeof( size_t ) - 1 ) ) == 0 )\r
+\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*_RB_ Functions require comment blocks. */\r
+static void prvSDMMCSetupWakeup( void *pvInfo );\r
+static uint32_t prvSDMMCWait( void );\r
+static void prvSDMMCDelay_ms( uint32_t time );\r
+static void prvInitialiseCardInfo( void );\r
+static int32_t prvSDMMC_Init( void );\r
+static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );\r
+static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*_RB_ Variables require a comment block where appropriate. */\r
+static int32_t lSDDetected = 0;\r
+static mci_card_struct xCardInfo;\r
+static volatile int32_t lSDIOWaitExit;\r
+static BaseType_t xSDCardStatus;\r
+static SemaphoreHandle_t xSDCardSemaphore;\r
+static SemaphoreHandle_t xPlusFATMutex;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#warning Update to make read and write functions static and make use of the FF_Disk_t type.\r
+\r
+static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
+{\r
+int32_t iReturn;\r
+\r
+       /*_RB_ Many of the comments in this file apply to other functions in the file. */\r
+\r
+       if( ( pxDisk != NULL ) &&\r
+               ( xSDCardStatus == pdPASS ) &&\r
+               ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
+               ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
+               ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
+               ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
+       {\r
+\r
+               iReturn = Chip_SDMMC_ReadBlocks( LPC_SDMMC, pucBuffer, ulSectorNumber, ulSectorCount );\r
+\r
+               /*_RB_ I'm guessing 512 is a sector size, but that needs to be clear.\r
+               Is it defined in a header somewhere?  If so we can do a search and\r
+               replace in files on it as it seems to be used everywhere. */\r
+               if( iReturn == ( ulSectorCount * 512 ) ) /*_RB_ Signed/unsigned mismatch (twice!) */\r
+               {\r
+                       iReturn = FF_ERR_NONE;\r
+               }\r
+               else\r
+               {\r
+                       /*_RB_ Signed number used to return bitmap (again below). */\r
+                       iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );\r
+\r
+               if( pxDisk->xStatus.bIsInitialised != 0 )\r
+               {\r
+                       FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
+               }\r
+\r
+               iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );\r
+       }\r
+\r
+       return iReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
+{\r
+int32_t iReturn;\r
+\r
+       if( ( pxDisk != NULL ) &&\r
+               ( xSDCardStatus == pdPASS ) &&\r
+               ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
+               ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
+               ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
+               ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
+       {\r
+               iReturn = Chip_SDMMC_WriteBlocks( LPC_SDMMC, pucBuffer, ulSectorNumber, ulSectorCount );\r
+\r
+               if( iReturn == ( ulSectorCount * 512 ) ) /*_RB_ Signed/unsigned mismatch (twice!) */\r
+               {\r
+                       iReturn = 0;\r
+               }\r
+               else\r
+               {\r
+                       iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );\r
+               if( pxDisk->xStatus.bIsInitialised )\r
+               {\r
+                       FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
+               }\r
+\r
+               iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );\r
+       }\r
+\r
+       return iReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_SDDiskFlush( FF_Disk_t *pxDisk )\r
+{\r
+       if( ( pxDisk != NULL ) &&\r
+               ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
+               ( pxDisk->pxIOManager != NULL ) )\r
+       {\r
+               FF_FlushCache( pxDisk->pxIOManager );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Initialise the SDIO driver and mount an SD card */\r
+FF_Disk_t *FF_SDDiskInit( const char *pcName )\r
+{\r
+FF_Error_t xFFError;\r
+BaseType_t xPartitionNumber = 0;\r
+FF_CreationParameters_t xParameters;\r
+FF_Disk_t * pxDisk;\r
+\r
+       xSDCardStatus = prvSDMMC_Init();\r
+       if( xSDCardStatus == pdPASS )\r
+       {\r
+               pxDisk = ( FF_Disk_t * ) pvPortMalloc( sizeof( *pxDisk ) );\r
+\r
+               if( pxDisk != NULL )\r
+               {\r
+\r
+                       /* Initialise the created disk structure. */\r
+                       memset( pxDisk, '\0', sizeof( *pxDisk ) );\r
+\r
+\r
+                       if( xPlusFATMutex == NULL)\r
+                       {\r
+                               xPlusFATMutex = xSemaphoreCreateRecursiveMutex();\r
+                       }\r
+                       pxDisk->ulNumberOfSectors = xCardInfo.card_info.blocknr;\r
+                       pxDisk->ulSignature = sdSIGNATURE;\r
+\r
+                       if( xPlusFATMutex != NULL)\r
+                       {\r
+                               memset( &xParameters, '\0', sizeof( xParameters ) );\r
+                               xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;\r
+                               xParameters.ulSectorSize = 512;\r
+                               xParameters.fnWriteBlocks = prvFFWrite;\r
+                               xParameters.fnReadBlocks = prvFFRead;\r
+                               xParameters.pxDisk = pxDisk;\r
+\r
+                               /* prvFFRead()/prvFFWrite() are not re-entrant and must be\r
+                               protected with the use of a semaphore. */\r
+                               xParameters.xBlockDeviceIsReentrant = pdFALSE;\r
+\r
+                               /* The semaphore will be used to protect critical sections in\r
+                               the +FAT driver, and also to avoid concurrent calls to\r
+                               prvFFRead()/prvFFWrite() from different tasks. */\r
+                               xParameters.pvSemaphore = ( void * ) xPlusFATMutex;\r
+\r
+                               pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );\r
+\r
+                               if( pxDisk->pxIOManager == NULL )\r
+                               {\r
+                                       FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", ( const char * ) FF_GetErrMessage( xFFError ) );\r
+                                       FF_SDDiskDelete( pxDisk );\r
+                                       pxDisk = NULL;\r
+                               }\r
+                               else\r
+                               {\r
+                                       pxDisk->xStatus.bIsInitialised = pdTRUE;\r
+                                       pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
+                                       if( FF_SDDiskMount( pxDisk ) == 0 )\r
+                                       {\r
+                                               FF_SDDiskDelete( pxDisk );\r
+                                               pxDisk = NULL;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if( pcName == NULL )\r
+                                               {\r
+                                                       pcName = "/";\r
+                                               }\r
+                                               FF_FS_Add( pcName, pxDisk );\r
+                                               FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );\r
+                                               FF_SDDiskShowPartition( pxDisk );\r
+                                       }\r
+                               }       /* if( pxDisk->pxIOManager != NULL ) */\r
+                       }       /* if( xPlusFATMutex != NULL) */\r
+               }       /* if( pxDisk != NULL ) */\r
+               else\r
+               {\r
+                       FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );\r
+               }\r
+       }       /* if( xSDCardStatus == pdPASS ) */\r
+       else\r
+       {\r
+               FF_PRINTF( "FF_SDDiskInit: prvSDMMC_Init failed\n" );\r
+               pxDisk = NULL;\r
+       }\r
+\r
+       return pxDisk;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber )\r
+{\r
+FF_Error_t xError;\r
+BaseType_t xReturn = pdFAIL;\r
+\r
+       xError = FF_Unmount( pxDisk );\r
+\r
+       if( FF_isERR( xError ) != pdFALSE )\r
+       {\r
+               FF_PRINTF( "FF_SDDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );\r
+       }\r
+       else\r
+       {\r
+               /* Format the drive - try FAT32 with large clusters. */\r
+               xError = FF_Format( pxDisk, xPartitionNumber, pdFALSE, pdFALSE);\r
+\r
+               if( FF_isERR( xError ) )\r
+               {\r
+                       FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );\r
+               }\r
+               else\r
+               {\r
+                       FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );\r
+                       pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
+                       xError = FF_SDDiskMount( pxDisk );\r
+                       FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );\r
+                       if( FF_isERR( xError ) == pdFALSE )\r
+                       {\r
+                               xReturn = pdPASS;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Get a pointer to IOMAN, which can be used for all FreeRTOS+FAT functions */\r
+BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )\r
+{\r
+FF_Error_t xFFError;\r
+BaseType_t xReturn;\r
+\r
+       /* Mount the partition */\r
+       xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );\r
+\r
+       if( FF_isERR( xFFError ) )\r
+       {\r
+               FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );\r
+               xReturn = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               pxDisk->xStatus.bIsMounted = pdTRUE;\r
+               FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );\r
+               FF_SDDiskShowPartition( pxDisk );\r
+               xReturn = pdPASS;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )\r
+{\r
+FF_IOManager_t *pxReturn;\r
+\r
+       if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )\r
+       {\r
+               pxReturn = pxDisk->pxIOManager;\r
+       }\r
+       else\r
+       {\r
+               pxReturn = NULL;\r
+       }\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Release all resources */\r
+BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )\r
+{\r
+       if( pxDisk != NULL )\r
+       {\r
+               pxDisk->ulSignature = 0;\r
+               pxDisk->xStatus.bIsInitialised = 0;\r
+               if( pxDisk->pxIOManager != NULL )\r
+               {\r
+                       if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )\r
+                       {\r
+                               FF_Unmount( pxDisk );\r
+                       }\r
+                       FF_DeleteIOManager( pxDisk->pxIOManager );\r
+               }\r
+\r
+               vPortFree( pxDisk );\r
+       }\r
+       return 1;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )\r
+{\r
+FF_Error_t xError;\r
+uint64_t ullFreeSectors;\r
+uint32_t ulTotalSizeMB, ulFreeSizeMB;\r
+int iPercentageFree;\r
+FF_IOManager_t *pxIOManager;\r
+const char *pcTypeName = "unknown type";\r
+BaseType_t xReturn = pdPASS;\r
+\r
+       if( pxDisk == NULL )\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               pxIOManager = pxDisk->pxIOManager;\r
+\r
+               FF_PRINTF( "Reading FAT and calculating Free Space\n" );\r
+\r
+               switch( pxIOManager->xPartition.ucType )\r
+               {\r
+                       case FF_T_FAT12:\r
+                               pcTypeName = "FAT12";\r
+                               break;\r
+\r
+                       case FF_T_FAT16:\r
+                               pcTypeName = "FAT16";\r
+                               break;\r
+\r
+                       case FF_T_FAT32:\r
+                               pcTypeName = "FAT32";\r
+                               break;\r
+\r
+                       default:\r
+                               pcTypeName = "UNKOWN";\r
+                               break;\r
+               }\r
+\r
+               FF_GetFreeSize( pxIOManager, &xError );\r
+\r
+               ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;\r
+               iPercentageFree = ( int ) ( ( sdHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /\r
+                       ( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );\r
+\r
+               ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sdSECTORS_PER_MB;\r
+               ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sdSECTORS_PER_MB );\r
+\r
+               /* It is better not to use the 64-bit format such as %Lu because it\r
+               might not be implemented. */\r
+               FF_PRINTF( "Partition Nr   %8u\n", pxDisk->xStatus.bPartitionNumber );\r
+               FF_PRINTF( "Type           %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );\r
+               FF_PRINTF( "VolLabel       '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );\r
+               FF_PRINTF( "TotalSectors   %8lu\n", pxIOManager->xPartition.ulTotalSectors );\r
+               FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );\r
+               FF_PRINTF( "Size           %8lu MB\n", ulTotalSizeMB );\r
+               FF_PRINTF( "FreeSize       %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void SDIO_IRQHandler( void )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       /* All SD based register handling is done in the callback function. The SDIO\r
+       interrupt is not enabled as part of this driver and needs to be\r
+       enabled/disabled in the callbacks or application as needed. This is to allow\r
+       flexibility with IRQ handling for applications and RTOSes. */\r
+\r
+       /* Set wait exit flag to tell wait function we are ready. In an RTOS, this\r
+       would trigger wakeup of a thread waiting for the IRQ. */\r
+       NVIC_DisableIRQ( SDIO_IRQn );\r
+       xSemaphoreGiveFromISR( xSDCardSemaphore, &xHigherPriorityTaskWoken );\r
+       lSDIOWaitExit = 1;\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Sets up the SD event driven wakeup */\r
+static void prvSDMMCSetupWakeup( void *pvInfo )\r
+{\r
+uint32_t *ulWaitStatus = ( uint32_t * ) pvInfo;\r
+\r
+       /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ\r
+       based wakeup. */\r
+       /*_RB_ Don't understand why this is spinning on a block time of 0.  Is it\r
+       really meant to be != pdFALSE? */\r
+       while( xSemaphoreTake( xSDCardSemaphore, 0 ) != pdFALSE )\r
+       {\r
+       }\r
+\r
+       NVIC_ClearPendingIRQ( SDIO_IRQn );\r
+       lSDIOWaitExit = 0;\r
+       Chip_SDIF_SetIntMask( LPC_SDMMC, *ulWaitStatus );\r
+       NVIC_EnableIRQ( SDIO_IRQn );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvSDMMCWait( void )\r
+{\r
+uint32_t ulStatus;\r
+\r
+       /*_RB_ 2000 needs to be defined and use pdMS_TO_TICKS so the delay period\r
+       remains constant no matter how the end user sets configTICK_RATE_MS. */\r
+       xSemaphoreTake( xSDCardSemaphore, 2000 );\r
+\r
+       ulStatus = Chip_SDIF_GetIntStatus( LPC_SDMMC );\r
+       if( ( ( ulStatus & MCI_INT_CMD_DONE ) == 0 ) || ( lSDIOWaitExit == 0 ) )\r
+       {\r
+               FF_PRINTF( "Wait SD: int32_t %ld ulStatus 0x%02lX\n", lSDIOWaitExit, ulStatus );\r
+       }\r
+\r
+       return ulStatus;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSDMMCDelay_ms( uint32_t ulTime )\r
+{\r
+       /* In an RTOS, the thread would sleep allowing other threads to run.\r
+       For standalone operation, just spin on a timer */\r
+       vTaskDelay( pdMS_TO_TICKS( ulTime ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static int32_t prvSDMMC_Init( void )\r
+{\r
+int32_t lSDCardStatus;\r
+\r
+       if( xSDCardSemaphore == NULL )\r
+       {\r
+               xSDCardSemaphore = xSemaphoreCreateBinary();\r
+               configASSERT( xSDCardSemaphore );\r
+               xSemaphoreGive( xSDCardSemaphore );\r
+       }\r
+\r
+       prvInitialiseCardInfo();\r
+       NVIC_SetPriority( SDIO_IRQn, configSD_INTERRUPT_PRIORITY );\r
+\r
+       /*_RB_ Board_SDMMC_Init() is library specific code that is also specific to\r
+       the target development board.The SDMMC peripheral should be initialised from\r
+       the application code before this code is called. */\r
+       Board_SDMMC_Init();\r
+       Chip_SDIF_Init( LPC_SDMMC );\r
+       lSDDetected = !Chip_SDIF_CardNDetect( LPC_SDMMC );\r
+\r
+       Chip_SDIF_PowerOn( LPC_SDMMC );\r
+       lSDCardStatus = Chip_SDMMC_Acquire( LPC_SDMMC, &xCardInfo );\r
+       FF_PRINTF( "Acquire: %ld\n", lSDCardStatus );\r
+\r
+       return lSDCardStatus;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInitialiseCardInfo( void )\r
+{\r
+       memset( &xCardInfo, 0, sizeof( xCardInfo ) );\r
+       xCardInfo.card_info.evsetup_cb = prvSDMMCSetupWakeup;\r
+       xCardInfo.card_info.waitfunc_cb = prvSDMMCWait;\r
+       xCardInfo.card_info.msdelay_func = prvSDMMCDelay_ms;\r
+}\r