logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

wear_leveling_flash_spi.c (3385B)


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