1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
73
74
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
101
102
103
104
105
124
125
126
134
135
136
137
138
142
143
144
145
149
150
151
152
153
154
155
156
157
158
159
160
164
168
169
170
171
172
173
174
175
176
177
178
179
180
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
200
201
202
203
204
205
206
207
208
209
212
213
214
215
216
217
218
219
220
221
224
225
226
227
228
229
230
231
232
233
236
237
238
239
240
241
242
243
244
245
248
249
250
251
252
253
254
/* ... */
#include <stdlib.h>
#include <new>
#include <sys/lock.h>
#include "wear_levelling.h"
#include "WL_Config.h"
#include "WL_Ext_Cfg.h"
#include "WL_Flash.h"
#include "WL_Ext_Perf.h"
#include "WL_Ext_Safe.h"
#include "SPI_Flash.h"
#include "Partition.h"11 includes
#ifndef MAX_WL_HANDLES
#define MAX_WL_HANDLES 8
#endif
#ifndef WL_DEFAULT_UPDATERATE
#define WL_DEFAULT_UPDATERATE 16
#endif
#ifndef WL_DEFAULT_TEMP_BUFF_SIZE
#define WL_DEFAULT_TEMP_BUFF_SIZE 32
#endif
#ifndef WL_DEFAULT_WRITE_SIZE
#define WL_DEFAULT_WRITE_SIZE 16
#endif
#ifndef WL_DEFAULT_START_ADDR
#define WL_DEFAULT_START_ADDR 0
#endif
#ifndef WL_CURRENT_VERSION
#define WL_CURRENT_VERSION 2
#endif
typedef struct {
WL_Flash *instance;
_lock_t lock;
}{ ... } wl_instance_t;
static wl_instance_t s_instances[MAX_WL_HANDLES];
static _lock_t s_instances_lock;
static const char *TAG = "wear_levelling";
static esp_err_t check_handle(wl_handle_t handle, const char *func);
esp_err_t wl_mount(const esp_partition_t *partition, wl_handle_t *out_handle)
{
void *wl_flash_ptr = NULL;
WL_Flash *wl_flash = NULL;
void *part_ptr = NULL;
Partition *part = NULL;
esp_err_t result = ESP_OK;
*out_handle = WL_INVALID_HANDLE;
_lock_acquire(&s_instances_lock);
for (size_t i = 0; i < MAX_WL_HANDLES; i++) {
if (s_instances[i].instance == NULL) {
*out_handle = i;
break;
}{...}
}{...}
if (*out_handle == WL_INVALID_HANDLE) {
ESP_LOGE(TAG, "MAX_WL_HANDLES=%d instances already allocated", MAX_WL_HANDLES);
result = ESP_ERR_NO_MEM;
goto out;
}{...}
wl_ext_cfg_t cfg;
cfg.wl_partition_start_addr = WL_DEFAULT_START_ADDR;
cfg.wl_partition_size = partition->size;
cfg.wl_page_size = partition->erase_size;
cfg.flash_sector_size = partition->erase_size;
cfg.wl_update_rate = WL_DEFAULT_UPDATERATE;
cfg.wl_pos_update_record_size = WL_DEFAULT_WRITE_SIZE;
cfg.version = WL_CURRENT_VERSION;
cfg.wl_temp_buff_size = WL_DEFAULT_TEMP_BUFF_SIZE;
cfg.fat_sector_size = CONFIG_WL_SECTOR_SIZE;
part_ptr = malloc(sizeof(Partition));
if (part_ptr == NULL) {
result = ESP_ERR_NO_MEM;
ESP_LOGE(TAG, "%s: can't allocate Partition", __func__);
goto out;
}{...}
part = new (part_ptr) Partition(partition);
#if CONFIG_WL_SECTOR_SIZE == 512
#if CONFIG_WL_SECTOR_MODE == 1
wl_flash_ptr = malloc(sizeof(WL_Ext_Safe));
if (wl_flash_ptr == NULL) {
result = ESP_ERR_NO_MEM;
ESP_LOGE(TAG, "%s: can't allocate WL_Ext_Safe", __func__);
goto out;
}{...}
wl_flash = new (wl_flash_ptr) WL_Ext_Safe();/* ... */
#else
wl_flash_ptr = malloc(sizeof(WL_Ext_Perf));
if (wl_flash_ptr == NULL) {
result = ESP_ERR_NO_MEM;
ESP_LOGE(TAG, "%s: can't allocate WL_Ext_Perf", __func__);
goto out;
}{...}
wl_flash = new (wl_flash_ptr) WL_Ext_Perf();/* ... */
#endif /* ... */
#endif
#if CONFIG_WL_SECTOR_SIZE == 4096
wl_flash_ptr = malloc(sizeof(WL_Flash));
if (wl_flash_ptr == NULL) {
result = ESP_ERR_NO_MEM;
ESP_LOGE(TAG, "%s: can't allocate WL_Flash", __func__);
goto out;
}{...}
wl_flash = new (wl_flash_ptr) WL_Flash();/* ... */
#endif
result = wl_flash->config(&cfg, part);
if (ESP_OK != result) {
ESP_LOGE(TAG, "%s: config instance=0x%08" PRIx32 ", result=0x%x", __func__, *out_handle, result);
goto out;
}{...}
result = wl_flash->init();
if (ESP_OK != result) {
ESP_LOGE(TAG, "%s: init instance=0x%08" PRIx32 ", result=0x%x", __func__, *out_handle, result);
goto out;
}{...}
s_instances[*out_handle].instance = wl_flash;
_lock_init(&s_instances[*out_handle].lock);
_lock_release(&s_instances_lock);
return ESP_OK;
out:
_lock_release(&s_instances_lock);
*out_handle = WL_INVALID_HANDLE;
if (wl_flash) {
wl_flash->~WL_Flash();
free(wl_flash);
}{...}
if (part) {
part->~Partition();
free(part);
}{...}
return result;
}{ ... }
esp_err_t wl_unmount(wl_handle_t handle)
{
esp_err_t result = ESP_OK;
_lock_acquire(&s_instances_lock);
result = check_handle(handle, __func__);
if (result == ESP_OK) {
Partition *part = s_instances[handle].instance->get_part();
if (!part->is_readonly()) {
result = s_instances[handle].instance->flush();
}{...}
part->~Partition();
free(part);
s_instances[handle].instance->~WL_Flash();
free(s_instances[handle].instance);
s_instances[handle].instance = NULL;
_lock_close(&s_instances[handle].lock);
}{...}
_lock_release(&s_instances_lock);
return result;
}{ ... }
esp_err_t wl_erase_range(wl_handle_t handle, size_t start_addr, size_t size)
{
esp_err_t result = check_handle(handle, __func__);
if (result != ESP_OK) {
return result;
}{...}
_lock_acquire(&s_instances[handle].lock);
result = s_instances[handle].instance->erase_range(start_addr, size);
_lock_release(&s_instances[handle].lock);
return result;
}{ ... }
esp_err_t wl_write(wl_handle_t handle, size_t dest_addr, const void *src, size_t size)
{
esp_err_t result = check_handle(handle, __func__);
if (result != ESP_OK) {
return result;
}{...}
_lock_acquire(&s_instances[handle].lock);
result = s_instances[handle].instance->write(dest_addr, src, size);
_lock_release(&s_instances[handle].lock);
return result;
}{ ... }
esp_err_t wl_read(wl_handle_t handle, size_t src_addr, void *dest, size_t size)
{
esp_err_t result = check_handle(handle, __func__);
if (result != ESP_OK) {
return result;
}{...}
_lock_acquire(&s_instances[handle].lock);
result = s_instances[handle].instance->read(src_addr, dest, size);
_lock_release(&s_instances[handle].lock);
return result;
}{ ... }
size_t wl_size(wl_handle_t handle)
{
esp_err_t err = check_handle(handle, __func__);
if (err != ESP_OK) {
return 0;
}{...}
_lock_acquire(&s_instances[handle].lock);
size_t result = s_instances[handle].instance->get_flash_size();
_lock_release(&s_instances[handle].lock);
return result;
}{ ... }
size_t wl_sector_size(wl_handle_t handle)
{
esp_err_t err = check_handle(handle, __func__);
if (err != ESP_OK) {
return 0;
}{...}
_lock_acquire(&s_instances[handle].lock);
size_t result = s_instances[handle].instance->get_sector_size();
_lock_release(&s_instances[handle].lock);
return result;
}{ ... }
static esp_err_t check_handle(wl_handle_t handle, const char *func)
{
if (handle == WL_INVALID_HANDLE) {
ESP_LOGE(TAG, "%s: invalid handle", func);
return ESP_ERR_NOT_FOUND;
}{...}
if (handle >= MAX_WL_HANDLES) {
ESP_LOGE(TAG, "%s: instance[0x%08" PRIx32 "] out of range", func, handle);
return ESP_ERR_INVALID_ARG;
}{...}
if (s_instances[handle].instance == NULL) {
ESP_LOGE(TAG, "%s: instance[0x%08" PRIx32 "] not initialized", func, handle);
return ESP_ERR_NOT_FOUND;
}{...}
return ESP_OK;
}{ ... }