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