]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/ATSAM4E/ff_sddisk.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / portable / ATSAM4E / 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 /* FreeRTOS includes. */\r
34 #include "FreeRTOS.h"\r
35 #include "task.h"\r
36 #include "semphr.h"\r
37 #include "portmacro.h"\r
38 \r
39 /* FreeRTOS+FAT includes. */\r
40 #include "ff_sddisk.h"\r
41 #include "ff_sys.h"\r
42 \r
43 /* Atmel includes. */\r
44 #include <board.h>\r
45 #include <sd_mmc.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 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
59 \r
60         /* Define a time-out for all DMA transactions in msec. */\r
61         #ifndef sdMAX_TRANSFER_TIME\r
62                 #define sdMAX_TRANSFER_TIME                     4000\r
63         #endif\r
64 \r
65         /* Define all possible interrupts of interest. */\r
66         #define sdHSMCI_INTERRUPT_FLAGS \\r
67                 HSMCI_IER_NOTBUSY | \\r
68                 HSMCI_IER_UNRE | \\r
69                 HSMCI_IER_OVRE | \\r
70                 HSMCI_IER_DTOE | \\r
71                 HSMCI_IER_DCRCE | \\r
72                 HSMCI_IER_TXBUFE | \\r
73                 HSMCI_IER_RXBUFF | \\r
74                 HSMCI_IER_XFRDONE\r
75 \r
76         #define sdMSMCI_USE_SEMAPHORE  1\r
77 \r
78 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
79 \r
80 /*-----------------------------------------------------------*/\r
81 \r
82 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
83 \r
84         static TickType_t xDMARemainingTime;\r
85         static TimeOut_t xDMATimeOut;\r
86         static volatile uint32_t ulSDInterruptStatus;\r
87         static volatile int iWaitForWriting;\r
88 \r
89         #if( sdMSMCI_USE_SEMAPHORE != 0 )\r
90                 static SemaphoreHandle_t xSDSemaphore = NULL;\r
91         #else\r
92                 static TaskHandle_t xSDTaskHandle = NULL;\r
93         #endif\r
94 \r
95 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
96 \r
97 /*\r
98  * Return pdFALSE if the SD card is not inserted.\r
99  */\r
100 static BaseType_t prvSDDetect( void );\r
101 \r
102 /*\r
103  * Check if the card is present, and if so, print out some info on the card.\r
104  */\r
105 static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber );\r
106 \r
107 /*-----------------------------------------------------------*/\r
108 \r
109 /*\r
110  * Mutex for partition.\r
111  */\r
112 static SemaphoreHandle_t xPlusFATMutex = NULL;\r
113 \r
114 /*\r
115  * Remembers if the card is currently considered to be present.\r
116  */\r
117 static BaseType_t xSDCardStatus = pdFALSE;\r
118 \r
119 /*-----------------------------------------------------------*/\r
120 \r
121 typedef struct {\r
122         uint32_t ulStart;\r
123         uint32_t ulSize;\r
124 } MemoryGroup_t;\r
125 \r
126 #define ARRAY_SIZE(x) (int)(sizeof(x)/sizeof(x)[0])\r
127 \r
128 static const MemoryGroup_t xMemories[] = {\r
129         { IRAM_ADDR, IRAM_SIZE },\r
130         { EBI_CS1_ADDR, 512ul * 1024ul },\r
131         { EBI_CS3_ADDR, 512ul * 1024ul },\r
132 };\r
133 \r
134 static BaseType_t prvIsInternalRAM( uint8_t *pucBuffer )\r
135 {\r
136 BaseType_t xResult = pdFALSE, xIndex;\r
137 uint32_t ulAddress = ( uint32_t ) pucBuffer;\r
138 \r
139         for( xIndex = 0; xIndex < ARRAY_SIZE( xMemories ); xIndex++ )\r
140         {\r
141                 if( ( ulAddress >= xMemories[ xIndex].ulStart ) && ( ulAddress < xMemories[ xIndex].ulStart + xMemories[ xIndex].ulSize ) )\r
142                 {\r
143                         xResult = pdTRUE;\r
144                         break;\r
145                 }\r
146         }\r
147 \r
148         return xResult;\r
149 }\r
150 /*-----------------------------------------------------------*/\r
151 \r
152 static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
153 {\r
154 int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG, lResult = pdFALSE;\r
155 \r
156         if( ( pxDisk != NULL ) &&\r
157                 ( xSDCardStatus == pdPASS ) &&\r
158                 ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
159                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
160                 ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
161                 ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
162         {\r
163                 /* As the MCI driver is configured to use DMA, it must be tested that\r
164                 the buffer is located in internal SRAM ("IRAM") and if it is 4-byte aligned. */\r
165                 if( sdAligned( pucBuffer ) && prvIsInternalRAM( pucBuffer ) )\r
166                 {\r
167                         lResult = sd_physical_read( ulSectorNumber, pucBuffer, ulSectorCount );\r
168                 }\r
169                 else\r
170                 {\r
171                 uint32_t ulSector;\r
172                 uint8_t *pucDMABuffer = ffconfigMALLOC( 512ul );\r
173 \r
174                         /* The buffer is NOT word-aligned, read to an aligned buffer and then\r
175                         copy the data to the user provided buffer. */\r
176                         if( pucDMABuffer != NULL )\r
177                         {\r
178                                 for( ulSector = 0; ulSector < ulSectorCount; ulSector++ )\r
179                                 {\r
180                                         lResult = sd_physical_read( ulSectorNumber + ulSector, pucDMABuffer, 1 );\r
181                                         if( lResult == pdFALSE )\r
182                                         {\r
183                                                 break;\r
184                                         }\r
185                                         /* Copy to the user-provided buffer. */\r
186                                         memcpy( pucBuffer + 512ul * ulSector, pucDMABuffer, 512ul );\r
187                                 }\r
188                                 ffconfigFREE( pucDMABuffer );\r
189                         }\r
190                         else\r
191                         {\r
192                                 FF_PRINTF( "prvFFRead: malloc failed\n" );\r
193                                 lResult = pdFALSE;\r
194                         }\r
195                 }\r
196                 \r
197                 if( lResult != pdFALSE )\r
198                 {\r
199                         lReturnCode = 0L;\r
200                 }\r
201                 else\r
202                 {\r
203                         /* Some error occurred. */\r
204                         FF_PRINTF( "prvFFRead: %lu: %ld\n", ulSectorNumber, lResult );\r
205                 }\r
206         }\r
207         else\r
208         {\r
209                 /* Make sure no random data is in the returned buffer. */\r
210                 memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512UL );\r
211 \r
212                 if( pxDisk->xStatus.bIsInitialised != pdFALSE )\r
213                 {\r
214                         FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
215                 }\r
216         }\r
217 \r
218         return lReturnCode;\r
219 }\r
220 /*-----------------------------------------------------------*/\r
221 \r
222 static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
223 {\r
224 int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG, lResult = pdFALSE;\r
225 \r
226         if( ( pxDisk != NULL ) &&\r
227                 ( xSDCardStatus == pdPASS ) &&\r
228                 ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
229                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
230                 ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
231                 ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
232         {\r
233                 /* As the MCI driver is configured to use DMA, it must be tested that\r
234                 the buffer is located in internal SRAM ("IRAM") and if it is 4-byte aligned. */\r
235                 if( sdAligned( pucBuffer ) && prvIsInternalRAM( pucBuffer ) )\r
236                 {\r
237                         lResult = sd_physical_write( ulSectorNumber, pucBuffer, ulSectorCount );\r
238                 }\r
239                 else\r
240                 {\r
241                 uint32_t ulSector;\r
242                 uint8_t *pucDMABuffer = ffconfigMALLOC( 512ul );\r
243 \r
244                         /* The buffer is NOT word-aligned, read to an aligned buffer and then\r
245                         copy the data to the user provided buffer. */\r
246                         if( pucDMABuffer != NULL )\r
247                         {\r
248                                 for( ulSector = 0; ulSector < ulSectorCount; ulSector++ )\r
249                                 {\r
250                                         /* Copy from the user provided buffer to the temporary buffer. */\r
251                                         memcpy( pucDMABuffer, pucBuffer + 512ul * ulSector, 512ul );\r
252                                         lResult = sd_physical_write( ulSectorNumber + ulSector, pucDMABuffer, 1 );\r
253                                         if( lResult == pdFALSE )\r
254                                         {\r
255                                                 break;\r
256                                         }\r
257                                 }\r
258                                 ffconfigFREE( pucDMABuffer );\r
259                         }\r
260                         else\r
261                         {\r
262                                 FF_PRINTF( "prvFFWrite: malloc failed\n" );\r
263                                 lResult = pdFALSE;\r
264                         }\r
265                 }\r
266 \r
267                 if( lResult != pdFALSE )\r
268                 {\r
269                         /* No errors. */\r
270                         lReturnCode = 0L;\r
271                 }\r
272                 else\r
273                 {\r
274                         FF_PRINTF( "prvFFWrite: %lu: %ld\n", ulSectorNumber, lResult  );\r
275                 }\r
276         }\r
277         else\r
278         {\r
279                 if( pxDisk->xStatus.bIsInitialised != pdFALSE )\r
280                 {\r
281                         FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
282                 }\r
283         }\r
284 \r
285         return lReturnCode;\r
286 }\r
287 /*-----------------------------------------------------------*/\r
288 \r
289 void FF_SDDiskFlush( FF_Disk_t *pxDisk )\r
290 {\r
291         if( ( pxDisk != NULL ) &&\r
292                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
293                 ( pxDisk->pxIOManager != NULL ) )\r
294         {\r
295                 FF_FlushCache( pxDisk->pxIOManager );\r
296         }\r
297 }\r
298 /*-----------------------------------------------------------*/\r
299 \r
300 /* Initialise the SDIO driver and mount an SD card */\r
301 FF_Disk_t *FF_SDDiskInit( const char *pcName )\r
302 {\r
303 FF_Error_t xFFError;\r
304 BaseType_t xPartitionNumber = 0;\r
305 FF_CreationParameters_t xParameters;\r
306 FF_Disk_t *pxDisk;\r
307 \r
308         #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
309         {\r
310                 NVIC_SetPriority( HSMCI_IRQn, configHSMCI_INTERRUPT_PRIORITY );\r
311                 NVIC_EnableIRQ( HSMCI_IRQn );\r
312                 #if( sdMSMCI_USE_SEMAPHORE != 0 )\r
313                 {\r
314                         if( xSDSemaphore == NULL )\r
315                         {\r
316                                 xSDSemaphore = xSemaphoreCreateBinary();\r
317                         }\r
318                 }\r
319                 #endif /* sdMSMCI_USE_SEMAPHORE */\r
320         }\r
321         #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
322 \r
323         xSDCardStatus = prvSDMMCInit( 0 );\r
324 \r
325         if( xSDCardStatus == pdPASS )\r
326         {\r
327                 pxDisk = (FF_Disk_t *)ffconfigMALLOC( sizeof( *pxDisk ) );\r
328                 if( pxDisk != NULL )\r
329                 {\r
330                         /* Initialise the created disk structure. */\r
331                         memset( pxDisk, '\0', sizeof( *pxDisk ) );\r
332 \r
333                         /* The Atmel MMC driver sets capacity as a number of KB.\r
334                         Divide by two to get the number of 512-byte sectors. */\r
335                         pxDisk->ulNumberOfSectors = xSDCardInfo.capacity << 1;\r
336 \r
337                         if( xPlusFATMutex == NULL )\r
338                         {\r
339                                 xPlusFATMutex = xSemaphoreCreateRecursiveMutex();\r
340                         }\r
341                         pxDisk->ulSignature = sdSIGNATURE;\r
342 \r
343                         if( xPlusFATMutex != NULL)\r
344                         {\r
345                                 memset( &xParameters, '\0', sizeof( xParameters ) );\r
346                                 xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;\r
347                                 xParameters.ulSectorSize = 512;\r
348                                 xParameters.fnWriteBlocks = prvFFWrite;\r
349                                 xParameters.fnReadBlocks = prvFFRead;\r
350                                 xParameters.pxDisk = pxDisk;\r
351 \r
352                                 /* prvFFRead()/prvFFWrite() are not re-entrant and must be\r
353                                 protected with the use of a semaphore. */\r
354                                 xParameters.xBlockDeviceIsReentrant = pdFALSE;\r
355 \r
356                                 /* The semaphore will be used to protect critical sections in\r
357                                 the +FAT driver, and also to avoid concurrent calls to\r
358                                 prvFFRead()/prvFFWrite() from different tasks. */\r
359                                 xParameters.pvSemaphore = ( void * ) xPlusFATMutex;\r
360 \r
361                                 pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );\r
362 \r
363                                 if( pxDisk->pxIOManager == NULL )\r
364                                 {\r
365                                         FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", (const char*)FF_GetErrMessage( xFFError ) );\r
366                                         FF_SDDiskDelete( pxDisk );\r
367                                         pxDisk = NULL;\r
368                                 }\r
369                                 else\r
370                                 {\r
371                                         pxDisk->xStatus.bIsInitialised = pdTRUE;\r
372                                         pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
373                                         if( FF_SDDiskMount( pxDisk ) == 0 )\r
374                                         {\r
375                                                 FF_SDDiskDelete( pxDisk );\r
376                                                 pxDisk = NULL;\r
377                                         }\r
378                                         else\r
379                                         {\r
380                                                 if( pcName == NULL )\r
381                                                 {\r
382                                                         pcName = "/";\r
383                                                 }\r
384                                                 FF_FS_Add( pcName, pxDisk );\r
385                                                 FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );\r
386                                         }\r
387                                 }       /* if( pxDisk->pxIOManager != NULL ) */\r
388                         }       /* if( xPlusFATMutex != NULL) */\r
389                 }       /* if( pxDisk != NULL ) */\r
390                 else\r
391                 {\r
392                         FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );\r
393                 }\r
394         }       /* if( xSDCardStatus == pdPASS ) */\r
395         else\r
396         {\r
397                 FF_PRINTF( "FF_SDDiskInit: prvSDMMC_Init failed\n" );\r
398                 pxDisk = NULL;\r
399         }\r
400 \r
401         return pxDisk;\r
402 }\r
403 /*-----------------------------------------------------------*/\r
404 \r
405 BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber )\r
406 {\r
407 FF_Error_t xError;\r
408 BaseType_t xReturn = pdFAIL;\r
409 \r
410         xError = FF_Unmount( pxDisk );\r
411 \r
412         if( FF_isERR( xError ) != pdFALSE )\r
413         {\r
414                 FF_PRINTF( "FF_SDDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );\r
415         }\r
416         else\r
417         {\r
418                 /* Format the drive - try FAT32 with large clusters. */\r
419                 xError = FF_Format( pxDisk, xPartitionNumber, pdFALSE, pdFALSE);\r
420 \r
421                 if( FF_isERR( xError ) )\r
422                 {\r
423                         FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );\r
424                 }\r
425                 else\r
426                 {\r
427                         FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );\r
428                         pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
429                         xError = FF_SDDiskMount( pxDisk );\r
430                         FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );\r
431                         if( FF_isERR( xError ) == pdFALSE )\r
432                         {\r
433                                 xReturn = pdPASS;\r
434                         }\r
435                 }\r
436         }\r
437 \r
438         return xReturn;\r
439 }\r
440 /*-----------------------------------------------------------*/\r
441 \r
442 BaseType_t FF_SDDiskUnmount( FF_Disk_t *pxDisk )\r
443 {\r
444 FF_Error_t xFFError;\r
445 BaseType_t xReturn = pdPASS;\r
446 \r
447         if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsMounted != pdFALSE ) )\r
448         {\r
449                 pxDisk->xStatus.bIsMounted = pdFALSE;\r
450                 xFFError = FF_Unmount( pxDisk );\r
451 \r
452                 if( FF_isERR( xFFError ) )\r
453                 {\r
454                         FF_PRINTF( "FF_SDDiskUnmount: rc %08x\n", ( unsigned )xFFError );\r
455                         xReturn = pdFAIL;\r
456                 }\r
457                 else\r
458                 {\r
459                         FF_PRINTF( "Drive unmounted\n" );\r
460                 }\r
461         }\r
462 \r
463         return xReturn;\r
464 }\r
465 /*-----------------------------------------------------------*/\r
466 \r
467 BaseType_t FF_SDDiskReinit( FF_Disk_t *pxDisk )\r
468 {\r
469 BaseType_t xStatus = prvSDMMCInit( 0 ); /* Hard coded index. */\r
470 \r
471         /*_RB_ parameter not used. */\r
472         ( void ) pxDisk;\r
473 \r
474         FF_PRINTF( "FF_SDDiskReinit: rc %08x\n", ( unsigned ) xStatus );\r
475         return xStatus;\r
476 }\r
477 /*-----------------------------------------------------------*/\r
478 \r
479 BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )\r
480 {\r
481 FF_Error_t xFFError;\r
482 BaseType_t xReturn;\r
483 \r
484         /* Mount the partition */\r
485         xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );\r
486 \r
487         if( FF_isERR( xFFError ) )\r
488         {\r
489                 FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );\r
490                 xReturn = pdFAIL;\r
491         }\r
492         else\r
493         {\r
494                 pxDisk->xStatus.bIsMounted = pdTRUE;\r
495                 FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );\r
496                 FF_SDDiskShowPartition( pxDisk );\r
497                 xReturn = pdPASS;\r
498         }\r
499 \r
500         return xReturn;\r
501 }\r
502 /*-----------------------------------------------------------*/\r
503 \r
504 FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )\r
505 {\r
506 FF_IOManager_t *pxReturn;\r
507 \r
508         if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )\r
509         {\r
510                 pxReturn = pxDisk->pxIOManager;\r
511         }\r
512         else\r
513         {\r
514                 pxReturn = NULL;\r
515         }\r
516         return pxReturn;\r
517 }\r
518 /*-----------------------------------------------------------*/\r
519 \r
520 /* Release all resources */\r
521 BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )\r
522 {\r
523         if( pxDisk != NULL )\r
524         {\r
525                 pxDisk->ulSignature = 0;\r
526                 pxDisk->xStatus.bIsInitialised = 0;\r
527                 if( pxDisk->pxIOManager != NULL )\r
528                 {\r
529                         if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )\r
530                         {\r
531                                 FF_Unmount( pxDisk );\r
532                         }\r
533                         FF_DeleteIOManager( pxDisk->pxIOManager );\r
534                 }\r
535 \r
536                 vPortFree( pxDisk );\r
537         }\r
538         return 1;\r
539 }\r
540 /*-----------------------------------------------------------*/\r
541 \r
542 BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )\r
543 {\r
544 FF_Error_t xError;\r
545 uint64_t ullFreeSectors;\r
546 uint32_t ulTotalSizeMB, ulFreeSizeMB;\r
547 int iPercentageFree;\r
548 FF_IOManager_t *pxIOManager;\r
549 const char *pcTypeName = "unknown type";\r
550 BaseType_t xReturn = pdPASS;\r
551 \r
552         if( pxDisk == NULL )\r
553         {\r
554                 xReturn = pdFAIL;\r
555         }\r
556         else\r
557         {\r
558                 pxIOManager = pxDisk->pxIOManager;\r
559 \r
560                 FF_PRINTF( "Reading FAT and calculating Free Space\n" );\r
561 \r
562                 switch( pxIOManager->xPartition.ucType )\r
563                 {\r
564                         case FF_T_FAT12:\r
565                                 pcTypeName = "FAT12";\r
566                                 break;\r
567 \r
568                         case FF_T_FAT16:\r
569                                 pcTypeName = "FAT16";\r
570                                 break;\r
571 \r
572                         case FF_T_FAT32:\r
573                                 pcTypeName = "FAT32";\r
574                                 break;\r
575 \r
576                         default:\r
577                                 pcTypeName = "UNKOWN";\r
578                                 break;\r
579                 }\r
580 \r
581                 FF_GetFreeSize( pxIOManager, &xError );\r
582 \r
583                 ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;\r
584                 iPercentageFree = ( int ) ( ( sdHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /\r
585                         ( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );\r
586 \r
587                 ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sdSECTORS_PER_MB;\r
588                 ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sdSECTORS_PER_MB );\r
589 \r
590                 /* It is better not to use the 64-bit format such as %Lu because it\r
591                 might not be implemented. */\r
592                 FF_PRINTF( "Partition Nr   %8u\n", pxDisk->xStatus.bPartitionNumber );\r
593                 FF_PRINTF( "Type           %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );\r
594                 FF_PRINTF( "VolLabel       '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );\r
595                 FF_PRINTF( "TotalSectors   %8lu\n", pxIOManager->xPartition.ulTotalSectors );\r
596                 FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );\r
597                 FF_PRINTF( "Size           %8lu MB\n", ulTotalSizeMB );\r
598                 FF_PRINTF( "FreeSize       %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );\r
599         }\r
600 \r
601         return xReturn;\r
602 }\r
603 /*-----------------------------------------------------------*/\r
604 \r
605 BaseType_t FF_SDDiskDetect( FF_Disk_t *pxDisk )\r
606 {\r
607 BaseType_t xIsPresent;\r
608 void *pvSemaphore;\r
609 \r
610         if( ( pxDisk != NULL ) && ( pxDisk->pxIOManager ) )\r
611         {\r
612                 pvSemaphore = pxDisk->pxIOManager->pvSemaphore;\r
613         }\r
614         else\r
615         {\r
616                 pvSemaphore = NULL;\r
617         }\r
618 \r
619         /*_RB_ Can these NULL checks be moved inside the FF_nnnSemaphore() functions? */\r
620         /*_HT_ I'm afraid not, both functions start with configASSERT( pxSemaphore ); */\r
621         if( pvSemaphore != NULL )\r
622         {\r
623                 FF_PendSemaphore( pvSemaphore );\r
624         }\r
625 \r
626         xIsPresent = prvSDDetect();\r
627 \r
628         if( pvSemaphore != NULL )\r
629         {\r
630                 FF_ReleaseSemaphore( pvSemaphore );\r
631         }\r
632 \r
633         return xIsPresent;\r
634 }\r
635 /*-----------------------------------------------------------*/\r
636 \r
637 static BaseType_t prvSDDetect( void )\r
638 {\r
639 static BaseType_t xWasPresent;\r
640 BaseType_t xIsPresent;\r
641 sd_mmc_err_t xSDPresence;\r
642 \r
643         if( xWasPresent == pdFALSE )\r
644         {\r
645                 /* Try to initialize SD MMC stack */\r
646                 sd_mmc_init();\r
647                 xSDPresence = sd_mmc_check( 0 );\r
648                 if( ( xSDPresence == SD_MMC_OK ) || ( xSDPresence == SD_MMC_INIT_ONGOING ) )\r
649                 {\r
650                         xIsPresent = pdTRUE;\r
651                 }\r
652                 else\r
653                 {\r
654                         xIsPresent = pdFALSE;\r
655                 }\r
656         }\r
657         else\r
658         {\r
659                 /* See if the card is still present. */\r
660                 xSDPresence = sd_mmc_check_status(0);\r
661                 if( xSDPresence == SD_MMC_OK )\r
662                 {\r
663                         xIsPresent = pdTRUE;\r
664                 }\r
665                 else\r
666                 {\r
667                         xIsPresent = pdFALSE;\r
668                 }\r
669         }\r
670         xWasPresent = xIsPresent;\r
671 \r
672         return xIsPresent;\r
673 }\r
674 /*-----------------------------------------------------------*/\r
675 \r
676 static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber )\r
677 {\r
678 BaseType_t xReturn;\r
679 \r
680         /* 'xDriveNumber' not yet in use. */\r
681         ( void ) xDriveNumber;\r
682 \r
683         /* Check if the SD card is plugged in the slot */\r
684         if( prvSDDetect() == pdFALSE )\r
685         {\r
686                 FF_PRINTF( "No SD card detected\n" );\r
687                 xReturn = pdFAIL;\r
688         }\r
689         else\r
690         {\r
691                 FF_PRINTF( "HAL_SD_Init: type: %s Capacity: %lu MB\n",\r
692                         xSDCardInfo.type & CARD_TYPE_HC ? "SDHC" : "SD",\r
693                         ( xSDCardInfo.capacity << 1 ) / 2048 );\r
694 \r
695                 xReturn = pdPASS;\r
696         }\r
697 \r
698         return xReturn;\r
699 }\r
700 /*-----------------------------------------------------------*/\r
701 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
702         void HSMCI_Handler( void )\r
703         {\r
704         uint32_t ulSR;\r
705         BaseType_t xSwitchRequired = pdFALSE;\r
706         \r
707                 ulSR = HSMCI->HSMCI_SR & HSMCI->HSMCI_IMR;\r
708                 HSMCI->HSMCI_IDR = ulSR;\r
709                 ulSDInterruptStatus |= ulSR;\r
710                 #if( sdMSMCI_USE_SEMAPHORE != 0 )\r
711                 {\r
712                         if( xSDSemaphore != NULL )\r
713                         {\r
714                                 xSemaphoreGiveFromISR( xSDSemaphore, &xSwitchRequired );\r
715                         }\r
716                 }\r
717                 #else\r
718                 {\r
719                         if( xSDTaskHandle != NULL )\r
720                         {\r
721                                 vTaskNotifyGiveFromISR( xSDTaskHandle, ( BaseType_t * ) &xSwitchRequired );\r
722                         }\r
723                 }\r
724                 #endif\r
725                 if( xSwitchRequired != pdFALSE )\r
726                 {\r
727                         portEND_SWITCHING_ISR( xSwitchRequired );\r
728                 }\r
729         }\r
730 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
731 /*-----------------------------------------------------------*/\r
732 \r
733 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
734         void vMCIEventSetupFunction( int iForWriting )\r
735         {\r
736                 iWaitForWriting = iForWriting != 0;\r
737         \r
738                 #if( sdMSMCI_USE_SEMAPHORE == 0 )\r
739                 {\r
740                         xSDTaskHandle = xTaskGetCurrentTaskHandle();\r
741                 }\r
742                 #endif\r
743                 ulSDInterruptStatus = 0;\r
744                 HSMCI->HSMCI_IER = sdHSMCI_INTERRUPT_FLAGS;\r
745         \r
746                 /* A DMA transfer to or from the SD-card is about to start.\r
747                 Reset the timers that will be used in prvEventWaitFunction() */\r
748                 xDMARemainingTime = pdMS_TO_TICKS( sdMAX_TRANSFER_TIME );\r
749                 vTaskSetTimeOutState( &xDMATimeOut );\r
750         }\r
751 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
752 /*-----------------------------------------------------------*/\r
753 \r
754 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
755         void vMCIEventReadyFunction()\r
756         {\r
757                 #if( sdMSMCI_USE_SEMAPHORE == 0 )\r
758                 {\r
759                         xSDTaskHandle = NULL;\r
760                 }\r
761                 #endif\r
762                 ulSDInterruptStatus = 0;\r
763                 HSMCI->HSMCI_IDR = sdHSMCI_INTERRUPT_FLAGS;\r
764         }\r
765 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
766 /*-----------------------------------------------------------*/\r
767 \r
768 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
769         uint32_t ulMCIEventWaitFunction( uint32_t ulMask )\r
770         {\r
771                 /*\r
772                  * It was measured how quickly a DMA interrupt was received. It varied\r
773                  * between 0 and 4 ms.\r
774                  * <= 1 ms : 8047\r
775                  * <= 2 ms : 1850\r
776                  * <= 3 ms :   99\r
777                  * <= 4 ms :   79\r
778                  * >= 5 ms :    0 times\r
779                  */\r
780                 if( xTaskCheckForTimeOut( &xDMATimeOut, &xDMARemainingTime ) != pdFALSE )\r
781                 {\r
782                         /* The timeout has been reached, no need to block. */\r
783                         FF_PRINTF( "ulMCIEventWaitFunction: %s timed out. SR = %08x\n",\r
784                                 iWaitForWriting ? "Write" : "Read", ulSDInterruptStatus );\r
785                 }\r
786                 else\r
787                 {\r
788                         /* The timeout has not been reached yet, block on the semaphore. */\r
789                         #if( sdMSMCI_USE_SEMAPHORE != 0 )\r
790                         {\r
791                                 if( ( ulSDInterruptStatus & ulMask ) == 0ul )\r
792                                 {\r
793                                         xSemaphoreTake( xSDSemaphore, xDMARemainingTime );\r
794                                 }\r
795                         }\r
796                         #else\r
797                         {\r
798                                 if( ( ulSDInterruptStatus & ulMask ) == 0ul )\r
799                                 {\r
800                                         ulTaskNotifyTake( pdFALSE, xDMARemainingTime );\r
801                                 }\r
802                         }\r
803                         #endif\r
804                         if( xTaskCheckForTimeOut( &xDMATimeOut, &xDMARemainingTime ) != pdFALSE )\r
805                         {\r
806                                 FF_PRINTF( "ulMCIEventWaitFunction: %s timed out. SR = %08x\n",\r
807                                         iWaitForWriting ? "Write" : "Read", ulSDInterruptStatus );\r
808                         }\r
809                 }\r
810 \r
811                 return ulSDInterruptStatus;\r
812         }\r
813 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
814 /*-----------------------------------------------------------*/\r
815 \r