InternalFileSystem.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2019 hathach for Adafruit Industries
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all 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,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include <Arduino.h>
  25. #include "InternalFileSystem.h"
  26. //--------------------------------------------------------------------+
  27. // LFS Disk IO
  28. //--------------------------------------------------------------------+
  29. static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
  30. {
  31. if (!buffer || !size) return LFS_ERR_INVAL;
  32. lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * FLASH_PAGE_SIZE + off);
  33. memcpy(buffer, (void *)address, size);
  34. return LFS_ERR_OK;
  35. }
  36. // Program a region in a block. The block must have previously
  37. // been erased. Negative error codes are propogated to the user.
  38. // May return LFS_ERR_CORRUPT if the block should be considered bad.
  39. static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
  40. {
  41. HAL_StatusTypeDef hal_rc = HAL_OK;
  42. lfs_block_t addr = LFS_FLASH_ADDR_BASE + (block * FLASH_PAGE_SIZE + off);
  43. uint64_t *bufp = (uint64_t *) buffer;
  44. if (HAL_FLASH_Unlock() != HAL_OK) return LFS_ERR_IO;
  45. for (uint32_t i = 0; i < size/8; i++) {
  46. if ((addr < LFS_FLASH_ADDR_BASE) || (addr > FLASH_END_ADDR)) {
  47. HAL_FLASH_Lock();
  48. return LFS_ERR_INVAL;
  49. }
  50. hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, *bufp);
  51. addr += 8;
  52. bufp += 1;
  53. }
  54. if (HAL_FLASH_Lock() != HAL_OK) return LFS_ERR_IO;
  55. return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO;
  56. }
  57. // Erase a block. A block must be erased before being programmed.
  58. // The state of an erased block is undefined. Negative error codes
  59. // are propogated to the user.
  60. // May return LFS_ERR_CORRUPT if the block should be considered bad.
  61. static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
  62. {
  63. HAL_StatusTypeDef hal_rc;
  64. lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * FLASH_PAGE_SIZE);
  65. uint32_t pageError = 0;
  66. FLASH_EraseInitTypeDef EraseInitStruct = {
  67. .TypeErase = FLASH_TYPEERASE_PAGES,
  68. .Page = 0,
  69. .NbPages = 1
  70. };
  71. if ((address < LFS_FLASH_ADDR_BASE) || (address > FLASH_END_ADDR)) {
  72. return LFS_ERR_INVAL;
  73. }
  74. EraseInitStruct.Page = (address - FLASH_BASE) / FLASH_PAGE_SIZE;
  75. HAL_FLASH_Unlock();
  76. hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &pageError);
  77. HAL_FLASH_Lock();
  78. return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO;
  79. }
  80. // Sync the state of the underlying block device. Negative error codes
  81. // are propogated to the user.
  82. static int _internal_flash_sync(const struct lfs_config *c)
  83. {
  84. return LFS_ERR_OK; // don't need sync
  85. }
  86. struct lfs_config _InternalFSConfig = {
  87. .context = NULL,
  88. .read = _internal_flash_read,
  89. .prog = _internal_flash_prog,
  90. .erase = _internal_flash_erase,
  91. .sync = _internal_flash_sync,
  92. .read_size = LFS_BLOCK_SIZE,
  93. .prog_size = LFS_BLOCK_SIZE,
  94. .block_size = LFS_BLOCK_SIZE,
  95. .block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE,
  96. .lookahead = 128,
  97. .read_buffer = NULL,
  98. .prog_buffer = NULL,
  99. .lookahead_buffer = NULL,
  100. .file_buffer = NULL
  101. };
  102. InternalFileSystem InternalFS;
  103. //--------------------------------------------------------------------+
  104. //
  105. //--------------------------------------------------------------------+
  106. InternalFileSystem::InternalFileSystem(void)
  107. : Adafruit_LittleFS(&_InternalFSConfig)
  108. {
  109. }
  110. bool InternalFileSystem::begin(void)
  111. {
  112. #ifdef FORMAT_FS
  113. this->format();
  114. #endif
  115. // failed to mount, erase all sector then format and mount again
  116. if ( !Adafruit_LittleFS::begin() )
  117. {
  118. // lfs format
  119. this->format();
  120. // mount again if still failed, give up
  121. if ( !Adafruit_LittleFS::begin() ) return false;
  122. }
  123. return true;
  124. }