ff_sfdisk.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /*
  2. * FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
  3. * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. * Authors include James Walmsley, Hein Tibosch and Richard Barry
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  7. * this software and associated documentation files (the "Software"), to deal in
  8. * the Software without restriction, including without limitation the rights to
  9. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10. * the Software, and to permit persons to whom the Software is furnished to do so,
  11. * subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. * https://www.FreeRTOS.org
  24. *
  25. */
  26. /* Standard includes. */
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <stdarg.h>
  30. #include <stdio.h>
  31. /* LPC18xx includes. */
  32. #include "chip.h"
  33. #include "board.h"
  34. /* FreeRTOS includes. */
  35. #include "FreeRTOS.h"
  36. #include "task.h"
  37. #include "semphr.h"
  38. #include "portmacro.h"
  39. /* FreeRTOS+FAT includes. */
  40. #include "ff_sfdisk.h"
  41. #include "ff_sys.h"
  42. #include "sfud.h"
  43. /* Misc definitions. */
  44. #define sfSIGNATURE 0x41404342UL
  45. #define sfHUNDRED_64_BIT ( 100ull )
  46. #define sfBYTES_PER_MB ( 1024ull * 1024ull )
  47. #define sfSECTOR_SIZE ( 4096ull )
  48. #define sfSECTORS_PER_MB ( sfBYTES_PER_MB / sfSECTOR_SIZE )
  49. #define sfIOMAN_MEM_SIZE 16384
  50. #define sfDISK_MEDIA_OFFSET OTA_MEDIA_OFFSET
  51. #define sfAligned( pvAddress ) ( ( ( ( size_t ) ( pvAddress ) ) & ( sizeof( size_t ) - 1 ) ) == 0 )
  52. /*-----------------------------------------------------------*/
  53. /*_RB_ Functions require comment blocks. */
  54. static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );
  55. static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );
  56. /*-----------------------------------------------------------*/
  57. /*_RB_ Variables require a comment block where appropriate. */
  58. static sfud_flash *sflash;
  59. static SemaphoreHandle_t xPlusFATMutex;
  60. /*-----------------------------------------------------------*/
  61. static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
  62. {
  63. int32_t iReturn;
  64. /*_RB_ Many of the comments in this file apply to other functions in the file. */
  65. if( ( pxDisk != NULL ) &&
  66. ( sflash != NULL ) &&
  67. ( pxDisk->ulSignature == sfSIGNATURE ) &&
  68. ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
  69. ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
  70. ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
  71. {
  72. iReturn = sfud_read(sflash, sfDISK_MEDIA_OFFSET + ulSectorNumber * sfSECTOR_SIZE,
  73. ulSectorCount * sfSECTOR_SIZE, pucBuffer);
  74. /*_RB_ I'm guessing 4096 is a sector size, but that needs to be clear.
  75. Is it defined in a header somewhere? If so we can do a search and
  76. replace in files on it as it seems to be used everywhere. */
  77. if( iReturn == 0 ) /*_RB_ Signed/unsigned mismatch (twice!) */
  78. {
  79. iReturn = FF_ERR_NONE;
  80. }
  81. else
  82. {
  83. /*_RB_ Signed number used to return bitmap (again below). */
  84. iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );
  85. }
  86. }
  87. else
  88. {
  89. memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );
  90. if( pxDisk->xStatus.bIsInitialised != 0 )
  91. {
  92. FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
  93. }
  94. iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );
  95. }
  96. return iReturn;
  97. }
  98. /*-----------------------------------------------------------*/
  99. static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
  100. {
  101. int32_t iReturn;
  102. if( ( pxDisk != NULL ) &&
  103. ( sflash != NULL ) &&
  104. ( pxDisk->ulSignature == sfSIGNATURE ) &&
  105. ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
  106. ( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
  107. ( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
  108. {
  109. iReturn = sfud_erase_write(sflash, sfDISK_MEDIA_OFFSET + ulSectorNumber * sfSECTOR_SIZE,
  110. ulSectorCount * sfSECTOR_SIZE, pucBuffer);
  111. if( iReturn == 0 ) /*_RB_ Signed/unsigned mismatch (twice!) */
  112. {
  113. iReturn = FF_ERR_NONE;
  114. }
  115. else
  116. {
  117. iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
  118. }
  119. }
  120. else
  121. {
  122. memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );
  123. if( pxDisk->xStatus.bIsInitialised )
  124. {
  125. FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
  126. }
  127. iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
  128. }
  129. return iReturn;
  130. }
  131. /*-----------------------------------------------------------*/
  132. void FF_SFDiskFlush( FF_Disk_t *pxDisk )
  133. {
  134. if( ( pxDisk != NULL ) &&
  135. ( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
  136. ( pxDisk->pxIOManager != NULL ) )
  137. {
  138. FF_FlushCache( pxDisk->pxIOManager );
  139. }
  140. }
  141. /*-----------------------------------------------------------*/
  142. #define sfHIDDEN_SECTOR_COUNT 8
  143. #define sfPRIMARY_PARTITIONS 1
  144. #define sfPARTITION_NUMBER 0 /* Only a single partition is used. */
  145. static FF_Error_t PartitionAndFormatSFDisk( FF_Disk_t * pxDisk )
  146. {
  147. FF_PartitionParameters_t xPartition;
  148. FF_Error_t xError;
  149. /* Create a single partition that fills all available space on the disk. */
  150. memset( &xPartition, '\0', sizeof( xPartition ) );
  151. xPartition.ulSectorCount = OTA_MEDIA_SIZE / sfSECTOR_SIZE;
  152. xPartition.ulHiddenSectors = sfHIDDEN_SECTOR_COUNT;
  153. xPartition.xPrimaryCount = sfPRIMARY_PARTITIONS;
  154. xPartition.eSizeType = eSizeIsQuota;
  155. /* Partition the disk */
  156. xError = FF_Partition( pxDisk, &xPartition );
  157. FF_PRINTF( "FF_Partition: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
  158. if( FF_isERR( xError ) == pdFALSE )
  159. {
  160. /* Format the partition. */
  161. xError = FF_Format( pxDisk, sfPARTITION_NUMBER, pdFALSE, pdFALSE );
  162. FF_PRINTF( "FF_Format: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
  163. if ( FF_isERR( xError ) == pdFALSE )
  164. {
  165. xError = FF_Mount( pxDisk, 0 );
  166. FF_PRINTF( "FF_Mount: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
  167. FF_SFDiskShowPartition( pxDisk );
  168. }
  169. }
  170. return xError;
  171. }
  172. /* mount an spi-flash partition */
  173. FF_Disk_t *FF_SFDiskInit( const char *pcName )
  174. {
  175. FF_Error_t xFFError;
  176. BaseType_t xPartitionNumber = 0;
  177. FF_CreationParameters_t xParameters;
  178. FF_Disk_t * pxDisk;
  179. sflash = sfud_get_device(0);
  180. if( sflash != NULL )
  181. {
  182. pxDisk = ( FF_Disk_t * ) pvPortMalloc( sizeof( *pxDisk ) );
  183. if( pxDisk != NULL )
  184. {
  185. /* Initialise the created disk structure. */
  186. memset( pxDisk, '\0', sizeof( *pxDisk ) );
  187. if( xPlusFATMutex == NULL)
  188. {
  189. xPlusFATMutex = xSemaphoreCreateRecursiveMutex();
  190. }
  191. //pxDisk->ulNumberOfSectors = sflash->chip.capacity / sfSECTOR_SIZE;
  192. pxDisk->ulNumberOfSectors = OTA_MEDIA_SIZE / sfSECTOR_SIZE;
  193. pxDisk->ulSignature = sfSIGNATURE;
  194. if( xPlusFATMutex != NULL)
  195. {
  196. memset( &xParameters, '\0', sizeof( xParameters ) );
  197. xParameters.ulMemorySize = sfIOMAN_MEM_SIZE;
  198. xParameters.ulSectorSize = sfSECTOR_SIZE;
  199. xParameters.fnWriteBlocks = prvFFWrite;
  200. xParameters.fnReadBlocks = prvFFRead;
  201. xParameters.pxDisk = pxDisk;
  202. /* prvFFRead()/prvFFWrite() are not re-entrant and must be
  203. protected with the use of a semaphore. */
  204. xParameters.xBlockDeviceIsReentrant = pdFALSE;
  205. /* The semaphore will be used to protect critical sections in
  206. the +FAT driver, and also to avoid concurrent calls to
  207. prvFFRead()/prvFFWrite() from different tasks. */
  208. xParameters.pvSemaphore = ( void * ) xPlusFATMutex;
  209. pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );
  210. if( pxDisk->pxIOManager == NULL )
  211. {
  212. FF_PRINTF( "FF_SFDiskInit: FF_CreateIOManger: %s\n", ( const char * ) FF_GetErrMessage( xFFError ) );
  213. FF_SFDiskDelete( pxDisk );
  214. pxDisk = NULL;
  215. }
  216. else
  217. {
  218. pxDisk->xStatus.bIsInitialised = pdTRUE;
  219. pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
  220. if( FF_SFDiskMount( pxDisk ) == 0 )
  221. {
  222. if ( PartitionAndFormatSFDisk(pxDisk) != FF_ERR_NONE )
  223. {
  224. FF_PRINTF( "FF_SFDiskInit: Mount spi-flash fail.\n");
  225. FF_SFDiskDelete( pxDisk );
  226. pxDisk = NULL;
  227. }
  228. else
  229. {
  230. if( pcName == NULL )
  231. {
  232. pcName = "/";
  233. }
  234. FF_FS_Add( pcName, pxDisk );
  235. FF_PRINTF( "FF_SFDiskInit: Mounted spi-flash as root \"%s\"\n", pcName );
  236. }
  237. }
  238. else
  239. {
  240. if( pcName == NULL )
  241. {
  242. pcName = "/";
  243. }
  244. FF_FS_Add( pcName, pxDisk );
  245. FF_PRINTF( "FF_SFDiskInit: Mounted spi-flash as root \"%s\"\n", pcName );
  246. }
  247. } /* if( pxDisk->pxIOManager != NULL ) */
  248. } /* if( xPlusFATMutex != NULL) */
  249. } /* if( pxDisk != NULL ) */
  250. else
  251. {
  252. FF_PRINTF( "FF_SFDiskInit: Malloc failed\n" );
  253. }
  254. } /* if( sflash != NULL ) */
  255. else
  256. {
  257. FF_PRINTF( "FF_SFDiskInit: sfud_get_device failed\n" );
  258. pxDisk = NULL;
  259. }
  260. return pxDisk;
  261. }
  262. /*-----------------------------------------------------------*/
  263. BaseType_t FF_SFDiskFormat( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber )
  264. {
  265. FF_Error_t xError;
  266. BaseType_t xReturn = pdFAIL;
  267. xError = FF_Unmount( pxDisk );
  268. if( FF_isERR( xError ) != pdFALSE )
  269. {
  270. FF_PRINTF( "FF_SFDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );
  271. }
  272. else
  273. {
  274. /* Format the drive - try FAT32 with large clusters. */
  275. xError = FF_Format( pxDisk, xPartitionNumber, pdFALSE, pdFALSE);
  276. if( FF_isERR( xError ) )
  277. {
  278. FF_PRINTF( "FF_SFDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );
  279. }
  280. else
  281. {
  282. FF_PRINTF( "FF_SFDiskFormat: OK, now remounting\n" );
  283. pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
  284. xError = FF_SFDiskMount( pxDisk );
  285. FF_PRINTF( "FF_SFDiskFormat: rc %08x\n", ( unsigned )xError );
  286. if( FF_isERR( xError ) == pdFALSE )
  287. {
  288. xReturn = pdPASS;
  289. }
  290. }
  291. }
  292. return xReturn;
  293. }
  294. /*-----------------------------------------------------------*/
  295. BaseType_t FF_SFDiskFormatRemount( FF_Disk_t *pxDisk, const char *pcName )
  296. {
  297. FF_Error_t xError;
  298. BaseType_t xReturn = pdFAIL;
  299. xError = FF_Unmount( pxDisk );
  300. if( FF_isERR( xError ) != pdFALSE )
  301. {
  302. FF_PRINTF( "FF_SFDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );
  303. }
  304. else
  305. {
  306. if ( PartitionAndFormatSFDisk( pxDisk ) != FF_ERR_NONE )
  307. {
  308. FF_PRINTF( "FF_SFDiskFormatRemount: PartitionAndFormatSFDisk fail.\n");
  309. FF_SFDiskDelete( pxDisk );
  310. pxDisk = NULL;
  311. }
  312. else
  313. {
  314. if( pcName == NULL )
  315. {
  316. pcName = "/";
  317. }
  318. FF_FS_Add( pcName, pxDisk );
  319. FF_PRINTF( "FF_SDDiskFormatRemount: Mount SPI nor/nand Flash as root \"%s\"\n", pcName );
  320. }
  321. }
  322. return xReturn;
  323. }
  324. /*-----------------------------------------------------------*/
  325. /* Get a pointer to IOMAN, which can be used for all FreeRTOS+FAT functions */
  326. BaseType_t FF_SFDiskMount( FF_Disk_t *pxDisk )
  327. {
  328. FF_Error_t xFFError;
  329. BaseType_t xReturn;
  330. /* Mount the partition */
  331. xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );
  332. if( FF_isERR( xFFError ) )
  333. {
  334. FF_PRINTF( "FF_SFDiskMount: %08lX\n", xFFError );
  335. xReturn = pdFAIL;
  336. }
  337. else
  338. {
  339. pxDisk->xStatus.bIsMounted = pdTRUE;
  340. FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );
  341. FF_SFDiskShowPartition( pxDisk );
  342. xReturn = pdPASS;
  343. }
  344. return xReturn;
  345. }
  346. /*-----------------------------------------------------------*/
  347. /* Release all resources */
  348. BaseType_t FF_SFDiskDelete( FF_Disk_t *pxDisk )
  349. {
  350. if( pxDisk != NULL )
  351. {
  352. pxDisk->ulSignature = 0;
  353. pxDisk->xStatus.bIsInitialised = 0;
  354. if( pxDisk->pxIOManager != NULL )
  355. {
  356. if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )
  357. {
  358. FF_Unmount( pxDisk );
  359. }
  360. FF_DeleteIOManager( pxDisk->pxIOManager );
  361. }
  362. vPortFree( pxDisk );
  363. }
  364. return 1;
  365. }
  366. /*-----------------------------------------------------------*/
  367. BaseType_t FF_SFDiskShowPartition( FF_Disk_t *pxDisk )
  368. {
  369. FF_Error_t xError;
  370. uint64_t ullFreeSectors;
  371. uint32_t ulTotalSizeMB, ulFreeSizeMB;
  372. int iPercentageFree;
  373. FF_IOManager_t *pxIOManager;
  374. const char *pcTypeName = "unknown type";
  375. BaseType_t xReturn = pdPASS;
  376. if( pxDisk == NULL )
  377. {
  378. xReturn = pdFAIL;
  379. }
  380. else
  381. {
  382. pxIOManager = pxDisk->pxIOManager;
  383. FF_PRINTF( "Reading FAT and calculating Free Space\n" );
  384. switch( pxIOManager->xPartition.ucType )
  385. {
  386. case FF_T_FAT12:
  387. pcTypeName = "FAT12";
  388. break;
  389. case FF_T_FAT16:
  390. pcTypeName = "FAT16";
  391. break;
  392. case FF_T_FAT32:
  393. pcTypeName = "FAT32";
  394. break;
  395. default:
  396. pcTypeName = "UNKOWN";
  397. break;
  398. }
  399. FF_GetFreeSize( pxIOManager, &xError );
  400. ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;
  401. iPercentageFree = ( int ) ( ( sfHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /
  402. ( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );
  403. ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sfSECTORS_PER_MB;
  404. ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sfSECTORS_PER_MB );
  405. /* It is better not to use the 64-bit format such as %Lu because it
  406. might not be implemented. */
  407. FF_PRINTF( "Partition Nr %8u\n", pxDisk->xStatus.bPartitionNumber );
  408. FF_PRINTF( "Type %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );
  409. FF_PRINTF( "VolLabel '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );
  410. FF_PRINTF( "TotalSectors %8lu\n", pxIOManager->xPartition.ulTotalSectors );
  411. FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );
  412. FF_PRINTF( "Size %8lu MB\n", ulTotalSizeMB );
  413. FF_PRINTF( "FreeSize %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );
  414. }
  415. return xReturn;
  416. }
  417. /*-----------------------------------------------------------*/