wear_leveling_flash_spi.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 "util.h"
  6. #include "timer.h"
  7. #include "wear_leveling.h"
  8. #include "wear_leveling_internal.h"
  9. #ifndef WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT
  10. # define WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT 32
  11. #endif // WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT
  12. bool backing_store_init(void) {
  13. bs_dprintf("Init\n");
  14. flash_init();
  15. return true;
  16. }
  17. bool backing_store_unlock(void) {
  18. bs_dprintf("Unlock\n");
  19. // No-op -- handled by the flash driver as it is.
  20. return true;
  21. }
  22. bool backing_store_erase(void) {
  23. #ifdef WEAR_LEVELING_DEBUG_OUTPUT
  24. uint32_t start = timer_read32();
  25. #endif
  26. bool ret = true;
  27. for (int i = 0; i < (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT); ++i) {
  28. flash_status_t status = flash_erase_block(((WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) + i) * (EXTERNAL_FLASH_BLOCK_SIZE));
  29. if (status != FLASH_STATUS_SUCCESS) {
  30. ret = false;
  31. break;
  32. }
  33. }
  34. bs_dprintf("Backing store erase took %ldms to complete\n", ((long)(timer_read32() - start)));
  35. return ret;
  36. }
  37. bool backing_store_write(uint32_t address, backing_store_int_t value) {
  38. return backing_store_write_bulk(address, &value, 1);
  39. }
  40. bool backing_store_lock(void) {
  41. bs_dprintf("Lock \n");
  42. // No-op -- handled by the flash driver as it is.
  43. return true;
  44. }
  45. bool backing_store_read(uint32_t address, backing_store_int_t *value) {
  46. return backing_store_read_bulk(address, value, 1);
  47. }
  48. bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
  49. bs_dprintf("Read ");
  50. uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
  51. flash_status_t status = flash_read_block(offset, values, sizeof(backing_store_int_t) * item_count);
  52. if (status == FLASH_STATUS_SUCCESS) {
  53. for (size_t i = 0; i < item_count; ++i) {
  54. values[i] = ~values[i];
  55. }
  56. wl_dump(offset, values, sizeof(backing_store_int_t) * item_count);
  57. }
  58. return status == FLASH_STATUS_SUCCESS;
  59. }
  60. bool backing_store_write_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
  61. uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
  62. size_t index = 0;
  63. backing_store_int_t temp[WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT];
  64. do {
  65. // Copy out the block of data we want to transmit first
  66. size_t this_loop = MIN(item_count, WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT);
  67. for (size_t i = 0; i < this_loop; ++i) {
  68. temp[i] = values[index + i];
  69. }
  70. bs_dprintf("Write ");
  71. wl_dump(offset, temp, sizeof(backing_store_int_t) * this_loop);
  72. // Take the complement instead
  73. for (size_t i = 0; i < this_loop; ++i) {
  74. temp[i] = ~temp[i];
  75. }
  76. // Write out the block
  77. if (flash_write_block(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) {
  78. return false;
  79. }
  80. offset += this_loop * sizeof(backing_store_int_t);
  81. index += this_loop;
  82. item_count -= this_loop;
  83. } while (item_count > 0);
  84. return true;
  85. }