]> git.sur5r.net Git - freertos/blob - 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
1 /*\r
2  * FreeRTOS+FAT build 191128 - Note:  FreeRTOS+FAT is still in the lab!\r
3  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  * Authors include James Walmsley, Hein Tibosch and Richard Barry\r
5  *\r
6  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
7  * this software and associated documentation files (the "Software"), to deal in\r
8  * the Software without restriction, including without limitation the rights to\r
9  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
10  * the Software, and to permit persons to whom the Software is furnished to do so,\r
11  * subject to the following conditions:\r
12  *\r
13  * The above copyright notice and this permission notice shall be included in all\r
14  * copies or substantial portions of the Software.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * https://www.FreeRTOS.org\r
24  *\r
25  */\r
26 \r
27 /* Standard includes. */\r
28 #include <stdlib.h>\r
29 #include <string.h>\r
30 #include <stdarg.h>\r
31 #include <stdio.h>\r
32 \r
33 /* LPC18xx includes. */\r
34 #include "chip.h"\r
35 #include "board.h"\r
36 \r
37 /* FreeRTOS includes. */\r
38 #include "FreeRTOS.h"\r
39 #include "task.h"\r
40 #include "semphr.h"\r
41 #include "portmacro.h"\r
42 \r
43 /* FreeRTOS+FAT includes. */\r
44 #include "ff_sddisk.h"\r
45 #include "ff_sys.h"\r
46 \r
47 #include "hr_gettime.h"\r
48 \r
49 /* Misc definitions. */\r
50 #define sdSIGNATURE                     0x41404342UL\r
51 #define sdHUNDRED_64_BIT                ( 100ull )\r
52 #define sdBYTES_PER_MB                  ( 1024ull * 1024ull )\r
53 #define sdSECTORS_PER_MB                ( sdBYTES_PER_MB / 512ull )\r
54 #define sdIOMAN_MEM_SIZE                4096\r
55 #define xSDCardInfo                             ( sd_mmc_cards[ 0 ] )\r
56 #define sdAligned( pvAddress )  ( ( ( ( size_t ) ( pvAddress ) ) & ( sizeof( size_t ) - 1 ) ) == 0 )\r
57 \r
58 \r
59 \r
60 /*-----------------------------------------------------------*/\r
61 \r
62 /*_RB_ Functions require comment blocks. */\r
63 static void prvSDMMCSetupWakeup( void *pvInfo );\r
64 static uint32_t prvSDMMCWait( void );\r
65 static void prvSDMMCDelay_ms( uint32_t time );\r
66 static void prvInitialiseCardInfo( void );\r
67 static int32_t prvSDMMC_Init( void );\r
68 static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );\r
69 static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );\r
70 \r
71 \r
72 /*-----------------------------------------------------------*/\r
73 \r
74 /*_RB_ Variables require a comment block where appropriate. */\r
75 static int32_t lSDDetected = 0;\r
76 static mci_card_struct xCardInfo;\r
77 static volatile int32_t lSDIOWaitExit;\r
78 static BaseType_t xSDCardStatus;\r
79 static SemaphoreHandle_t xSDCardSemaphore;\r
80 static SemaphoreHandle_t xPlusFATMutex;\r
81 \r
82 /*-----------------------------------------------------------*/\r
83 \r
84 #warning Update to make read and write functions static and make use of the FF_Disk_t type.\r
85 \r
86 static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
87 {\r
88 int32_t iReturn;\r
89 \r
90         /*_RB_ Many of the comments in this file apply to other functions in the file. */\r
91 \r
92         if( ( pxDisk != NULL ) &&\r
93                 ( xSDCardStatus == pdPASS ) &&\r
94                 ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
95                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
96                 ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
97                 ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
98         {\r
99 \r
100                 iReturn = Chip_SDMMC_ReadBlocks( LPC_SDMMC, pucBuffer, ulSectorNumber, ulSectorCount );\r
101 \r
102                 /*_RB_ I'm guessing 512 is a sector size, but that needs to be clear.\r
103                 Is it defined in a header somewhere?  If so we can do a search and\r
104                 replace in files on it as it seems to be used everywhere. */\r
105                 if( iReturn == ( ulSectorCount * 512 ) ) /*_RB_ Signed/unsigned mismatch (twice!) */\r
106                 {\r
107                         iReturn = FF_ERR_NONE;\r
108                 }\r
109                 else\r
110                 {\r
111                         /*_RB_ Signed number used to return bitmap (again below). */\r
112                         iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );\r
113                 }\r
114         }\r
115         else\r
116         {\r
117                 memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );\r
118 \r
119                 if( pxDisk->xStatus.bIsInitialised != 0 )\r
120                 {\r
121                         FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
122                 }\r
123 \r
124                 iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );\r
125         }\r
126 \r
127         return iReturn;\r
128 }\r
129 /*-----------------------------------------------------------*/\r
130 \r
131 static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
132 {\r
133 int32_t iReturn;\r
134 \r
135         if( ( pxDisk != NULL ) &&\r
136                 ( xSDCardStatus == pdPASS ) &&\r
137                 ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
138                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
139                 ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
140                 ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
141         {\r
142                 iReturn = Chip_SDMMC_WriteBlocks( LPC_SDMMC, pucBuffer, ulSectorNumber, ulSectorCount );\r
143 \r
144                 if( iReturn == ( ulSectorCount * 512 ) ) /*_RB_ Signed/unsigned mismatch (twice!) */\r
145                 {\r
146                         iReturn = 0;\r
147                 }\r
148                 else\r
149                 {\r
150                         iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );\r
151                 }\r
152         }\r
153         else\r
154         {\r
155                 memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );\r
156                 if( pxDisk->xStatus.bIsInitialised )\r
157                 {\r
158                         FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
159                 }\r
160 \r
161                 iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );\r
162         }\r
163 \r
164         return iReturn;\r
165 }\r
166 /*-----------------------------------------------------------*/\r
167 \r
168 void FF_SDDiskFlush( FF_Disk_t *pxDisk )\r
169 {\r
170         if( ( pxDisk != NULL ) &&\r
171                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
172                 ( pxDisk->pxIOManager != NULL ) )\r
173         {\r
174                 FF_FlushCache( pxDisk->pxIOManager );\r
175         }\r
176 }\r
177 /*-----------------------------------------------------------*/\r
178 \r
179 /* Initialise the SDIO driver and mount an SD card */\r
180 FF_Disk_t *FF_SDDiskInit( const char *pcName )\r
181 {\r
182 FF_Error_t xFFError;\r
183 BaseType_t xPartitionNumber = 0;\r
184 FF_CreationParameters_t xParameters;\r
185 FF_Disk_t * pxDisk;\r
186 \r
187         xSDCardStatus = prvSDMMC_Init();\r
188         if( xSDCardStatus == pdPASS )\r
189         {\r
190                 pxDisk = ( FF_Disk_t * ) pvPortMalloc( sizeof( *pxDisk ) );\r
191 \r
192                 if( pxDisk != NULL )\r
193                 {\r
194 \r
195                         /* Initialise the created disk structure. */\r
196                         memset( pxDisk, '\0', sizeof( *pxDisk ) );\r
197 \r
198 \r
199                         if( xPlusFATMutex == NULL)\r
200                         {\r
201                                 xPlusFATMutex = xSemaphoreCreateRecursiveMutex();\r
202                         }\r
203                         pxDisk->ulNumberOfSectors = xCardInfo.card_info.blocknr;\r
204                         pxDisk->ulSignature = sdSIGNATURE;\r
205 \r
206                         if( xPlusFATMutex != NULL)\r
207                         {\r
208                                 memset( &xParameters, '\0', sizeof( xParameters ) );\r
209                                 xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;\r
210                                 xParameters.ulSectorSize = 512;\r
211                                 xParameters.fnWriteBlocks = prvFFWrite;\r
212                                 xParameters.fnReadBlocks = prvFFRead;\r
213                                 xParameters.pxDisk = pxDisk;\r
214 \r
215                                 /* prvFFRead()/prvFFWrite() are not re-entrant and must be\r
216                                 protected with the use of a semaphore. */\r
217                                 xParameters.xBlockDeviceIsReentrant = pdFALSE;\r
218 \r
219                                 /* The semaphore will be used to protect critical sections in\r
220                                 the +FAT driver, and also to avoid concurrent calls to\r
221                                 prvFFRead()/prvFFWrite() from different tasks. */\r
222                                 xParameters.pvSemaphore = ( void * ) xPlusFATMutex;\r
223 \r
224                                 pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );\r
225 \r
226                                 if( pxDisk->pxIOManager == NULL )\r
227                                 {\r
228                                         FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", ( const char * ) FF_GetErrMessage( xFFError ) );\r
229                                         FF_SDDiskDelete( pxDisk );\r
230                                         pxDisk = NULL;\r
231                                 }\r
232                                 else\r
233                                 {\r
234                                         pxDisk->xStatus.bIsInitialised = pdTRUE;\r
235                                         pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
236                                         if( FF_SDDiskMount( pxDisk ) == 0 )\r
237                                         {\r
238                                                 FF_SDDiskDelete( pxDisk );\r
239                                                 pxDisk = NULL;\r
240                                         }\r
241                                         else\r
242                                         {\r
243                                                 if( pcName == NULL )\r
244                                                 {\r
245                                                         pcName = "/";\r
246                                                 }\r
247                                                 FF_FS_Add( pcName, pxDisk );\r
248                                                 FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );\r
249                                                 FF_SDDiskShowPartition( pxDisk );\r
250                                         }\r
251                                 }       /* if( pxDisk->pxIOManager != NULL ) */\r
252                         }       /* if( xPlusFATMutex != NULL) */\r
253                 }       /* if( pxDisk != NULL ) */\r
254                 else\r
255                 {\r
256                         FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );\r
257                 }\r
258         }       /* if( xSDCardStatus == pdPASS ) */\r
259         else\r
260         {\r
261                 FF_PRINTF( "FF_SDDiskInit: prvSDMMC_Init failed\n" );\r
262                 pxDisk = NULL;\r
263         }\r
264 \r
265         return pxDisk;\r
266 }\r
267 /*-----------------------------------------------------------*/\r
268 \r
269 BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber )\r
270 {\r
271 FF_Error_t xError;\r
272 BaseType_t xReturn = pdFAIL;\r
273 \r
274         xError = FF_Unmount( pxDisk );\r
275 \r
276         if( FF_isERR( xError ) != pdFALSE )\r
277         {\r
278                 FF_PRINTF( "FF_SDDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );\r
279         }\r
280         else\r
281         {\r
282                 /* Format the drive - try FAT32 with large clusters. */\r
283                 xError = FF_Format( pxDisk, xPartitionNumber, pdFALSE, pdFALSE);\r
284 \r
285                 if( FF_isERR( xError ) )\r
286                 {\r
287                         FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );\r
288                 }\r
289                 else\r
290                 {\r
291                         FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );\r
292                         pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
293                         xError = FF_SDDiskMount( pxDisk );\r
294                         FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );\r
295                         if( FF_isERR( xError ) == pdFALSE )\r
296                         {\r
297                                 xReturn = pdPASS;\r
298                         }\r
299                 }\r
300         }\r
301 \r
302         return xReturn;\r
303 }\r
304 /*-----------------------------------------------------------*/\r
305 \r
306 /* Get a pointer to IOMAN, which can be used for all FreeRTOS+FAT functions */\r
307 BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )\r
308 {\r
309 FF_Error_t xFFError;\r
310 BaseType_t xReturn;\r
311 \r
312         /* Mount the partition */\r
313         xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );\r
314 \r
315         if( FF_isERR( xFFError ) )\r
316         {\r
317                 FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );\r
318                 xReturn = pdFAIL;\r
319         }\r
320         else\r
321         {\r
322                 pxDisk->xStatus.bIsMounted = pdTRUE;\r
323                 FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );\r
324                 FF_SDDiskShowPartition( pxDisk );\r
325                 xReturn = pdPASS;\r
326         }\r
327 \r
328         return xReturn;\r
329 }\r
330 /*-----------------------------------------------------------*/\r
331 \r
332 FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )\r
333 {\r
334 FF_IOManager_t *pxReturn;\r
335 \r
336         if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )\r
337         {\r
338                 pxReturn = pxDisk->pxIOManager;\r
339         }\r
340         else\r
341         {\r
342                 pxReturn = NULL;\r
343         }\r
344         return pxReturn;\r
345 }\r
346 /*-----------------------------------------------------------*/\r
347 \r
348 /* Release all resources */\r
349 BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )\r
350 {\r
351         if( pxDisk != NULL )\r
352         {\r
353                 pxDisk->ulSignature = 0;\r
354                 pxDisk->xStatus.bIsInitialised = 0;\r
355                 if( pxDisk->pxIOManager != NULL )\r
356                 {\r
357                         if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )\r
358                         {\r
359                                 FF_Unmount( pxDisk );\r
360                         }\r
361                         FF_DeleteIOManager( pxDisk->pxIOManager );\r
362                 }\r
363 \r
364                 vPortFree( pxDisk );\r
365         }\r
366         return 1;\r
367 }\r
368 /*-----------------------------------------------------------*/\r
369 \r
370 BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )\r
371 {\r
372 FF_Error_t xError;\r
373 uint64_t ullFreeSectors;\r
374 uint32_t ulTotalSizeMB, ulFreeSizeMB;\r
375 int iPercentageFree;\r
376 FF_IOManager_t *pxIOManager;\r
377 const char *pcTypeName = "unknown type";\r
378 BaseType_t xReturn = pdPASS;\r
379 \r
380         if( pxDisk == NULL )\r
381         {\r
382                 xReturn = pdFAIL;\r
383         }\r
384         else\r
385         {\r
386                 pxIOManager = pxDisk->pxIOManager;\r
387 \r
388                 FF_PRINTF( "Reading FAT and calculating Free Space\n" );\r
389 \r
390                 switch( pxIOManager->xPartition.ucType )\r
391                 {\r
392                         case FF_T_FAT12:\r
393                                 pcTypeName = "FAT12";\r
394                                 break;\r
395 \r
396                         case FF_T_FAT16:\r
397                                 pcTypeName = "FAT16";\r
398                                 break;\r
399 \r
400                         case FF_T_FAT32:\r
401                                 pcTypeName = "FAT32";\r
402                                 break;\r
403 \r
404                         default:\r
405                                 pcTypeName = "UNKOWN";\r
406                                 break;\r
407                 }\r
408 \r
409                 FF_GetFreeSize( pxIOManager, &xError );\r
410 \r
411                 ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;\r
412                 iPercentageFree = ( int ) ( ( sdHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /\r
413                         ( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );\r
414 \r
415                 ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sdSECTORS_PER_MB;\r
416                 ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sdSECTORS_PER_MB );\r
417 \r
418                 /* It is better not to use the 64-bit format such as %Lu because it\r
419                 might not be implemented. */\r
420                 FF_PRINTF( "Partition Nr   %8u\n", pxDisk->xStatus.bPartitionNumber );\r
421                 FF_PRINTF( "Type           %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );\r
422                 FF_PRINTF( "VolLabel       '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );\r
423                 FF_PRINTF( "TotalSectors   %8lu\n", pxIOManager->xPartition.ulTotalSectors );\r
424                 FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );\r
425                 FF_PRINTF( "Size           %8lu MB\n", ulTotalSizeMB );\r
426                 FF_PRINTF( "FreeSize       %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );\r
427         }\r
428 \r
429         return xReturn;\r
430 }\r
431 /*-----------------------------------------------------------*/\r
432 \r
433 void SDIO_IRQHandler( void )\r
434 {\r
435 BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
436 \r
437         /* All SD based register handling is done in the callback function. The SDIO\r
438         interrupt is not enabled as part of this driver and needs to be\r
439         enabled/disabled in the callbacks or application as needed. This is to allow\r
440         flexibility with IRQ handling for applications and RTOSes. */\r
441 \r
442         /* Set wait exit flag to tell wait function we are ready. In an RTOS, this\r
443         would trigger wakeup of a thread waiting for the IRQ. */\r
444         NVIC_DisableIRQ( SDIO_IRQn );\r
445         xSemaphoreGiveFromISR( xSDCardSemaphore, &xHigherPriorityTaskWoken );\r
446         lSDIOWaitExit = 1;\r
447         portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
448 }\r
449 /*-----------------------------------------------------------*/\r
450 \r
451 /* Sets up the SD event driven wakeup */\r
452 static void prvSDMMCSetupWakeup( void *pvInfo )\r
453 {\r
454 uint32_t *ulWaitStatus = ( uint32_t * ) pvInfo;\r
455 \r
456         /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ\r
457         based wakeup. */\r
458         /*_RB_ Don't understand why this is spinning on a block time of 0.  Is it\r
459         really meant to be != pdFALSE? */\r
460         while( xSemaphoreTake( xSDCardSemaphore, 0 ) != pdFALSE )\r
461         {\r
462         }\r
463 \r
464         NVIC_ClearPendingIRQ( SDIO_IRQn );\r
465         lSDIOWaitExit = 0;\r
466         Chip_SDIF_SetIntMask( LPC_SDMMC, *ulWaitStatus );\r
467         NVIC_EnableIRQ( SDIO_IRQn );\r
468 }\r
469 /*-----------------------------------------------------------*/\r
470 \r
471 static uint32_t prvSDMMCWait( void )\r
472 {\r
473 uint32_t ulStatus;\r
474 \r
475         /*_RB_ 2000 needs to be defined and use pdMS_TO_TICKS so the delay period\r
476         remains constant no matter how the end user sets configTICK_RATE_MS. */\r
477         xSemaphoreTake( xSDCardSemaphore, 2000 );\r
478 \r
479         ulStatus = Chip_SDIF_GetIntStatus( LPC_SDMMC );\r
480         if( ( ( ulStatus & MCI_INT_CMD_DONE ) == 0 ) || ( lSDIOWaitExit == 0 ) )\r
481         {\r
482                 FF_PRINTF( "Wait SD: int32_t %ld ulStatus 0x%02lX\n", lSDIOWaitExit, ulStatus );\r
483         }\r
484 \r
485         return ulStatus;\r
486 }\r
487 /*-----------------------------------------------------------*/\r
488 \r
489 static void prvSDMMCDelay_ms( uint32_t ulTime )\r
490 {\r
491         /* In an RTOS, the thread would sleep allowing other threads to run.\r
492         For standalone operation, just spin on a timer */\r
493         vTaskDelay( pdMS_TO_TICKS( ulTime ) );\r
494 }\r
495 /*-----------------------------------------------------------*/\r
496 \r
497 static int32_t prvSDMMC_Init( void )\r
498 {\r
499 int32_t lSDCardStatus;\r
500 \r
501         if( xSDCardSemaphore == NULL )\r
502         {\r
503                 xSDCardSemaphore = xSemaphoreCreateBinary();\r
504                 configASSERT( xSDCardSemaphore );\r
505                 xSemaphoreGive( xSDCardSemaphore );\r
506         }\r
507 \r
508         prvInitialiseCardInfo();\r
509         NVIC_SetPriority( SDIO_IRQn, configSD_INTERRUPT_PRIORITY );\r
510 \r
511         /*_RB_ Board_SDMMC_Init() is library specific code that is also specific to\r
512         the target development board.The SDMMC peripheral should be initialised from\r
513         the application code before this code is called. */\r
514         Board_SDMMC_Init();\r
515         Chip_SDIF_Init( LPC_SDMMC );\r
516         lSDDetected = !Chip_SDIF_CardNDetect( LPC_SDMMC );\r
517 \r
518         Chip_SDIF_PowerOn( LPC_SDMMC );\r
519         lSDCardStatus = Chip_SDMMC_Acquire( LPC_SDMMC, &xCardInfo );\r
520         FF_PRINTF( "Acquire: %ld\n", lSDCardStatus );\r
521 \r
522         return lSDCardStatus;\r
523 }\r
524 /*-----------------------------------------------------------*/\r
525 \r
526 static void prvInitialiseCardInfo( void )\r
527 {\r
528         memset( &xCardInfo, 0, sizeof( xCardInfo ) );\r
529         xCardInfo.card_info.evsetup_cb = prvSDMMCSetupWakeup;\r
530         xCardInfo.card_info.waitfunc_cb = prvSDMMCWait;\r
531         xCardInfo.card_info.msdelay_func = prvSDMMCDelay_ms;\r
532 }\r