wear_levelling.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdlib.h>
  15. #include <new>
  16. #include <sys/lock.h>
  17. #include "wear_levelling.h"
  18. #include "WL_Config.h"
  19. #include "WL_Ext_Cfg.h"
  20. #include "WL_Flash.h"
  21. #include "WL_Ext_Perf.h"
  22. #include "WL_Ext_Safe.h"
  23. #include "SPI_Flash.h"
  24. #include "Partition.h"
  25. #ifndef MAX_WL_HANDLES
  26. #define MAX_WL_HANDLES 8
  27. #endif // MAX_WL_HANDLES
  28. #ifndef WL_DEFAULT_UPDATERATE
  29. #define WL_DEFAULT_UPDATERATE 16
  30. #endif //WL_DEFAULT_UPDATERATE
  31. #ifndef WL_DEFAULT_TEMP_BUFF_SIZE
  32. #define WL_DEFAULT_TEMP_BUFF_SIZE 32
  33. #endif //WL_DEFAULT_TEMP_BUFF_SIZE
  34. #ifndef WL_DEFAULT_WRITE_SIZE
  35. #define WL_DEFAULT_WRITE_SIZE 16
  36. #endif //WL_DEFAULT_WRITE_SIZE
  37. #ifndef WL_DEFAULT_START_ADDR
  38. #define WL_DEFAULT_START_ADDR 0
  39. #endif //WL_DEFAULT_START_ADDR
  40. #ifndef WL_CURRENT_VERSION
  41. #define WL_CURRENT_VERSION 2
  42. #endif //WL_CURRENT_VERSION
  43. typedef struct {
  44. WL_Flash *instance;
  45. _lock_t lock;
  46. } wl_instance_t;
  47. static wl_instance_t s_instances[MAX_WL_HANDLES];
  48. static _lock_t s_instances_lock;
  49. static const char *TAG = "wear_levelling";
  50. static esp_err_t check_handle(wl_handle_t handle, const char *func);
  51. esp_err_t wl_mount(const esp_partition_t *partition, wl_handle_t *out_handle)
  52. {
  53. // Initialize variables before the first jump to cleanup label
  54. void *wl_flash_ptr = NULL;
  55. WL_Flash *wl_flash = NULL;
  56. void *part_ptr = NULL;
  57. Partition *part = NULL;
  58. _lock_acquire(&s_instances_lock);
  59. esp_err_t result = ESP_OK;
  60. *out_handle = WL_INVALID_HANDLE;
  61. for (size_t i = 0; i < MAX_WL_HANDLES; i++) {
  62. if (s_instances[i].instance == NULL) {
  63. *out_handle = i;
  64. break;
  65. }
  66. }
  67. wl_ext_cfg_t cfg;
  68. cfg.full_mem_size = partition->size;
  69. cfg.start_addr = WL_DEFAULT_START_ADDR;
  70. cfg.version = WL_CURRENT_VERSION;
  71. cfg.sector_size = SPI_FLASH_SEC_SIZE;
  72. cfg.page_size = SPI_FLASH_SEC_SIZE;
  73. cfg.updaterate = WL_DEFAULT_UPDATERATE;
  74. cfg.temp_buff_size = WL_DEFAULT_TEMP_BUFF_SIZE;
  75. cfg.wr_size = WL_DEFAULT_WRITE_SIZE;
  76. // FAT sector size by default will be 512
  77. cfg.fat_sector_size = CONFIG_WL_SECTOR_SIZE;
  78. if (*out_handle == WL_INVALID_HANDLE) {
  79. ESP_LOGE(TAG, "MAX_WL_HANDLES=%d instances already allocated", MAX_WL_HANDLES);
  80. result = ESP_ERR_NO_MEM;
  81. goto out;
  82. }
  83. // Allocate memory for a Partition object, and then initialize the object
  84. // using placement new operator. This way we can recover from out of
  85. // memory condition.
  86. part_ptr = malloc(sizeof(Partition));
  87. if (part_ptr == NULL) {
  88. result = ESP_ERR_NO_MEM;
  89. ESP_LOGE(TAG, "%s: can't allocate Partition", __func__);
  90. goto out;
  91. }
  92. part = new (part_ptr) Partition(partition);
  93. // Same for WL_Flash: allocate memory, use placement new
  94. #if CONFIG_WL_SECTOR_SIZE == 512
  95. #if CONFIG_WL_SECTOR_MODE == 1
  96. wl_flash_ptr = malloc(sizeof(WL_Ext_Safe));
  97. if (wl_flash_ptr == NULL) {
  98. result = ESP_ERR_NO_MEM;
  99. ESP_LOGE(TAG, "%s: can't allocate WL_Ext_Safe", __func__);
  100. goto out;
  101. }
  102. wl_flash = new (wl_flash_ptr) WL_Ext_Safe();
  103. #else
  104. wl_flash_ptr = malloc(sizeof(WL_Ext_Perf));
  105. if (wl_flash_ptr == NULL) {
  106. result = ESP_ERR_NO_MEM;
  107. ESP_LOGE(TAG, "%s: can't allocate WL_Ext_Perf", __func__);
  108. goto out;
  109. }
  110. wl_flash = new (wl_flash_ptr) WL_Ext_Perf();
  111. #endif // CONFIG_WL_SECTOR_MODE
  112. #endif // CONFIG_WL_SECTOR_SIZE
  113. #if CONFIG_WL_SECTOR_SIZE == 4096
  114. wl_flash_ptr = malloc(sizeof(WL_Flash));
  115. if (wl_flash_ptr == NULL) {
  116. result = ESP_ERR_NO_MEM;
  117. ESP_LOGE(TAG, "%s: can't allocate WL_Flash", __func__);
  118. goto out;
  119. }
  120. wl_flash = new (wl_flash_ptr) WL_Flash();
  121. #endif // CONFIG_WL_SECTOR_SIZE
  122. result = wl_flash->config(&cfg, part);
  123. if (ESP_OK != result) {
  124. ESP_LOGE(TAG, "%s: config instance=0x%08x, result=0x%x", __func__, *out_handle, result);
  125. goto out;
  126. }
  127. result = wl_flash->init();
  128. if (ESP_OK != result) {
  129. ESP_LOGE(TAG, "%s: init instance=0x%08x, result=0x%x", __func__, *out_handle, result);
  130. goto out;
  131. }
  132. s_instances[*out_handle].instance = wl_flash;
  133. _lock_init(&s_instances[*out_handle].lock);
  134. _lock_release(&s_instances_lock);
  135. return ESP_OK;
  136. out:
  137. _lock_release(&s_instances_lock);
  138. *out_handle = WL_INVALID_HANDLE;
  139. if (wl_flash) {
  140. wl_flash->~WL_Flash();
  141. free(wl_flash);
  142. }
  143. if (part) {
  144. part->~Partition();
  145. free(part);
  146. }
  147. return result;
  148. }
  149. esp_err_t wl_unmount(wl_handle_t handle)
  150. {
  151. esp_err_t result = ESP_OK;
  152. _lock_acquire(&s_instances_lock);
  153. result = check_handle(handle, __func__);
  154. if (result == ESP_OK) {
  155. // We have to flush state of the component
  156. result = s_instances[handle].instance->flush();
  157. // We use placement new in wl_mount, so call destructor directly
  158. Flash_Access *drv = s_instances[handle].instance->get_drv();
  159. drv->~Flash_Access();
  160. free(drv);
  161. s_instances[handle].instance->~WL_Flash();
  162. free(s_instances[handle].instance);
  163. s_instances[handle].instance = NULL;
  164. _lock_close(&s_instances[handle].lock); // also zeroes the lock variable
  165. }
  166. _lock_release(&s_instances_lock);
  167. return result;
  168. }
  169. esp_err_t wl_erase_range(wl_handle_t handle, size_t start_addr, size_t size)
  170. {
  171. esp_err_t result = check_handle(handle, __func__);
  172. if (result != ESP_OK) {
  173. return result;
  174. }
  175. _lock_acquire(&s_instances[handle].lock);
  176. result = s_instances[handle].instance->erase_range(start_addr, size);
  177. _lock_release(&s_instances[handle].lock);
  178. return result;
  179. }
  180. esp_err_t wl_write(wl_handle_t handle, size_t dest_addr, const void *src, size_t size)
  181. {
  182. esp_err_t result = check_handle(handle, __func__);
  183. if (result != ESP_OK) {
  184. return result;
  185. }
  186. _lock_acquire(&s_instances[handle].lock);
  187. result = s_instances[handle].instance->write(dest_addr, src, size);
  188. _lock_release(&s_instances[handle].lock);
  189. return result;
  190. }
  191. esp_err_t wl_read(wl_handle_t handle, size_t src_addr, void *dest, size_t size)
  192. {
  193. esp_err_t result = check_handle(handle, __func__);
  194. if (result != ESP_OK) {
  195. return result;
  196. }
  197. _lock_acquire(&s_instances[handle].lock);
  198. result = s_instances[handle].instance->read(src_addr, dest, size);
  199. _lock_release(&s_instances[handle].lock);
  200. return result;
  201. }
  202. size_t wl_size(wl_handle_t handle)
  203. {
  204. esp_err_t err = check_handle(handle, __func__);
  205. if (err != ESP_OK) {
  206. return 0;
  207. }
  208. _lock_acquire(&s_instances[handle].lock);
  209. size_t result = s_instances[handle].instance->chip_size();
  210. _lock_release(&s_instances[handle].lock);
  211. return result;
  212. }
  213. size_t wl_sector_size(wl_handle_t handle)
  214. {
  215. esp_err_t err = check_handle(handle, __func__);
  216. if (err != ESP_OK) {
  217. return 0;
  218. }
  219. _lock_acquire(&s_instances[handle].lock);
  220. size_t result = s_instances[handle].instance->sector_size();
  221. _lock_release(&s_instances[handle].lock);
  222. return result;
  223. }
  224. static esp_err_t check_handle(wl_handle_t handle, const char *func)
  225. {
  226. if (handle == WL_INVALID_HANDLE) {
  227. ESP_LOGE(TAG, "%s: invalid handle", func);
  228. return ESP_ERR_NOT_FOUND;
  229. }
  230. if (handle >= MAX_WL_HANDLES) {
  231. ESP_LOGE(TAG, "%s: instance[0x%08x] out of range", func, handle);
  232. return ESP_ERR_INVALID_ARG;
  233. }
  234. if (s_instances[handle].instance == NULL) {
  235. ESP_LOGE(TAG, "%s: instance[0x%08x] not initialized", func, handle);
  236. return ESP_ERR_NOT_FOUND;
  237. }
  238. return ESP_OK;
  239. }