wear_leveling_efl.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2022 Nick Brassel (@tzarc)
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <stdbool.h>
  4. #include <hal.h>
  5. #include "timer.h"
  6. #include "wear_leveling.h"
  7. #include "wear_leveling_efl_config.h"
  8. #include "wear_leveling_internal.h"
  9. static flash_offset_t base_offset = UINT32_MAX;
  10. #if defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
  11. static flash_sector_t first_sector = WEAR_LEVELING_EFL_FIRST_SECTOR;
  12. #else // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
  13. static flash_sector_t first_sector = UINT16_MAX;
  14. #endif // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
  15. #if !defined(WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT)
  16. # define WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT 0
  17. #endif // WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT
  18. static flash_sector_t sector_count = UINT16_MAX;
  19. static BaseFlash *flash;
  20. static bool flash_erased_is_one;
  21. static volatile bool is_issuing_read = false;
  22. static volatile bool ecc_error_occurred = false;
  23. // "Automatic" detection of the flash size -- ideally ChibiOS would have this already, but alas, it doesn't.
  24. static inline uint32_t detect_flash_size(void) {
  25. #if defined(WEAR_LEVELING_EFL_FLASH_SIZE)
  26. return WEAR_LEVELING_EFL_FLASH_SIZE;
  27. #elif defined(FLASH_BANK_SIZE)
  28. return FLASH_BANK_SIZE;
  29. #elif defined(FLASH_SIZE)
  30. return FLASH_SIZE;
  31. #elif defined(FLASHSIZE_BASE)
  32. # if defined(QMK_MCU_SERIES_STM32F0XX) || defined(QMK_MCU_SERIES_STM32F1XX) || defined(QMK_MCU_SERIES_STM32F3XX) || defined(QMK_MCU_SERIES_STM32F4XX) || defined(QMK_MCU_SERIES_STM32G4XX) || defined(QMK_MCU_SERIES_STM32L0XX) || defined(QMK_MCU_SERIES_STM32L4XX) || defined(QMK_MCU_SERIES_AT32F415) || defined(QMK_MCU_SERIES_GD32VF103)
  33. return ((*(uint32_t *)FLASHSIZE_BASE) & 0xFFFFU) << 10U; // this register has the flash size in kB, so we convert it to bytes
  34. # elif defined(QMK_MCU_SERIES_STM32L1XX)
  35. # error This MCU family has an uncommon flash size register definition and has not been implemented. Perhaps try using the true EEPROM on the MCU instead?
  36. # endif
  37. #else
  38. # error Unknown flash size definition.
  39. return 0;
  40. #endif
  41. }
  42. bool backing_store_init(void) {
  43. bs_dprintf("Init\n");
  44. flash = (BaseFlash *)&EFLD1;
  45. // Need to re-lock the EFL, as if we've just had the bootloader executing it'll already be unlocked.
  46. backing_store_lock();
  47. const flash_descriptor_t *desc = flashGetDescriptor(flash);
  48. uint32_t counter = 0;
  49. uint32_t flash_size = detect_flash_size();
  50. // Check if the hardware erase is logic 1
  51. flash_erased_is_one = (desc->attributes & FLASH_ATTR_ERASED_IS_ONE) ? true : false;
  52. if (WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT >= desc->sectors_count) {
  53. // Last sector defined is greater than available number of sectors. Can't do anything here. Fault.
  54. chSysHalt("Last sector intended to be used with wear_leveling is beyond available flash descriptor range");
  55. }
  56. #if defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
  57. // Work out how many sectors we want to use, working forwards from the first sector specified
  58. flash_sector_t last_sector = desc->sectors_count - WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT;
  59. for (flash_sector_t i = 0; i < last_sector - first_sector; ++i) {
  60. counter += flashGetSectorSize(flash, first_sector + i);
  61. if (counter >= (WEAR_LEVELING_BACKING_SIZE)) {
  62. sector_count = i + 1;
  63. base_offset = flashGetSectorOffset(flash, first_sector);
  64. break;
  65. }
  66. }
  67. if (sector_count == UINT16_MAX || base_offset >= flash_size) {
  68. // We didn't get the required number of sectors. Can't do anything here. Fault.
  69. chSysHalt("Invalid sector count intended to be used with wear_leveling");
  70. }
  71. #else // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
  72. // Work out how many sectors we want to use, working backwards from the end of the flash
  73. flash_sector_t last_sector = desc->sectors_count;
  74. // skip sectors that are past the actual flash size
  75. while (flashGetSectorOffset(flash, last_sector - 1) >= flash_size) {
  76. if (--last_sector == 0) {
  77. chSysHalt("No sector in available flash range");
  78. }
  79. }
  80. if (WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT >= last_sector) {
  81. chSysHalt("Last sector intended to be used with wear_leveling is beyond available flash descriptor range");
  82. }
  83. last_sector -= WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT;
  84. for (flash_sector_t i = 0; i < last_sector; ++i) {
  85. first_sector = last_sector - i - 1;
  86. counter += flashGetSectorSize(flash, first_sector);
  87. if (counter >= (WEAR_LEVELING_BACKING_SIZE)) {
  88. sector_count = last_sector - first_sector;
  89. base_offset = flashGetSectorOffset(flash, first_sector);
  90. break;
  91. }
  92. }
  93. if (counter < WEAR_LEVELING_BACKING_SIZE) {
  94. chSysHalt("Not enough flash is available for the requested wear_leveling size");
  95. }
  96. #endif // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
  97. return true;
  98. }
  99. bool backing_store_unlock(void) {
  100. bs_dprintf("Unlock\n");
  101. return eflStart(&EFLD1, NULL) == HAL_RET_SUCCESS;
  102. }
  103. bool backing_store_erase(void) {
  104. #ifdef WEAR_LEVELING_DEBUG_OUTPUT
  105. uint32_t start = timer_read32();
  106. #endif
  107. bool ret = true;
  108. flash_error_t status;
  109. for (int i = 0; i < sector_count; ++i) {
  110. // Kick off the sector erase
  111. status = flashStartEraseSector(flash, first_sector + i);
  112. if (status != FLASH_NO_ERROR && status != FLASH_BUSY_ERASING) {
  113. ret = false;
  114. }
  115. // Wait for the erase to complete
  116. status = flashWaitErase(flash);
  117. if (status != FLASH_NO_ERROR && status != FLASH_BUSY_ERASING) {
  118. ret = false;
  119. }
  120. }
  121. bs_dprintf("Backing store erase took %ldms to complete\n", ((long)(timer_read32() - start)));
  122. return ret;
  123. }
  124. bool backing_store_write(uint32_t address, backing_store_int_t value) {
  125. uint32_t offset = (base_offset + address);
  126. bs_dprintf("Write ");
  127. wl_dump(offset, &value, sizeof(value));
  128. if (flash_erased_is_one) {
  129. value = ~value;
  130. }
  131. return flashProgram(flash, offset, sizeof(value), (const uint8_t *)&value) == FLASH_NO_ERROR;
  132. }
  133. bool backing_store_lock(void) {
  134. bs_dprintf("Lock \n");
  135. eflStop(&EFLD1);
  136. return true;
  137. }
  138. static backing_store_int_t backing_store_safe_read_from_location(backing_store_int_t *loc) {
  139. backing_store_int_t value;
  140. is_issuing_read = true;
  141. ecc_error_occurred = false;
  142. value = flash_erased_is_one ? ~(*loc) : (*loc);
  143. is_issuing_read = false;
  144. return value;
  145. }
  146. bool backing_store_read(uint32_t address, backing_store_int_t *value) {
  147. uint32_t offset = (base_offset + address);
  148. backing_store_int_t *loc = (backing_store_int_t *)flashGetOffsetAddress(flash, offset);
  149. backing_store_int_t tmp = backing_store_safe_read_from_location(loc);
  150. if (ecc_error_occurred) {
  151. bs_dprintf("Failed to read from backing store, ECC error detected\n");
  152. ecc_error_occurred = false;
  153. *value = 0;
  154. return false;
  155. }
  156. *value = tmp;
  157. bs_dprintf("Read ");
  158. wl_dump(offset, value, sizeof(backing_store_int_t));
  159. return true;
  160. }
  161. bool backing_store_allow_ecc_errors(void) {
  162. return is_issuing_read;
  163. }
  164. void backing_store_signal_ecc_error(void) {
  165. ecc_error_occurred = true;
  166. }