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