]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/STM32F4xx/ff_sddisk.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / portable / STM32F4xx / 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 /* ST HAL includes. */\r
44 #include "stm32f4xx_hal.h"\r
45 \r
46 /* Misc definitions. */\r
47 #define sdSIGNATURE                     0x41404342UL\r
48 #define sdHUNDRED_64_BIT                ( 100ull )\r
49 #define sdBYTES_PER_MB                  ( 1024ull * 1024ull )\r
50 #define sdSECTORS_PER_MB                ( sdBYTES_PER_MB / 512ull )\r
51 #define sdIOMAN_MEM_SIZE                4096\r
52 \r
53 /* DMA constants. */\r
54 #define SD_DMAx_Tx_CHANNEL                                      DMA_CHANNEL_4\r
55 #define SD_DMAx_Rx_CHANNEL                                      DMA_CHANNEL_4\r
56 #define SD_DMAx_Tx_STREAM                                       DMA2_Stream6\r
57 #define SD_DMAx_Rx_STREAM                                       DMA2_Stream3\r
58 #define SD_DMAx_Tx_IRQn                                         DMA2_Stream6_IRQn\r
59 #define SD_DMAx_Rx_IRQn                                         DMA2_Stream3_IRQn\r
60 #define __DMAx_TxRx_CLK_ENABLE                          __DMA2_CLK_ENABLE\r
61 #define configSDIO_DMA_INTERRUPT_PRIORITY       ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY )\r
62 \r
63 /* Define a time-out for all DMA transactions in msec. */\r
64 #ifndef sdMAX_TIME_TICKS\r
65         #define sdMAX_TIME_TICKS        pdMS_TO_TICKS( 2000UL )\r
66 #endif\r
67 \r
68 #ifndef configSD_DETECT_PIN\r
69         #error configSD_DETECT_PIN must be defined in FreeRTOSConfig.h to the pin used to detect if the SD card is present.\r
70 #endif\r
71 \r
72 #ifndef configSD_DETECT_GPIO_PORT\r
73         #error configSD_DETECT_GPIO_PORT must be defined in FreeRTOSConfig.h to the port on which configSD_DETECT_PIN is located.\r
74 #endif\r
75 \r
76 #ifndef sdCARD_DETECT_DEBOUNCE_TIME_MS\r
77         /* Debouncing time is applied only after card gets inserted. */\r
78         #define sdCARD_DETECT_DEBOUNCE_TIME_MS  ( 5000 )\r
79 #endif\r
80 \r
81 #ifndef sdARRAY_SIZE\r
82         #define sdARRAY_SIZE( x )       ( int )( sizeof( x ) / sizeof( x )[ 0 ] )\r
83 #endif\r
84 \r
85 /*-----------------------------------------------------------*/\r
86 \r
87 /*\r
88  * Return pdFALSE if the SD card is not inserted.  This function just reads the\r
89  * value of the GPIO C/D pin.\r
90  */\r
91 static BaseType_t prvSDDetect( void );\r
92 \r
93 /*\r
94  * Translate a numeric code like 'SD_TX_UNDERRUN' to a printable string.\r
95  */\r
96 static const char *prvSDCodePrintable( uint32_t ulCode );\r
97 \r
98 /*\r
99  * The following 'hook' must be provided by the user of this module.  It will be\r
100  * called from a GPIO ISR after every change.  Note that during the ISR, the\r
101  * value of the GPIO is not stable and it can not be used.  All you can do from\r
102  * this hook is wake-up some task, which will call FF_SDDiskDetect().\r
103  */\r
104 extern void vApplicationCardDetectChangeHookFromISR( BaseType_t *pxHigherPriorityTaskWoken );\r
105 \r
106 /*\r
107  * Hardware initialisation.\r
108  */\r
109 static void prvSDIO_SD_Init( void );\r
110 static void vGPIO_SD_Init( SD_HandleTypeDef* xSDHandle );\r
111 \r
112 /*\r
113  * Check if the card is present, and if so, print out some info on the card.\r
114  */\r
115 static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber );\r
116 \r
117 #if( SDIO_USES_DMA != 0 )\r
118         /*\r
119          * Initialise the DMA for SDIO cards.\r
120          */\r
121         static void prvSDIO_DMA_Init( void );\r
122 #endif\r
123 \r
124 #if( SDIO_USES_DMA != 0 )\r
125         /*\r
126          * A function will be called at the start of a DMA action.\r
127          */\r
128         static void prvEventSetupFunction( SD_HandleTypeDef * pxHandle );\r
129 #endif\r
130 \r
131 #if( SDIO_USES_DMA != 0 )\r
132         /*\r
133          * This function is supposed to wait for an event: SDIO or DMA.\r
134          * Return non-zero if a timeout has been reached.\r
135          */\r
136         static uint32_t prvEventWaitFunction( SD_HandleTypeDef *pxHandle );\r
137 #endif\r
138 \r
139 /*-----------------------------------------------------------*/\r
140 \r
141 typedef struct\r
142 {\r
143         /* Only after a card has been inserted, debouncing is necessary. */\r
144         TickType_t xRemainingTime;\r
145         TimeOut_t xTimeOut;\r
146         UBaseType_t\r
147                 bLastPresent : 1,\r
148                 bStableSignal : 1;\r
149 } CardDetect_t;\r
150 \r
151 /* Used to handle timeouts. */\r
152 static TickType_t xDMARemainingTime;\r
153 static TimeOut_t xDMATimeOut;\r
154 \r
155 /* Used to unblock the task that calls prvEventWaitFunction() after an event has\r
156 occurred. */\r
157 static SemaphoreHandle_t xSDCardSemaphore = NULL;\r
158 \r
159 /* Handle of the SD card being used. */\r
160 static SD_HandleTypeDef xSDHandle;\r
161 \r
162 /* Holds parameters for the detected SD card. */\r
163 static HAL_SD_CardInfoTypedef xSDCardInfo;\r
164 \r
165 /* Mutex for partition. */\r
166 static SemaphoreHandle_t xPlusFATMutex = NULL;\r
167 \r
168 /* Remembers if the card is currently considered to be present. */\r
169 static BaseType_t xSDCardStatus = pdFALSE;\r
170 \r
171 /* Maintains state for card detection. */\r
172 static CardDetect_t xCardDetect;\r
173 \r
174 /*-----------------------------------------------------------*/\r
175 \r
176 static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
177 {\r
178 int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG;\r
179 \r
180         if( ( pxDisk != NULL ) &&\r
181                 ( xSDCardStatus == pdPASS ) &&\r
182                 ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
183                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
184                 ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
185                 ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
186         {\r
187         uint64_t ullReadAddr;\r
188         HAL_SD_ErrorTypedef sd_result;\r
189 \r
190                 ullReadAddr = 512ull * ( uint64_t ) ulSectorNumber;\r
191 \r
192                 #if( SDIO_USES_DMA == 0 )\r
193                 {\r
194                         sd_result = HAL_SD_ReadBlocks( &xSDHandle, (uint32_t *) pucBuffer, ullReadAddr, 512ul, ulSectorCount );\r
195                 }\r
196                 #else\r
197                 {\r
198                         if( ( ( ( size_t )pucBuffer ) & ( sizeof( size_t ) - 1 ) ) == 0 )\r
199                         {\r
200                                 /* The buffer is word-aligned, call DMA read directly. */\r
201                                 sd_result = HAL_SD_ReadBlocks_DMA( &xSDHandle, (uint32_t *) pucBuffer, ullReadAddr, 512ul, ulSectorCount);\r
202                                 if( sd_result == SD_OK )\r
203                                 {\r
204                                         sd_result = HAL_SD_CheckReadOperation( &xSDHandle, sdMAX_TIME_TICKS );\r
205                                 }\r
206                         }\r
207                         else\r
208                         {\r
209                         uint32_t ulSector;\r
210                         uint8_t *pucDMABuffer = ffconfigMALLOC( 512ul );\r
211 \r
212                                 /* The buffer is NOT word-aligned, copy first to an aligned buffer. */\r
213                                 if( pucDMABuffer != NULL )\r
214                                 {\r
215                                         sd_result = SD_OK;\r
216                                         for( ulSector = 0; ulSector < ulSectorCount; ulSector++ )\r
217                                         {\r
218                                                 ullReadAddr = 512ull * ( ( uint64_t ) ulSectorNumber + ( uint64_t ) ulSector );\r
219                                                 sd_result = HAL_SD_ReadBlocks_DMA( &xSDHandle, ( uint32_t * )pucDMABuffer, ullReadAddr, 512ul, 1 );\r
220 \r
221                                                 if( sd_result == SD_OK )\r
222                                                 {\r
223                                                         sd_result = HAL_SD_CheckReadOperation( &xSDHandle, sdMAX_TIME_TICKS );\r
224                                                         if( sd_result != SD_OK )\r
225                                                         {\r
226                                                                 break;\r
227                                                         }\r
228                                                         memcpy( pucBuffer + 512ul * ulSector, pucDMABuffer, 512ul );\r
229                                                 }\r
230                                         }\r
231                                         ffconfigFREE( pucDMABuffer );\r
232                                 }\r
233                                 else\r
234                                 {\r
235                                         sd_result = SD_INVALID_PARAMETER;\r
236                                 }\r
237                         }\r
238                 }\r
239                 #endif  /* SDIO_USES_DMA */\r
240 \r
241                 if( sd_result == SD_OK )\r
242                 {\r
243                         lReturnCode = 0L;\r
244                 }\r
245                 else\r
246                 {\r
247                         /* Some error occurred. */\r
248                         FF_PRINTF( "prvFFRead: %lu: %u (%s)\n", ulSectorNumber, sd_result, prvSDCodePrintable( sd_result ) );\r
249                 }\r
250         }\r
251         else\r
252         {\r
253                 /* Make sure no random data is in the returned buffer. */\r
254                 memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512UL );\r
255 \r
256                 if( pxDisk->xStatus.bIsInitialised != pdFALSE )\r
257                 {\r
258                         FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
259                 }\r
260         }\r
261 \r
262         return lReturnCode;\r
263 }\r
264 /*-----------------------------------------------------------*/\r
265 \r
266 static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )\r
267 {\r
268 int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG;\r
269 \r
270         if( ( pxDisk != NULL ) &&\r
271                 ( xSDCardStatus == pdPASS ) &&\r
272                 ( pxDisk->ulSignature == sdSIGNATURE ) &&\r
273                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
274                 ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&\r
275                 ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )\r
276         {\r
277                 HAL_SD_ErrorTypedef sd_result;\r
278                 uint64_t ullWriteAddr;\r
279                 ullWriteAddr = 512ull * ulSectorNumber;\r
280 \r
281                 #if( SDIO_USES_DMA == 0 )\r
282                 {\r
283                         sd_result = HAL_SD_WriteBlocks( &xSDHandle, ( uint32_t * )pucBuffer, ullWriteAddr, 512ul, ulSectorCount );\r
284                 }\r
285                 #else\r
286                 {\r
287                         if( ( ( ( size_t )pucBuffer ) & ( sizeof( size_t ) - 1 ) ) == 0 )\r
288                         {\r
289                                 /* The buffer is word-aligned, call DMA reawrite directly. */\r
290                                 sd_result = HAL_SD_WriteBlocks_DMA( &xSDHandle, ( uint32_t * )pucBuffer, ullWriteAddr, 512ul, ulSectorCount );\r
291                                 if( sd_result == SD_OK )\r
292                                 {\r
293                                         sd_result = HAL_SD_CheckWriteOperation( &xSDHandle, sdMAX_TIME_TICKS );\r
294                                 }\r
295                         }\r
296                         else\r
297                         {\r
298                         uint32_t ulSector;\r
299                         uint8_t *pucDMABuffer = ffconfigMALLOC( 512ul );\r
300 \r
301                                 /* The buffer is NOT word-aligned, read to an aligned buffer and then\r
302                                 copy the data to the user provided buffer. */\r
303                                 if( pucDMABuffer != NULL )\r
304                                 {\r
305                                         sd_result = SD_OK;\r
306                                         for( ulSector = 0; ulSector < ulSectorCount; ulSector++ )\r
307                                         {\r
308                                                 memcpy( pucDMABuffer, pucBuffer + 512ul * ulSector, 512ul );\r
309                                                 ullWriteAddr = 512ull * ( ulSectorNumber + ulSector );\r
310                                                 sd_result = HAL_SD_WriteBlocks_DMA( &xSDHandle, ( uint32_t * )pucDMABuffer, ullWriteAddr, 512ul, 1 );\r
311                                                 if( sd_result == SD_OK )\r
312                                                 {\r
313                                                         sd_result = HAL_SD_CheckWriteOperation( &xSDHandle, sdMAX_TIME_TICKS );\r
314                                                         if( sd_result != SD_OK )\r
315                                                         {\r
316                                                                 break;\r
317                                                         }\r
318                                                 }\r
319                                         }\r
320                                         ffconfigFREE( pucDMABuffer );\r
321                                 }\r
322                                 else\r
323                                 {\r
324                                         sd_result = SD_INVALID_PARAMETER;\r
325                                 }\r
326                         }\r
327                 }\r
328                 #endif  /* SDIO_USES_DMA */\r
329 \r
330                 if( sd_result == SD_OK )\r
331                 {\r
332                         /* No errors. */\r
333                         lReturnCode = 0L;\r
334                 }\r
335                 else\r
336                 {\r
337                         FF_PRINTF( "prvFFWrite: %lu: %u (%s)\n", ulSectorNumber, sd_result, prvSDCodePrintable( sd_result ) );\r
338                 }\r
339         }\r
340         else\r
341         {\r
342                 if( pxDisk->xStatus.bIsInitialised != pdFALSE )\r
343                 {\r
344                         FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );\r
345                 }\r
346         }\r
347 \r
348         return lReturnCode;\r
349 }\r
350 /*-----------------------------------------------------------*/\r
351 \r
352 void FF_SDDiskFlush( FF_Disk_t *pxDisk )\r
353 {\r
354         if( ( pxDisk != NULL ) &&\r
355                 ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&\r
356                 ( pxDisk->pxIOManager != NULL ) )\r
357         {\r
358                 FF_FlushCache( pxDisk->pxIOManager );\r
359         }\r
360 }\r
361 /*-----------------------------------------------------------*/\r
362 \r
363 static void vGPIO_SD_Init(SD_HandleTypeDef* xSDHandle)\r
364 {\r
365 GPIO_InitTypeDef GPIO_InitStruct;\r
366 \r
367         if( xSDHandle->Instance == SDIO )\r
368         {\r
369                 /* Peripheral clock enable */\r
370                 __SDIO_CLK_ENABLE();\r
371 \r
372                 /**SDIO GPIO Configuration\r
373                 PC8     ------> SDIO_D0\r
374                 PC9     ------> SDIO_D1\r
375                 PC10    ------> SDIO_D2\r
376                 PC11    ------> SDIO_D3\r
377                 PC12    ------> SDIO_CK\r
378                 PD2     ------> SDIO_CMD\r
379                 */\r
380                 __HAL_RCC_GPIOC_CLK_ENABLE();\r
381                 #if( BUS_4BITS != 0 )\r
382                 {\r
383                         GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;\r
384                 }\r
385                 #else\r
386                 {\r
387                         GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_12;\r
388                 }\r
389                 #endif\r
390                 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;\r
391                 GPIO_InitStruct.Pull = GPIO_NOPULL;\r
392                 GPIO_InitStruct.Speed = GPIO_SPEED_FAST;\r
393                 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;\r
394                 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);\r
395 \r
396                 __HAL_RCC_GPIOD_CLK_ENABLE();\r
397                 GPIO_InitStruct.Pin = GPIO_PIN_2;\r
398                 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;\r
399                 GPIO_InitStruct.Pull = GPIO_NOPULL;\r
400                 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;\r
401                 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;\r
402                 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);\r
403         }\r
404 }\r
405 /*-----------------------------------------------------------*/\r
406 \r
407 FF_Disk_t *FF_SDDiskInit( const char *pcName )\r
408 {\r
409 FF_Error_t xFFError;\r
410 BaseType_t xPartitionNumber = 0;\r
411 FF_CreationParameters_t xParameters;\r
412 FF_Disk_t *pxDisk;\r
413 \r
414         xSDCardStatus = prvSDMMCInit( 0 );\r
415 \r
416         if( xSDCardStatus != pdPASS )\r
417         {\r
418                 FF_PRINTF( "FF_SDDiskInit: prvSDMMCInit failed\n" );\r
419                 pxDisk = NULL;\r
420         }\r
421         else\r
422         {\r
423                 pxDisk = (FF_Disk_t *)ffconfigMALLOC( sizeof( *pxDisk ) );\r
424                 if( pxDisk == NULL )\r
425                 {\r
426                         FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );\r
427                 }\r
428                 else\r
429                 {\r
430                         /* Initialise the created disk structure. */\r
431                         memset( pxDisk, '\0', sizeof( *pxDisk ) );\r
432 \r
433                         pxDisk->ulNumberOfSectors = xSDCardInfo.CardCapacity / 512;\r
434 \r
435                         if( xPlusFATMutex == NULL )\r
436                         {\r
437                                 xPlusFATMutex = xSemaphoreCreateRecursiveMutex();\r
438                         }\r
439                         pxDisk->ulSignature = sdSIGNATURE;\r
440 \r
441                         if( xPlusFATMutex != NULL)\r
442                         {\r
443                                 memset( &xParameters, '\0', sizeof( xParameters ) );\r
444                                 xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;\r
445                                 xParameters.ulSectorSize = 512;\r
446                                 xParameters.fnWriteBlocks = prvFFWrite;\r
447                                 xParameters.fnReadBlocks = prvFFRead;\r
448                                 xParameters.pxDisk = pxDisk;\r
449 \r
450                                 /* prvFFRead()/prvFFWrite() are not re-entrant and must be\r
451                                 protected with the use of a semaphore. */\r
452                                 xParameters.xBlockDeviceIsReentrant = pdFALSE;\r
453 \r
454                                 /* The semaphore will be used to protect critical sections in\r
455                                 the +FAT driver, and also to avoid concurrent calls to\r
456                                 prvFFRead()/prvFFWrite() from different tasks. */\r
457                                 xParameters.pvSemaphore = ( void * ) xPlusFATMutex;\r
458 \r
459                                 pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );\r
460 \r
461                                 if( pxDisk->pxIOManager == NULL )\r
462                                 {\r
463                                         FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", (const char*)FF_GetErrMessage( xFFError ) );\r
464                                         FF_SDDiskDelete( pxDisk );\r
465                                         pxDisk = NULL;\r
466                                 }\r
467                                 else\r
468                                 {\r
469                                         pxDisk->xStatus.bIsInitialised = pdTRUE;\r
470                                         pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
471                                         if( FF_SDDiskMount( pxDisk ) == 0 )\r
472                                         {\r
473                                                 FF_SDDiskDelete( pxDisk );\r
474                                                 pxDisk = NULL;\r
475                                         }\r
476                                         else\r
477                                         {\r
478                                                 if( pcName == NULL )\r
479                                                 {\r
480                                                         pcName = "/";\r
481                                                 }\r
482                                                 FF_FS_Add( pcName, pxDisk );\r
483                                                 FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );\r
484                                                 FF_SDDiskShowPartition( pxDisk );\r
485                                         }\r
486                                 }       /* if( pxDisk->pxIOManager != NULL ) */\r
487                         }       /* if( xPlusFATMutex != NULL) */\r
488                 }       /* if( pxDisk != NULL ) */\r
489         }       /* if( xSDCardStatus == pdPASS ) */\r
490 \r
491         return pxDisk;\r
492 }\r
493 /*-----------------------------------------------------------*/\r
494 \r
495 BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber )\r
496 {\r
497 FF_Error_t xError;\r
498 BaseType_t xReturn = pdFAIL;\r
499 \r
500         xError = FF_Unmount( pxDisk );\r
501 \r
502         if( FF_isERR( xError ) != pdFALSE )\r
503         {\r
504                 FF_PRINTF( "FF_SDDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );\r
505         }\r
506         else\r
507         {\r
508                 /* Format the drive - try FAT32 with large clusters. */\r
509                 xError = FF_Format( pxDisk, xPartitionNumber, pdFALSE, pdFALSE);\r
510 \r
511                 if( FF_isERR( xError ) )\r
512                 {\r
513                         FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );\r
514                 }\r
515                 else\r
516                 {\r
517                         FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );\r
518                         pxDisk->xStatus.bPartitionNumber = xPartitionNumber;\r
519                         xError = FF_SDDiskMount( pxDisk );\r
520                         FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );\r
521                         if( FF_isERR( xError ) == pdFALSE )\r
522                         {\r
523                                 xReturn = pdPASS;\r
524                                 FF_SDDiskShowPartition( pxDisk );\r
525                         }\r
526                 }\r
527         }\r
528 \r
529         return xReturn;\r
530 }\r
531 /*-----------------------------------------------------------*/\r
532 \r
533 BaseType_t FF_SDDiskUnmount( FF_Disk_t *pxDisk )\r
534 {\r
535 FF_Error_t xFFError;\r
536 BaseType_t xReturn = pdPASS;\r
537 \r
538         if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsMounted != pdFALSE ) )\r
539         {\r
540                 pxDisk->xStatus.bIsMounted = pdFALSE;\r
541                 xFFError = FF_Unmount( pxDisk );\r
542 \r
543                 if( FF_isERR( xFFError ) )\r
544                 {\r
545                         FF_PRINTF( "FF_SDDiskUnmount: rc %08x\n", ( unsigned )xFFError );\r
546                         xReturn = pdFAIL;\r
547                 }\r
548                 else\r
549                 {\r
550                         FF_PRINTF( "Drive unmounted\n" );\r
551                 }\r
552         }\r
553 \r
554         return xReturn;\r
555 }\r
556 /*-----------------------------------------------------------*/\r
557 \r
558 BaseType_t FF_SDDiskReinit( FF_Disk_t *pxDisk )\r
559 {\r
560 BaseType_t xStatus = prvSDMMCInit( 0 ); /* Hard coded index. */\r
561 \r
562         /*_RB_ parameter not used. */\r
563         ( void ) pxDisk;\r
564 \r
565         FF_PRINTF( "FF_SDDiskReinit: rc %08x\n", ( unsigned ) xStatus );\r
566         return xStatus;\r
567 }\r
568 /*-----------------------------------------------------------*/\r
569 \r
570 BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )\r
571 {\r
572 FF_Error_t xFFError;\r
573 BaseType_t xReturn;\r
574 \r
575         /* Mount the partition */\r
576         xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );\r
577 \r
578         if( FF_isERR( xFFError ) )\r
579         {\r
580                 FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );\r
581                 xReturn = pdFAIL;\r
582         }\r
583         else\r
584         {\r
585                 pxDisk->xStatus.bIsMounted = pdTRUE;\r
586                 FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );\r
587                 xReturn = pdPASS;\r
588         }\r
589 \r
590         return xReturn;\r
591 }\r
592 /*-----------------------------------------------------------*/\r
593 \r
594 FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )\r
595 {\r
596 FF_IOManager_t *pxReturn;\r
597 \r
598         if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )\r
599         {\r
600                 pxReturn = pxDisk->pxIOManager;\r
601         }\r
602         else\r
603         {\r
604                 pxReturn = NULL;\r
605         }\r
606         return pxReturn;\r
607 }\r
608 /*-----------------------------------------------------------*/\r
609 \r
610 /* Release all resources */\r
611 BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )\r
612 {\r
613         if( pxDisk != NULL )\r
614         {\r
615                 pxDisk->ulSignature = 0;\r
616                 pxDisk->xStatus.bIsInitialised = 0;\r
617                 if( pxDisk->pxIOManager != NULL )\r
618                 {\r
619                         if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )\r
620                         {\r
621                                 FF_Unmount( pxDisk );\r
622                         }\r
623                         FF_DeleteIOManager( pxDisk->pxIOManager );\r
624                 }\r
625 \r
626                 vPortFree( pxDisk );\r
627         }\r
628         return 1;\r
629 }\r
630 /*-----------------------------------------------------------*/\r
631 \r
632 BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )\r
633 {\r
634 FF_Error_t xError;\r
635 uint64_t ullFreeSectors;\r
636 uint32_t ulTotalSizeMB, ulFreeSizeMB;\r
637 int iPercentageFree;\r
638 FF_IOManager_t *pxIOManager;\r
639 const char *pcTypeName = "unknown type";\r
640 BaseType_t xReturn = pdPASS;\r
641 \r
642         if( pxDisk == NULL )\r
643         {\r
644                 xReturn = pdFAIL;\r
645         }\r
646         else\r
647         {\r
648                 pxIOManager = pxDisk->pxIOManager;\r
649 \r
650                 FF_PRINTF( "Reading FAT and calculating Free Space\n" );\r
651 \r
652                 switch( pxIOManager->xPartition.ucType )\r
653                 {\r
654                         case FF_T_FAT12:\r
655                                 pcTypeName = "FAT12";\r
656                                 break;\r
657 \r
658                         case FF_T_FAT16:\r
659                                 pcTypeName = "FAT16";\r
660                                 break;\r
661 \r
662                         case FF_T_FAT32:\r
663                                 pcTypeName = "FAT32";\r
664                                 break;\r
665 \r
666                         default:\r
667                                 pcTypeName = "UNKOWN";\r
668                                 break;\r
669                 }\r
670 \r
671                 FF_GetFreeSize( pxIOManager, &xError );\r
672 \r
673                 ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;\r
674                 iPercentageFree = ( int ) ( ( sdHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /\r
675                         ( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );\r
676 \r
677                 ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sdSECTORS_PER_MB;\r
678                 ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sdSECTORS_PER_MB );\r
679 \r
680                 /* It is better not to use the 64-bit format such as %Lu because it\r
681                 might not be implemented. */\r
682                 FF_PRINTF( "Partition Nr   %8u\n", pxDisk->xStatus.bPartitionNumber );\r
683                 FF_PRINTF( "Type           %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );\r
684                 FF_PRINTF( "VolLabel       '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );\r
685                 FF_PRINTF( "TotalSectors   %8lu\n", pxIOManager->xPartition.ulTotalSectors );\r
686                 FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );\r
687                 FF_PRINTF( "Size           %8lu MB\n", ulTotalSizeMB );\r
688                 FF_PRINTF( "FreeSize       %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );\r
689         }\r
690 \r
691         return xReturn;\r
692 }\r
693 /*-----------------------------------------------------------*/\r
694 \r
695 /* SDIO init function */\r
696 static void prvSDIO_SD_Init( void )\r
697 {\r
698         xSDHandle.Instance = SDIO;\r
699         xSDHandle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;\r
700         xSDHandle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;\r
701         xSDHandle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;\r
702 \r
703         /* Start as a 1-bit bus and switch to 4-bits later on. */\r
704         xSDHandle.Init.BusWide = SDIO_BUS_WIDE_1B;\r
705 \r
706         xSDHandle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;\r
707 \r
708         /* Use fastest CLOCK at 0. */\r
709         xSDHandle.Init.ClockDiv = 32;\r
710 \r
711         #if( SDIO_USES_DMA != 0 )\r
712         {\r
713                 xSDHandle.EventSetupFunction = prvEventSetupFunction;\r
714                 xSDHandle.EventWaitFunction = prvEventWaitFunction;\r
715         }\r
716         #else\r
717         {\r
718                 xSDHandle.EventSetupFunction = NULL;\r
719                 xSDHandle.EventWaitFunction = NULL;\r
720         }\r
721         #endif\r
722         __HAL_RCC_SDIO_CLK_ENABLE( );\r
723 }\r
724 /*-----------------------------------------------------------*/\r
725 \r
726 /* This routine returns true if the SD-card is inserted.  After insertion, it\r
727 will wait for sdCARD_DETECT_DEBOUNCE_TIME_MS before returning pdTRUE. */\r
728 BaseType_t FF_SDDiskDetect( FF_Disk_t *pxDisk )\r
729 {\r
730 int xReturn;\r
731 \r
732         xReturn = prvSDDetect();\r
733 \r
734         if( xReturn != pdFALSE )\r
735         {\r
736                 if( xCardDetect.bStableSignal == pdFALSE )\r
737                 {\r
738                         /* The card seems to be present. */\r
739                         if( xCardDetect.bLastPresent == pdFALSE )\r
740                         {\r
741                                 xCardDetect.bLastPresent = pdTRUE;\r
742                                 xCardDetect.xRemainingTime = pdMS_TO_TICKS( ( TickType_t ) sdCARD_DETECT_DEBOUNCE_TIME_MS );\r
743                                 /* Fetch the current time. */\r
744                                 vTaskSetTimeOutState( &xCardDetect.xTimeOut );\r
745                         }\r
746                         /* Has the timeout been reached? */\r
747                         if( xTaskCheckForTimeOut( &xCardDetect.xTimeOut, &xCardDetect.xRemainingTime ) != pdFALSE )\r
748                         {\r
749                                 xCardDetect.bStableSignal = pdTRUE;\r
750                         }\r
751                         else\r
752                         {\r
753                                 /* keep returning false until de time-out is reached. */\r
754                                 xReturn = pdFALSE;\r
755                         }\r
756                 }\r
757         }\r
758         else\r
759         {\r
760                 xCardDetect.bLastPresent = pdFALSE;\r
761                 xCardDetect.bStableSignal = pdFALSE;\r
762         }\r
763 \r
764         return xReturn;\r
765 }\r
766 /*-----------------------------------------------------------*/\r
767 \r
768 /* Raw SD-card detection, just return the GPIO status. */\r
769 static BaseType_t prvSDDetect( void )\r
770 {\r
771 int iReturn;\r
772 \r
773         /*!< Check GPIO to detect SD */\r
774         if( HAL_GPIO_ReadPin( configSD_DETECT_GPIO_PORT, configSD_DETECT_PIN ) != 0 )\r
775         {\r
776                 /* The internal pull-up makes the signal high. */\r
777                 iReturn = pdFALSE;\r
778         }\r
779         else\r
780         {\r
781                 /* The card will pull the GPIO signal down. */\r
782                 iReturn = pdTRUE;\r
783         }\r
784 \r
785         return iReturn;\r
786 }\r
787 /*-----------------------------------------------------------*/\r
788 \r
789 static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber )\r
790 {\r
791         /* 'xDriveNumber' not yet in use. */\r
792         ( void )xDriveNumber;\r
793 \r
794         if( xSDCardSemaphore == NULL )\r
795         {\r
796                 xSDCardSemaphore = xSemaphoreCreateBinary();\r
797         }\r
798         prvSDIO_SD_Init();\r
799 \r
800         vGPIO_SD_Init( &xSDHandle );\r
801 \r
802         #if( SDIO_USES_DMA != 0 )\r
803         {\r
804                 prvSDIO_DMA_Init( );\r
805         }\r
806         #endif\r
807 \r
808         int SD_state = SD_OK;\r
809         /* Check if the SD card is plugged in the slot */\r
810         if( prvSDDetect() == pdFALSE )\r
811         {\r
812                 FF_PRINTF( "No SD card detected\n" );\r
813                 return 0;\r
814         }\r
815         /* When starting up, skip debouncing of the Card Detect signal. */\r
816         xCardDetect.bLastPresent = pdTRUE;\r
817         xCardDetect.bStableSignal = pdTRUE;\r
818         /* Initialise the SDIO device and read the card parameters. */\r
819         SD_state = HAL_SD_Init( &xSDHandle, &xSDCardInfo );\r
820         #if( BUS_4BITS != 0 )\r
821     {\r
822                 if( SD_state == SD_OK )\r
823                 {\r
824                         HAL_SD_ErrorTypedef rc;\r
825 \r
826                         xSDHandle.Init.BusWide = SDIO_BUS_WIDE_4B;\r
827                         rc = HAL_SD_WideBusOperation_Config(&xSDHandle, SDIO_BUS_WIDE_4B);\r
828                         if( rc != SD_OK )\r
829                         {\r
830                                 FF_PRINTF( "HAL_SD_WideBus: %d: %s\n", rc, prvSDCodePrintable( ( uint32_t )rc ) );\r
831                         }\r
832                 }\r
833     }\r
834         #endif\r
835         FF_PRINTF( "HAL_SD_Init: %d: %s type: %s Capacity: %lu MB\n",\r
836                 SD_state,\r
837                 prvSDCodePrintable( ( uint32_t )SD_state ),\r
838                 xSDHandle.CardType == HIGH_CAPACITY_SD_CARD ? "SDHC" : "SD",\r
839                 xSDCardInfo.CardCapacity / ( 1024 * 1024 ) );\r
840 \r
841         return SD_state == SD_OK ? 1 : 0;\r
842 }\r
843 /*-----------------------------------------------------------*/\r
844 \r
845 struct xCODE_NAME\r
846 {\r
847         uint32_t ulValue;\r
848         const char *pcName;\r
849 };\r
850 \r
851 const struct xCODE_NAME xSD_CODES[] =\r
852 {\r
853         { SD_CMD_CRC_FAIL,          "CMD_CRC_FAIL: Command response received (but CRC check failed)" },\r
854         { SD_DATA_CRC_FAIL,         "DATA_CRC_FAIL: Data block sent/received (CRC check failed)" },\r
855         { SD_CMD_RSP_TIMEOUT,       "CMD_RSP_TIMEOUT: Command response timeout" },\r
856         { SD_DATA_TIMEOUT,          "DATA_TIMEOUT: Data timeout" },\r
857         { SD_TX_UNDERRUN,           "TX_UNDERRUN: Transmit FIFO underrun" },\r
858         { SD_RX_OVERRUN,            "RX_OVERRUN: Receive FIFO overrun" },\r
859         { SD_START_BIT_ERR,         "START_BIT_ERR: Start bit not detected on all data signals in wide bus mode" },\r
860         { SD_CMD_OUT_OF_RANGE,      "CMD_OUT_OF_RANGE: Command's argument was out of range" },\r
861         { SD_ADDR_MISALIGNED,       "ADDR_MISALIGNED: Misaligned address" },\r
862         { SD_BLOCK_LEN_ERR,         "BLOCK_LEN_ERR: Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length" },\r
863         { SD_ERASE_SEQ_ERR,         "ERASE_SEQ_ERR: An error in the sequence of erase command occurs." },\r
864         { SD_BAD_ERASE_PARAM,       "BAD_ERASE_PARAM: An invalid selection for erase groups" },\r
865         { SD_WRITE_PROT_VIOLATION,  "WRITE_PROT_VIOLATION: Attempt to program a write protect block" },\r
866         { SD_LOCK_UNLOCK_FAILED,    "LOCK_UNLOCK_FAILED: Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card" },\r
867         { SD_COM_CRC_FAILED,        "COM_CRC_FAILED: CRC check of the previous command failed" },\r
868         { SD_ILLEGAL_CMD,           "ILLEGAL_CMD: Command is not legal for the card state" },\r
869         { SD_CARD_ECC_FAILED,       "CARD_ECC_FAILED: Card internal ECC was applied but failed to correct the data" },\r
870         { SD_CC_ERROR,              "CC_ERROR: Internal card controller error" },\r
871         { SD_GENERAL_UNKNOWN_ERROR, "GENERAL_UNKNOWN_ERROR: General or unknown error" },\r
872         { SD_STREAM_READ_UNDERRUN,  "STREAM_READ_UNDERRUN: The card could not sustain data transfer in stream read operation" },\r
873         { SD_STREAM_WRITE_OVERRUN,  "STREAM_WRITE_OVERRUN: The card could not sustain data programming in stream mode" },\r
874         { SD_CID_CSD_OVERWRITE,     "CID_CSD_OVERWRITE: CID/CSD overwrite error" },\r
875         { SD_WP_ERASE_SKIP,         "WP_ERASE_SKIP: Only partial address space was erased" },\r
876         { SD_CARD_ECC_DISABLED,     "CARD_ECC_DISABLED: Command has been executed without using internal ECC" },\r
877         { SD_ERASE_RESET,           "ERASE_RESET: Erase sequence was cleared before executing because an out of erase sequence command was received" },\r
878         { SD_AKE_SEQ_ERROR,         "AKE_SEQ_ERROR: Error in sequence of authentication" },\r
879         { SD_INVALID_VOLTRANGE,     "INVALID_VOLTRANGE" },\r
880         { SD_ADDR_OUT_OF_RANGE,     "ADDR_OUT_OF_RANGE" },\r
881         { SD_SWITCH_ERROR,          "SWITCH_ERROR" },\r
882         { SD_SDIO_DISABLED,         "SDIO_DISABLED" },\r
883         { SD_SDIO_FUNCTION_BUSY,    "SDIO_FUNCTION_BUSY" },\r
884         { SD_SDIO_FUNCTION_FAILED,  "SDIO_FUNCTION_FAILED" },\r
885         { SD_SDIO_UNKNOWN_FUNCTION, "SDIO_UNKNOWN_FUNCTION" },\r
886 \r
887         /**\r
888         * @brief  Standard error defines\r
889         */\r
890         { SD_INTERNAL_ERROR,        "INTERNAL_ERROR" },\r
891         { SD_NOT_CONFIGURED,        "NOT_CONFIGURED" },\r
892         { SD_REQUEST_PENDING,       "REQUEST_PENDING" },\r
893         { SD_REQUEST_NOT_APPLICABLE,"REQUEST_NOT_APPLICABLE" },\r
894         { SD_INVALID_PARAMETER,     "INVALID_PARAMETER" },\r
895         { SD_UNSUPPORTED_FEATURE,   "UNSUPPORTED_FEATURE" },\r
896         { SD_UNSUPPORTED_HW,        "UNSUPPORTED_HW" },\r
897         { SD_ERROR,                 "ERROR" },\r
898         { SD_OK,                    "OK" },\r
899 };\r
900 /*-----------------------------------------------------------*/\r
901 \r
902 static const char *prvSDCodePrintable( uint32_t ulCode )\r
903 {\r
904 static char retString[32];\r
905 const struct xCODE_NAME *pxCode;\r
906 \r
907         for( pxCode = xSD_CODES; pxCode <= xSD_CODES + sdARRAY_SIZE( xSD_CODES ) - 1; pxCode++ )\r
908         {\r
909                 if( pxCode->ulValue == ulCode )\r
910                 {\r
911                         return pxCode->pcName;\r
912                 }\r
913         }\r
914         snprintf( retString, sizeof( retString ), "SD code %lu\n", ulCode );\r
915         return retString;\r
916 }\r
917 /*-----------------------------------------------------------*/\r
918 \r
919 #if( SDIO_USES_DMA != 0 )\r
920 \r
921         static void prvSDIO_DMA_Init( void )\r
922         {\r
923         static DMA_HandleTypeDef xRxDMAHandle;\r
924         static DMA_HandleTypeDef xTxDMAHandle;\r
925 \r
926                 /* Enable DMA2 clocks */\r
927                 __DMAx_TxRx_CLK_ENABLE();\r
928 \r
929                 /* NVIC configuration for SDIO interrupts */\r
930                 HAL_NVIC_SetPriority(SDIO_IRQn, configSDIO_DMA_INTERRUPT_PRIORITY, 0);\r
931                 HAL_NVIC_EnableIRQ(SDIO_IRQn);\r
932 \r
933                 /* Configure DMA Rx parameters */\r
934                 xRxDMAHandle.Init.Channel             = SD_DMAx_Rx_CHANNEL;\r
935                 xRxDMAHandle.Init.Direction           = DMA_PERIPH_TO_MEMORY;\r
936                 /* Peripheral address is fixed (FIFO). */\r
937                 xRxDMAHandle.Init.PeriphInc           = DMA_PINC_DISABLE;\r
938                 /* Memory address increases. */\r
939                 xRxDMAHandle.Init.MemInc              = DMA_MINC_ENABLE;\r
940                 xRxDMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;\r
941                 xRxDMAHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;\r
942                 /* The peripheral has flow-control. */\r
943                 xRxDMAHandle.Init.Mode                = DMA_PFCTRL;\r
944                 xRxDMAHandle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;\r
945                 xRxDMAHandle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;\r
946                 xRxDMAHandle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;\r
947                 xRxDMAHandle.Init.MemBurst            = DMA_MBURST_INC4;\r
948                 xRxDMAHandle.Init.PeriphBurst         = DMA_PBURST_INC4;\r
949 \r
950                 /* DMA2_Stream3. */\r
951                 xRxDMAHandle.Instance = SD_DMAx_Rx_STREAM;\r
952 \r
953                 /* Associate the DMA handle */\r
954                 __HAL_LINKDMA(&xSDHandle, hdmarx, xRxDMAHandle);\r
955 \r
956                 /* Deinitialize the stream for new transfer */\r
957                 HAL_DMA_DeInit(&xRxDMAHandle);\r
958 \r
959                 /* Configure the DMA stream */\r
960                 HAL_DMA_Init(&xRxDMAHandle);\r
961 \r
962                 /* Configure DMA Tx parameters */\r
963                 xTxDMAHandle.Init.Channel             = SD_DMAx_Tx_CHANNEL;\r
964                 xTxDMAHandle.Init.Direction           = DMA_MEMORY_TO_PERIPH;\r
965                 xTxDMAHandle.Init.PeriphInc           = DMA_PINC_DISABLE;\r
966                 xTxDMAHandle.Init.MemInc              = DMA_MINC_ENABLE;\r
967                 xTxDMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;\r
968                 xTxDMAHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;\r
969                 xTxDMAHandle.Init.Mode                = DMA_PFCTRL;\r
970                 xTxDMAHandle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;\r
971                 xTxDMAHandle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;\r
972                 xTxDMAHandle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;\r
973                 xTxDMAHandle.Init.MemBurst            = DMA_MBURST_SINGLE;\r
974                 xTxDMAHandle.Init.PeriphBurst         = DMA_PBURST_INC4;\r
975 \r
976                 /* DMA2_Stream6. */\r
977                 xTxDMAHandle.Instance = SD_DMAx_Tx_STREAM;\r
978 \r
979                 /* Associate the DMA handle */\r
980                 __HAL_LINKDMA(&xSDHandle, hdmatx, xTxDMAHandle);\r
981 \r
982                 /* Deinitialize the stream for new transfer */\r
983                 HAL_DMA_DeInit(&xTxDMAHandle);\r
984 \r
985                 /* Configure the DMA stream */\r
986                 HAL_DMA_Init(&xTxDMAHandle);\r
987 \r
988                 /* NVIC configuration for DMA transfer complete interrupt */\r
989                 HAL_NVIC_SetPriority(SD_DMAx_Rx_IRQn, configSDIO_DMA_INTERRUPT_PRIORITY + 2, 0);\r
990                 HAL_NVIC_EnableIRQ(SD_DMAx_Rx_IRQn);\r
991 \r
992                 /* NVIC configuration for DMA transfer complete interrupt */\r
993                 HAL_NVIC_SetPriority(SD_DMAx_Tx_IRQn, configSDIO_DMA_INTERRUPT_PRIORITY + 2, 0);\r
994                 HAL_NVIC_EnableIRQ(SD_DMAx_Tx_IRQn);\r
995         }\r
996 #endif  /* SDIO_USES_DMA */\r
997 /*-----------------------------------------------------------*/\r
998 \r
999 #if( SDIO_USES_DMA != 0 )\r
1000         void SDIO_IRQHandler(void)\r
1001         {\r
1002         BaseType_t xHigherPriorityTaskWoken = 0;\r
1003 \r
1004                 HAL_SD_IRQHandler( &xSDHandle );\r
1005                 if( xSDCardSemaphore != NULL )\r
1006                 {\r
1007                         xSemaphoreGiveFromISR( xSDCardSemaphore, &xHigherPriorityTaskWoken );\r
1008                 }\r
1009                 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
1010         }\r
1011 \r
1012 #endif  /* SDIO_USES_DMA */\r
1013 /*-----------------------------------------------------------*/\r
1014 \r
1015 #if( SDIO_USES_DMA != 0 )\r
1016 \r
1017         void DMA2_Stream6_IRQHandler(void)\r
1018         {\r
1019         BaseType_t xHigherPriorityTaskWoken = 0;\r
1020 \r
1021                 /* DMA SDIO-TX interrupt handler. */\r
1022                 HAL_DMA_IRQHandler (xSDHandle.hdmatx);\r
1023                 if( xSDCardSemaphore != NULL )\r
1024                 {\r
1025                         xSemaphoreGiveFromISR( xSDCardSemaphore, &xHigherPriorityTaskWoken );\r
1026                 }\r
1027                 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
1028         }\r
1029 \r
1030 #endif  /* SDIO_USES_DMA */\r
1031 /*-----------------------------------------------------------*/\r
1032 \r
1033 #if( SDIO_USES_DMA != 0 )\r
1034 \r
1035         void DMA2_Stream3_IRQHandler(void)\r
1036         {\r
1037         BaseType_t xHigherPriorityTaskWoken = 0;\r
1038 \r
1039                 /* DMA SDIO-RX interrupt handler. */\r
1040                 HAL_DMA_IRQHandler (xSDHandle.hdmarx);\r
1041                 if( xSDCardSemaphore != NULL )\r
1042                 {\r
1043                         xSemaphoreGiveFromISR( xSDCardSemaphore, &xHigherPriorityTaskWoken );\r
1044                 }\r
1045                 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
1046         }\r
1047 \r
1048 #endif  /* SDIO_USES_DMA */\r
1049 /*-----------------------------------------------------------*/\r
1050 \r
1051 #if( SDIO_USES_DMA != 0 )\r
1052 \r
1053         static void prvEventSetupFunction( SD_HandleTypeDef * pxHandle )\r
1054         {\r
1055                 /* A DMA transfer to or from the SD-card is about to start.\r
1056                 Reset the timers that will be used in prvEventWaitFunction() */\r
1057                 xDMARemainingTime = sdMAX_TIME_TICKS;\r
1058                 vTaskSetTimeOutState( &xDMATimeOut );\r
1059         }\r
1060 \r
1061 #endif  /* SDIO_USES_DMA != 0 */\r
1062 /*-----------------------------------------------------------*/\r
1063 \r
1064 #if( SDIO_USES_DMA != 0 )\r
1065 \r
1066         static uint32_t prvEventWaitFunction( SD_HandleTypeDef *pxHandle )\r
1067         {\r
1068         uint32_t ulReturn;\r
1069 \r
1070                 /*\r
1071                  * It was measured how quickly a DMA interrupt was received. It varied\r
1072                  * between 0 and 4 ms.\r
1073                  * <= 1 ms : 8047\r
1074                  * <= 2 ms : 1850\r
1075                  * <= 3 ms :   99\r
1076                  * <= 4 ms :   79\r
1077                  * >= 5 ms :    0 times\r
1078                  */\r
1079 \r
1080                 if( xTaskCheckForTimeOut( &xDMATimeOut, &xDMARemainingTime ) != pdFALSE )\r
1081                 {\r
1082                         /* The timeout has been reached, no need to block. */\r
1083                         ulReturn = 1UL;\r
1084                 }\r
1085                 else\r
1086                 {\r
1087                         /* The timeout has not been reached yet, block on the semaphore. */\r
1088                         xSemaphoreTake( xSDCardSemaphore, xDMARemainingTime );\r
1089                         if( xTaskCheckForTimeOut( &xDMATimeOut, &xDMARemainingTime ) != pdFALSE )\r
1090                         {\r
1091                                 ulReturn = 1UL;\r
1092                         }\r
1093                         else\r
1094                         {\r
1095                                 ulReturn = 0UL;\r
1096                         }\r
1097                 }\r
1098 \r
1099                 return ulReturn;\r
1100         }\r
1101 \r
1102 #endif  /* SDIO_USES_DMA != 0 */\r
1103 /*-----------------------------------------------------------*/\r
1104 \r
1105 void HAL_GPIO_EXTI_Callback( uint16_t GPIO_Pin )\r
1106 {\r
1107 BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
1108 \r
1109         if( GPIO_Pin == configSD_DETECT_PIN )\r
1110         {\r
1111                 vApplicationCardDetectChangeHookFromISR( &xHigherPriorityTaskWoken );\r
1112                 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
1113         }\r
1114 }\r
1115 /*-----------------------------------------------------------*/\r
1116 \r
1117 void EXTI15_10_IRQHandler( void )\r
1118 {\r
1119         HAL_GPIO_EXTI_IRQHandler( configSD_DETECT_PIN );        /* GPIO PIN H.13 */\r
1120 }\r
1121 /*-----------------------------------------------------------*/\r