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 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 #include <stdio.h>
15 #include "esp_system.h"
16 #include "esp_log.h"
17 #include "WL_Flash.h"
18 #include <stdlib.h>
19 #include "crc32.h"
20 #include <string.h>
21 #include <stddef.h>
22
23 static const char *TAG = "wl_flash";
24 #ifndef WL_CFG_CRC_CONST
25 #define WL_CFG_CRC_CONST UINT32_MAX
26 #endif // WL_CFG_CRC_CONST
27
28 #define WL_RESULT_CHECK(result) \
29 if (result != ESP_OK) { \
30 ESP_LOGE(TAG,"%s(%d): result = 0x%08x", __FUNCTION__, __LINE__, result); \
31 return (result); \
32 }
33
34 #ifndef _MSC_VER // MSVS has different format for this define
35 static_assert(sizeof(wl_state_t) % 32 == 0, "wl_state_t structure size must be multiple of flash encryption unit size");
36 #endif // _MSC_VER
37
38
WL_Flash()39 WL_Flash::WL_Flash()
40 {
41 }
42
~WL_Flash()43 WL_Flash::~WL_Flash()
44 {
45 free(this->temp_buff);
46 }
47
config(wl_config_t * cfg,Flash_Access * flash_drv)48 esp_err_t WL_Flash::config(wl_config_t *cfg, Flash_Access *flash_drv)
49 {
50 ESP_LOGV(TAG, "%s start_addr=0x%08x, full_mem_size=0x%08x, page_size=0x%08x, sector_size=0x%08x, updaterate=0x%08x, wr_size=0x%08x, version=0x%08x, temp_buff_size=0x%08x", __func__,
51 (uint32_t) cfg->start_addr,
52 cfg->full_mem_size,
53 cfg->page_size,
54 cfg->sector_size,
55 cfg->updaterate,
56 cfg->wr_size,
57 cfg->version,
58 (uint32_t) cfg->temp_buff_size);
59
60 cfg->crc = crc32::crc32_le(WL_CFG_CRC_CONST, (const unsigned char *)cfg, offsetof(wl_config_t, crc));
61 esp_err_t result = ESP_OK;
62 memcpy(&this->cfg, cfg, sizeof(wl_config_t));
63 if (this->cfg.temp_buff_size < this->cfg.wr_size) {
64 this->cfg.temp_buff_size = this->cfg.wr_size;
65 }
66 this->configured = false;
67 if (cfg == NULL) {
68 result = ESP_ERR_INVALID_ARG;
69 }
70 this->flash_drv = flash_drv;
71 if (flash_drv == NULL) {
72 result = ESP_ERR_INVALID_ARG;
73 }
74 if ((this->cfg.sector_size % this->cfg.temp_buff_size) != 0) {
75 result = ESP_ERR_INVALID_ARG;
76 }
77 if (this->cfg.page_size < this->cfg.sector_size) {
78 result = ESP_ERR_INVALID_ARG;
79 }
80 WL_RESULT_CHECK(result);
81
82 this->state_size = this->cfg.sector_size;
83 if (this->state_size < (sizeof(wl_state_t) + (this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size)) {
84 this->state_size = ((sizeof(wl_state_t) + (this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size) + this->cfg.sector_size - 1) / this->cfg.sector_size;
85 this->state_size = this->state_size * this->cfg.sector_size;
86 }
87 this->cfg_size = (sizeof(wl_config_t) + this->cfg.sector_size - 1) / this->cfg.sector_size;
88 this->cfg_size = cfg_size * this->cfg.sector_size;
89
90 this->addr_cfg = this->cfg.start_addr + this->cfg.full_mem_size - this->cfg_size;
91 this->addr_state1 = this->cfg.start_addr + this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size; // allocate data at the end of memory
92 this->addr_state2 = this->cfg.start_addr + this->cfg.full_mem_size - this->state_size * 1 - this->cfg_size; // allocate data at the end of memory
93
94 ptrdiff_t flash_sz = ((this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size) / this->cfg.page_size - 1) * this->cfg.page_size; // -1 remove dummy block
95 this->flash_size = ((this->cfg.full_mem_size - this->state_size * 2 - this->cfg_size) / this->cfg.page_size - 1) * this->cfg.page_size; // -1 remove dummy block
96
97 ESP_LOGD(TAG, "%s - config result: state_size=0x%08x, cfg_size=0x%08x, addr_cfg=0x%08x, addr_state1=0x%08x, addr_state2=0x%08x, flash_size=0x%08x", __func__,
98 (uint32_t) this->state_size,
99 (uint32_t) this->cfg_size,
100 (uint32_t) this->addr_cfg,
101 (uint32_t) this->addr_state1,
102 (uint32_t) this->addr_state2,
103 (uint32_t) this->flash_size
104 );
105 if (flash_sz <= 0) {
106 result = ESP_ERR_INVALID_ARG;
107 }
108 WL_RESULT_CHECK(result);
109
110 this->temp_buff = (uint8_t *)malloc(this->cfg.temp_buff_size);
111 if (this->temp_buff == NULL) {
112 result = ESP_ERR_NO_MEM;
113 }
114 WL_RESULT_CHECK(result);
115 this->configured = true;
116 return ESP_OK;
117 }
118
init()119 esp_err_t WL_Flash::init()
120 {
121 esp_err_t result = ESP_OK;
122 if (this->configured == false) {
123 ESP_LOGW(TAG, "WL_Flash: not configured, call config() first");
124 return ESP_ERR_INVALID_STATE;
125 }
126 // If flow will be interrupted by error, then this flag will be false
127 this->initialized = false;
128 // Init states if it is first time...
129 this->flash_drv->read(this->addr_state1, &this->state, sizeof(wl_state_t));
130 wl_state_t sa_copy;
131 wl_state_t *state_copy = &sa_copy;
132 result = this->flash_drv->read(this->addr_state2, state_copy, sizeof(wl_state_t));
133 WL_RESULT_CHECK(result);
134
135 int check_size = WL_STATE_CRC_LEN_V2;
136 // Chech CRC and recover state
137 uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
138 uint32_t crc2 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_copy, check_size);
139
140 ESP_LOGD(TAG, "%s - config ID=%i, stored ID=%i, access_count=%i, block_size=%i, max_count=%i, pos=%i, move_count=0x%8.8X",
141 __func__,
142 this->cfg.version,
143 this->state.version,
144 this->state.access_count,
145 this->state.block_size,
146 this->state.max_count,
147 this->state.pos,
148 this->state.move_count);
149
150 ESP_LOGD(TAG, "%s starts: crc1= 0x%08x, crc2 = 0x%08x, this->state.crc= 0x%08x, state_copy->crc= 0x%08x, version=%i, read_version=%i", __func__, crc1, crc2, this->state.crc, state_copy->crc, this->cfg.version, this->state.version);
151 if ((crc1 == this->state.crc) && (crc2 == state_copy->crc)) {
152 // The state is OK. Check the ID
153 if (this->state.version != this->cfg.version) {
154 result = this->initSections();
155 WL_RESULT_CHECK(result);
156 result = this->recoverPos();
157 WL_RESULT_CHECK(result);
158 } else {
159 if (crc1 != crc2) {// we did not update second structure.
160 result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
161 WL_RESULT_CHECK(result);
162 result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
163 WL_RESULT_CHECK(result);
164 for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size); i++) {
165 bool pos_bits;
166 result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
167 WL_RESULT_CHECK(result);
168 pos_bits = this->OkBuffSet(i);
169 if (pos_bits == true) {
170 //this->fillOkBuff(i);
171 result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
172 WL_RESULT_CHECK(result);
173 }
174 }
175 }
176 ESP_LOGD(TAG, "%s: crc1=0x%08x, crc2 = 0x%08x, result= 0x%08x", __func__, crc1, crc2, (uint32_t)result);
177 result = this->recoverPos();
178 WL_RESULT_CHECK(result);
179 }
180 } else if ((crc1 != this->state.crc) && (crc2 != state_copy->crc)) { // This is just new flash or new version
181 // Check if this is new version or just new instance of WL
182 ESP_LOGD(TAG, "%s: try to update version - crc1= 0x%08x, crc2 = 0x%08x, result= 0x%08x", __func__, (uint32_t)crc1, (uint32_t)crc2, (uint32_t)result);
183 result = this->updateVersion();
184 if (result == ESP_FAIL) {
185 ESP_LOGD(TAG, "%s: init flash sections", __func__);
186 result = this->initSections();
187 WL_RESULT_CHECK(result);
188 }
189 result = this->recoverPos();
190 WL_RESULT_CHECK(result);
191 } else {
192 // recover broken state
193 if (crc1 == this->state.crc) {// we have to recover state 2
194 result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
195 WL_RESULT_CHECK(result);
196 result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
197 WL_RESULT_CHECK(result);
198 for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) {
199 bool pos_bits;
200 result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
201 WL_RESULT_CHECK(result);
202 pos_bits = this->OkBuffSet(i);
203 if (pos_bits == true) {
204 result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
205 WL_RESULT_CHECK(result);
206 }
207 }
208 result = this->flash_drv->read(this->addr_state2, &this->state, sizeof(wl_state_t));
209 WL_RESULT_CHECK(result);
210 } else { // we have to recover state 1
211 result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
212 WL_RESULT_CHECK(result);
213 result = this->flash_drv->write(this->addr_state1, state_copy, sizeof(wl_state_t));
214 WL_RESULT_CHECK(result);
215 for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) {
216 bool pos_bits;
217 result = this->flash_drv->read(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
218
219 WL_RESULT_CHECK(result);
220 pos_bits = this->OkBuffSet(i);
221 if (pos_bits == true) {
222 result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
223 WL_RESULT_CHECK(result);
224 }
225 }
226 result = this->flash_drv->read(this->addr_state1, &this->state, sizeof(wl_state_t));
227 WL_RESULT_CHECK(result);
228 this->state.pos = this->state.max_pos - 1;
229 }
230 // done. We have recovered the state
231 // If we have a new configuration, we will overwrite it
232 if (this->state.version != this->cfg.version) {
233 result = this->initSections();
234 WL_RESULT_CHECK(result);
235 }
236 }
237 if (result != ESP_OK) {
238 this->initialized = false;
239 ESP_LOGE(TAG, "%s: returned 0x%08x", __func__, (uint32_t)result);
240 return result;
241 }
242 this->initialized = true;
243 ESP_LOGD(TAG, "%s - move_count= 0x%08x", __func__, (uint32_t)this->state.move_count);
244 return ESP_OK;
245 }
246
recoverPos()247 esp_err_t WL_Flash::recoverPos()
248 {
249 esp_err_t result = ESP_OK;
250 size_t position = 0;
251 ESP_LOGV(TAG, "%s start", __func__);
252 for (size_t i = 0; i < this->state.max_pos; i++) {
253 bool pos_bits;
254 position = i;
255 result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
256 pos_bits = this->OkBuffSet(i);
257 WL_RESULT_CHECK(result);
258 ESP_LOGV(TAG, "%s - check pos: result=0x%08x, position= %i, pos_bits= 0x%08x", __func__, (uint32_t)result, (uint32_t)position, (uint32_t)pos_bits);
259 if (pos_bits == false) {
260 break; // we have found position
261 }
262 }
263
264 this->state.pos = position;
265 if (this->state.pos == this->state.max_pos) {
266 this->state.pos--;
267 }
268 ESP_LOGD(TAG, "%s - this->state.pos= 0x%08x, position= 0x%08x, result= 0x%08x, max_pos= 0x%08x", __func__, (uint32_t)this->state.pos, (uint32_t)position, (uint32_t)result, (uint32_t)this->state.max_pos);
269 ESP_LOGV(TAG, "%s done", __func__);
270 return result;
271 }
272
initSections()273 esp_err_t WL_Flash::initSections()
274 {
275 esp_err_t result = ESP_OK;
276 this->state.pos = 0;
277 this->state.access_count = 0;
278 this->state.move_count = 0;
279 // max count
280 this->state.max_count = this->flash_size / this->state_size * this->cfg.updaterate;
281 if (this->cfg.updaterate != 0) {
282 this->state.max_count = this->cfg.updaterate;
283 }
284 this->state.version = this->cfg.version;
285 this->state.block_size = this->cfg.page_size;
286 this->state.device_id = esp_random();
287 memset(this->state.reserved, 0, sizeof(this->state.reserved));
288
289 this->state.max_pos = 1 + this->flash_size / this->cfg.page_size;
290
291 this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
292
293 result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
294 WL_RESULT_CHECK(result);
295 result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t));
296 WL_RESULT_CHECK(result);
297 // write state copy
298 result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
299 WL_RESULT_CHECK(result);
300 result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
301 WL_RESULT_CHECK(result);
302
303 result = this->flash_drv->erase_range(this->addr_cfg, this->cfg_size);
304 WL_RESULT_CHECK(result);
305 result = this->flash_drv->write(this->addr_cfg, &this->cfg, sizeof(wl_config_t));
306 WL_RESULT_CHECK(result);
307
308 ESP_LOGD(TAG, "%s - this->state->max_count= 0x%08x, this->state->max_pos= 0x%08x", __func__, this->state.max_count, this->state.max_pos);
309 ESP_LOGD(TAG, "%s - result= 0x%08x", __func__, result);
310 return result;
311 }
312
updateVersion()313 esp_err_t WL_Flash::updateVersion()
314 {
315 esp_err_t result = ESP_OK;
316
317 result = this->updateV1_V2();
318 if (result == ESP_OK) {
319 return result;
320 }
321 // check next version
322 return result;
323 }
324
updateV1_V2()325 esp_err_t WL_Flash::updateV1_V2()
326 {
327 esp_err_t result = ESP_OK;
328 // Check crc for old version and old version
329 ESP_LOGV(TAG, "%s start", __func__);
330 int check_size = WL_STATE_CRC_LEN_V1;
331 // Chech CRC and recover state
332 uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
333 wl_state_t sa_copy;
334 wl_state_t *state_copy = &sa_copy;
335 result = this->flash_drv->read(this->addr_state2, state_copy, sizeof(wl_state_t));
336 WL_RESULT_CHECK(result);
337 uint32_t crc2 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_copy, check_size);
338
339 // For V1 crc in place of device_id and version
340 uint32_t v1_crc1 = this->state.device_id;
341 uint32_t v1_crc2 = state_copy->device_id;
342
343 ESP_LOGD(TAG, "%s - process crc1=0x%08x, crc2=0x%08x, v1_crc1=0x%08x, v1_crc2=0x%08x, version=%i", __func__, crc1, crc2, v1_crc1, v1_crc2, this->state.version);
344
345 if ((crc1 == v1_crc1) && (crc2 == v1_crc2) && (v1_crc1 == v1_crc2) && (this->state.version == 1) && (state_copy->version == 1)) {
346 // Here we have to update all internal structures
347 ESP_LOGI(TAG, "%s Update from V1 to V2, crc=0x%08x, ", __func__, crc1);
348 uint32_t pos = 0;
349
350 for (size_t i = 0; i < this->state.max_pos; i++) {
351 uint8_t pos_bits;
352 result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, &pos_bits, 1);
353 WL_RESULT_CHECK(result);
354 ESP_LOGV(TAG, "%s- result= 0x%08x, pos= %i, pos_bits= 0x%08x", __func__, (uint32_t)result, (uint32_t)pos, (uint32_t)pos_bits);
355 pos = i;
356 if (pos_bits == 0xff) {
357 break; // we have found position
358 }
359 }
360 ESP_LOGI(TAG, "%s max_pos=%i, pos=%i, state.ver=%i, state2.ver=%i", __func__, (uint32_t)this->state.max_pos, (uint32_t)pos, (uint32_t)this->state.version, (uint32_t)state_copy->version);
361 if (pos == this->state.max_pos) {
362 pos--;
363 }
364 WL_RESULT_CHECK(result);
365
366 this->state.version = 2;
367 this->state.pos = 0;
368 this->state.device_id = esp_random();
369 memset(this->state.reserved, 0, sizeof(this->state.reserved));
370 this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
371
372 result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
373 WL_RESULT_CHECK(result);
374 result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t));
375 WL_RESULT_CHECK(result);
376
377 memset(this->temp_buff, 0, this->cfg.wr_size);
378 for (uint32_t i = 0 ; i <= pos; i++) {
379 this->fillOkBuff(i);
380 result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
381 WL_RESULT_CHECK(result);
382 }
383
384 result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
385 WL_RESULT_CHECK(result);
386 result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
387 WL_RESULT_CHECK(result);
388 ESP_LOGD(TAG, "%s - move_count= 0x%08x, pos= 0x%08x", __func__, this->state.move_count, this->state.pos);
389
390 memset(this->temp_buff, 0, this->cfg.wr_size);
391 for (uint32_t i = 0 ; i <= pos; i++) {
392 this->fillOkBuff(i);
393 result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
394 WL_RESULT_CHECK(result);
395 }
396 this->state.pos = pos;
397 return result;
398 }
399
400 return ESP_FAIL;
401 }
402
fillOkBuff(int n)403 void WL_Flash::fillOkBuff(int n)
404 {
405 uint32_t *buff = (uint32_t *)this->temp_buff;
406
407 for (int i = 0 ; i < 4 ; i++) {
408 buff[i] = this->state.device_id + n * 4 + i;
409 buff[i] = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&buff[i], sizeof(uint32_t));
410 }
411 }
412
OkBuffSet(int n)413 bool WL_Flash::OkBuffSet(int n)
414 {
415 bool result = true;
416 uint32_t *data_buff = (uint32_t *)this->temp_buff;
417 for (int i = 0 ; i < 4 ; i++) {
418 uint32_t data = this->state.device_id + n * 4 + i;
419 uint32_t crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&data, sizeof(uint32_t));
420 if (crc != data_buff[i]) {
421 result = false;
422 }
423 }
424 return result;
425 }
426
427
updateWL()428 esp_err_t WL_Flash::updateWL()
429 {
430 esp_err_t result = ESP_OK;
431 this->state.access_count++;
432 if (this->state.access_count < this->state.max_count) {
433 return result;
434 }
435 // Here we have to move the block and increase the state
436 this->state.access_count = 0;
437 ESP_LOGV(TAG, "%s - access_count= 0x%08x, pos= 0x%08x", __func__, this->state.access_count, this->state.pos);
438 // copy data to dummy block
439 size_t data_addr = this->state.pos + 1; // next block, [pos+1] copy to [pos]
440 if (data_addr >= this->state.max_pos) {
441 data_addr = 0;
442 }
443 data_addr = this->cfg.start_addr + data_addr * this->cfg.page_size;
444 this->dummy_addr = this->cfg.start_addr + this->state.pos * this->cfg.page_size;
445 result = this->flash_drv->erase_range(this->dummy_addr, this->cfg.page_size);
446 if (result != ESP_OK) {
447 ESP_LOGE(TAG, "%s - erase wl dummy sector result= 0x%08x", __func__, result);
448 this->state.access_count = this->state.max_count - 1; // we will update next time
449 return result;
450 }
451
452 size_t copy_count = this->cfg.page_size / this->cfg.temp_buff_size;
453 for (size_t i = 0; i < copy_count; i++) {
454 result = this->flash_drv->read(data_addr + i * this->cfg.temp_buff_size, this->temp_buff, this->cfg.temp_buff_size);
455 if (result != ESP_OK) {
456 ESP_LOGE(TAG, "%s - not possible to read buffer, will try next time, result= 0x%08x", __func__, result);
457 this->state.access_count = this->state.max_count - 1; // we will update next time
458 return result;
459 }
460 result = this->flash_drv->write(this->dummy_addr + i * this->cfg.temp_buff_size, this->temp_buff, this->cfg.temp_buff_size);
461 if (result != ESP_OK) {
462 ESP_LOGE(TAG, "%s - not possible to write buffer, will try next time, result= 0x%08x", __func__, result);
463 this->state.access_count = this->state.max_count - 1; // we will update next time
464 return result;
465 }
466 }
467 // done... block moved.
468 // Here we will update structures...
469 // Update bits and save to flash:
470 uint32_t byte_pos = this->state.pos * this->cfg.wr_size;
471 this->fillOkBuff(this->state.pos);
472 // write state to mem. We updating only affected bits
473 result |= this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + byte_pos, this->temp_buff, this->cfg.wr_size);
474 if (result != ESP_OK) {
475 ESP_LOGE(TAG, "%s - update position 1 result= 0x%08x", __func__, result);
476 this->state.access_count = this->state.max_count - 1; // we will update next time
477 return result;
478 }
479 this->fillOkBuff(this->state.pos);
480 result |= this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + byte_pos, this->temp_buff, this->cfg.wr_size);
481 if (result != ESP_OK) {
482 ESP_LOGE(TAG, "%s - update position 2 result= 0x%08x", __func__, result);
483 this->state.access_count = this->state.max_count - 1; // we will update next time
484 return result;
485 }
486
487 this->state.pos++;
488 if (this->state.pos >= this->state.max_pos) {
489 this->state.pos = 0;
490 // one loop more
491 this->state.move_count++;
492 if (this->state.move_count >= (this->state.max_pos - 1)) {
493 this->state.move_count = 0;
494 }
495 // write main state
496 this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
497
498 result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
499 WL_RESULT_CHECK(result);
500 result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t));
501 WL_RESULT_CHECK(result);
502 result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
503 WL_RESULT_CHECK(result);
504 result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
505 WL_RESULT_CHECK(result);
506 ESP_LOGD(TAG, "%s - move_count= 0x%08x, pos= 0x%08x, ", __func__, this->state.move_count, this->state.pos);
507 }
508 // Save structures to the flash... and check result
509 if (result == ESP_OK) {
510 ESP_LOGV(TAG, "%s - result= 0x%08x", __func__, result);
511 } else {
512 ESP_LOGE(TAG, "%s - result= 0x%08x", __func__, result);
513 }
514 return result;
515 }
516
calcAddr(size_t addr)517 size_t WL_Flash::calcAddr(size_t addr)
518 {
519 size_t result = (this->flash_size - this->state.move_count * this->cfg.page_size + addr) % this->flash_size;
520 size_t dummy_addr = this->state.pos * this->cfg.page_size;
521 if (result < dummy_addr) {
522 } else {
523 result += this->cfg.page_size;
524 }
525 ESP_LOGV(TAG, "%s - addr= 0x%08x -> result= 0x%08x, dummy_addr= 0x%08x", __func__, (uint32_t) addr, (uint32_t) result, (uint32_t)dummy_addr);
526 return result;
527 }
528
529
chip_size()530 size_t WL_Flash::chip_size()
531 {
532 if (!this->configured) {
533 return 0;
534 }
535 return this->flash_size;
536 }
sector_size()537 size_t WL_Flash::sector_size()
538 {
539 if (!this->configured) {
540 return 0;
541 }
542 return this->cfg.sector_size;
543 }
544
545
erase_sector(size_t sector)546 esp_err_t WL_Flash::erase_sector(size_t sector)
547 {
548 esp_err_t result = ESP_OK;
549 if (!this->initialized) {
550 return ESP_ERR_INVALID_STATE;
551 }
552 ESP_LOGD(TAG, "%s - sector= 0x%08x", __func__, (uint32_t) sector);
553 result = this->updateWL();
554 WL_RESULT_CHECK(result);
555 size_t virt_addr = this->calcAddr(sector * this->cfg.sector_size);
556 result = this->flash_drv->erase_sector((this->cfg.start_addr + virt_addr) / this->cfg.sector_size);
557 WL_RESULT_CHECK(result);
558 return result;
559 }
erase_range(size_t start_address,size_t size)560 esp_err_t WL_Flash::erase_range(size_t start_address, size_t size)
561 {
562 esp_err_t result = ESP_OK;
563 if (!this->initialized) {
564 return ESP_ERR_INVALID_STATE;
565 }
566 ESP_LOGD(TAG, "%s - start_address= 0x%08x, size= 0x%08x", __func__, (uint32_t) start_address, (uint32_t) size);
567 size_t erase_count = (size + this->cfg.sector_size - 1) / this->cfg.sector_size;
568 size_t start_sector = start_address / this->cfg.sector_size;
569 for (size_t i = 0; i < erase_count; i++) {
570 result = this->erase_sector(start_sector + i);
571 WL_RESULT_CHECK(result);
572 }
573 ESP_LOGV(TAG, "%s - result= 0x%08x", __func__, result);
574 return result;
575 }
576
write(size_t dest_addr,const void * src,size_t size)577 esp_err_t WL_Flash::write(size_t dest_addr, const void *src, size_t size)
578 {
579 esp_err_t result = ESP_OK;
580 if (!this->initialized) {
581 return ESP_ERR_INVALID_STATE;
582 }
583 ESP_LOGD(TAG, "%s - dest_addr= 0x%08x, size= 0x%08x", __func__, (uint32_t) dest_addr, (uint32_t) size);
584 uint32_t count = (size - 1) / this->cfg.page_size;
585 for (size_t i = 0; i < count; i++) {
586 size_t virt_addr = this->calcAddr(dest_addr + i * this->cfg.page_size);
587 result = this->flash_drv->write(this->cfg.start_addr + virt_addr, &((uint8_t *)src)[i * this->cfg.page_size], this->cfg.page_size);
588 WL_RESULT_CHECK(result);
589 }
590 size_t virt_addr_last = this->calcAddr(dest_addr + count * this->cfg.page_size);
591 result = this->flash_drv->write(this->cfg.start_addr + virt_addr_last, &((uint8_t *)src)[count * this->cfg.page_size], size - count * this->cfg.page_size);
592 WL_RESULT_CHECK(result);
593 return result;
594 }
595
read(size_t src_addr,void * dest,size_t size)596 esp_err_t WL_Flash::read(size_t src_addr, void *dest, size_t size)
597 {
598 esp_err_t result = ESP_OK;
599 if (!this->initialized) {
600 return ESP_ERR_INVALID_STATE;
601 }
602 ESP_LOGD(TAG, "%s - src_addr= 0x%08x, size= 0x%08x", __func__, (uint32_t) src_addr, (uint32_t) size);
603 uint32_t count = (size - 1) / this->cfg.page_size;
604 for (size_t i = 0; i < count; i++) {
605 size_t virt_addr = this->calcAddr(src_addr + i * this->cfg.page_size);
606 ESP_LOGV(TAG, "%s - real_addr= 0x%08x, size= 0x%08x", __func__, (uint32_t) (this->cfg.start_addr + virt_addr), (uint32_t) size);
607 result = this->flash_drv->read(this->cfg.start_addr + virt_addr, &((uint8_t *)dest)[i * this->cfg.page_size], this->cfg.page_size);
608 WL_RESULT_CHECK(result);
609 }
610 size_t virt_addr_last = this->calcAddr(src_addr + count * this->cfg.page_size);
611 result = this->flash_drv->read(this->cfg.start_addr + virt_addr_last, &((uint8_t *)dest)[count * this->cfg.page_size], size - count * this->cfg.page_size);
612 WL_RESULT_CHECK(result);
613 return result;
614 }
615
get_drv()616 Flash_Access *WL_Flash::get_drv()
617 {
618 return this->flash_drv;
619 }
get_cfg()620 wl_config_t *WL_Flash::get_cfg()
621 {
622 return &this->cfg;
623 }
624
flush()625 esp_err_t WL_Flash::flush()
626 {
627 esp_err_t result = ESP_OK;
628 this->state.access_count = this->state.max_count - 1;
629 result = this->updateWL();
630 ESP_LOGD(TAG, "%s - result= 0x%08x, move_count= 0x%08x", __func__, result, this->state.move_count);
631 return result;
632 }
633