mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
The version of WL component changed from 1 to 2.
WL version 2 mark used sectors as 16 bytes block of bytes with CRC. This changes required because old version did not worked with encryption. Additional unit tests are implemented.
This commit is contained in:
parent
321b1e0205
commit
a6d6c58eca
@ -55,9 +55,10 @@ esp_err_t WL_Flash::config(wl_config_t *cfg, Flash_Access *flash_drv)
|
||||
cfg->version,
|
||||
(uint32_t) cfg->temp_buff_size);
|
||||
|
||||
cfg->crc = crc32::crc32_le(WL_CFG_CRC_CONST, (const unsigned char *)cfg, sizeof(wl_config_t) - sizeof(cfg->crc));
|
||||
cfg->crc = crc32::crc32_le(WL_CFG_CRC_CONST, (const unsigned char *)cfg, offsetof(wl_config_t, crc));
|
||||
esp_err_t result = ESP_OK;
|
||||
memcpy(&this->cfg, cfg, sizeof(wl_config_t));
|
||||
if (this->cfg.temp_buff_size < this->cfg.wr_size) this->cfg.temp_buff_size = this->cfg.wr_size;
|
||||
this->configured = false;
|
||||
if (cfg == NULL) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
@ -74,7 +75,6 @@ esp_err_t WL_Flash::config(wl_config_t *cfg, Flash_Access *flash_drv)
|
||||
}
|
||||
WL_RESULT_CHECK(result);
|
||||
|
||||
this->temp_buff = (uint8_t *)malloc(this->cfg.temp_buff_size);
|
||||
this->state_size = this->cfg.sector_size;
|
||||
if (this->state_size < (sizeof(wl_state_t) + (this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size)) {
|
||||
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;
|
||||
@ -87,11 +87,27 @@ esp_err_t WL_Flash::config(wl_config_t *cfg, Flash_Access *flash_drv)
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
ESP_LOGV(TAG, "%s - this->addr_state1=0x%08x", __func__, (uint32_t) this->addr_state1);
|
||||
ESP_LOGV(TAG, "%s - this->addr_state2=0x%08x", __func__, (uint32_t) this->addr_state2);
|
||||
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__,
|
||||
(uint32_t) this->state_size,
|
||||
(uint32_t) this->cfg_size,
|
||||
(uint32_t) this->addr_cfg,
|
||||
(uint32_t) this->addr_state1,
|
||||
(uint32_t) this->addr_state2,
|
||||
(uint32_t) this->flash_size
|
||||
);
|
||||
if (flash_sz <= 0) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
WL_RESULT_CHECK(result);
|
||||
|
||||
this->temp_buff = (uint8_t *)malloc(this->cfg.temp_buff_size);
|
||||
if (this->temp_buff == NULL) {
|
||||
result = ESP_ERR_NO_MEM;
|
||||
}
|
||||
WL_RESULT_CHECK(result);
|
||||
this->configured = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -112,12 +128,12 @@ esp_err_t WL_Flash::init()
|
||||
result = this->flash_drv->read(this->addr_state2, state_copy, sizeof(wl_state_t));
|
||||
WL_RESULT_CHECK(result);
|
||||
|
||||
int check_size = sizeof(wl_state_t) - sizeof(uint32_t);
|
||||
int check_size = offsetof(wl_state_t, crc);
|
||||
// Chech CRC and recover state
|
||||
uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
|
||||
uint32_t crc2 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_copy, check_size);
|
||||
|
||||
ESP_LOGD(TAG, "%s - config ID=%i, stored ID=%i, access_count=%i, block_size=%i, max_count=%i, pos=%i, move_count=%i",
|
||||
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",
|
||||
__func__,
|
||||
this->cfg.version,
|
||||
this->state.version,
|
||||
@ -127,8 +143,7 @@ esp_err_t WL_Flash::init()
|
||||
this->state.pos,
|
||||
this->state.move_count);
|
||||
|
||||
|
||||
ESP_LOGD(TAG, "%s starts: crc1=%i, crc2 = %i, this->state.crc=%i, state_copy->crc=%i", __func__, crc1, crc2, this->state.crc, state_copy->crc);
|
||||
ESP_LOGD(TAG, "%s starts: crc1=%i, crc2 = %i, this->state.crc=%i, state_copy->crc=%i, version=%i, read_version=%i", __func__, crc1, crc2, this->state.crc, state_copy->crc, this->cfg.version, this->state.version);
|
||||
if ((crc1 == this->state.crc) && (crc2 == state_copy->crc)) {
|
||||
// The state is OK. Check the ID
|
||||
if (this->state.version != this->cfg.version) {
|
||||
@ -143,11 +158,13 @@ esp_err_t WL_Flash::init()
|
||||
result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
|
||||
WL_RESULT_CHECK(result);
|
||||
for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size)*this->cfg.wr_size); i++) {
|
||||
uint8_t pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i, &pos_bits, 1);
|
||||
bool pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
if (pos_bits != 0xff) {
|
||||
result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i, &pos_bits, 1);
|
||||
pos_bits = this->OkBuffSet(i);
|
||||
if (pos_bits == true) {
|
||||
//this->fillOkBuff(i);
|
||||
result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
}
|
||||
@ -156,9 +173,13 @@ esp_err_t WL_Flash::init()
|
||||
result = this->recoverPos();
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
} else if ((crc1 != this->state.crc) && (crc2 != state_copy->crc)) { // This is just new flash
|
||||
result = this->initSections();
|
||||
WL_RESULT_CHECK(result);
|
||||
} else if ((crc1 != this->state.crc) && (crc2 != state_copy->crc)) { // This is just new flash or new version
|
||||
// Check if this is new version or just new instance of WL
|
||||
result = this->updateVersion();
|
||||
if (result == ESP_FAIL) {
|
||||
result = this->initSections();
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
result = this->recoverPos();
|
||||
WL_RESULT_CHECK(result);
|
||||
} else {
|
||||
@ -169,11 +190,12 @@ esp_err_t WL_Flash::init()
|
||||
result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
|
||||
WL_RESULT_CHECK(result);
|
||||
for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) {
|
||||
uint8_t pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i, &pos_bits, 1);
|
||||
bool pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
if (pos_bits != 0xff) {
|
||||
result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i, &pos_bits, 1);
|
||||
pos_bits = this->OkBuffSet(i);
|
||||
if (pos_bits == true) {
|
||||
result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
}
|
||||
@ -185,11 +207,13 @@ esp_err_t WL_Flash::init()
|
||||
result = this->flash_drv->write(this->addr_state1, state_copy, sizeof(wl_state_t));
|
||||
WL_RESULT_CHECK(result);
|
||||
for (size_t i = 0; i < ((this->cfg.full_mem_size / this->cfg.sector_size) * this->cfg.wr_size); i++) {
|
||||
uint8_t pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state2 + sizeof(wl_state_t) + i, &pos_bits, 1);
|
||||
bool pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
|
||||
WL_RESULT_CHECK(result);
|
||||
if (pos_bits != 0xff) {
|
||||
result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i, &pos_bits, 1);
|
||||
pos_bits = this->OkBuffSet(i);
|
||||
if (pos_bits == true) {
|
||||
result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
}
|
||||
@ -206,10 +230,11 @@ esp_err_t WL_Flash::init()
|
||||
}
|
||||
if (result != ESP_OK) {
|
||||
this->initialized = false;
|
||||
ESP_LOGE(TAG, "%s: returned 0x%x", __func__, result);
|
||||
ESP_LOGE(TAG, "%s: returned 0x%x", __func__, (uint32_t)result);
|
||||
return result;
|
||||
}
|
||||
this->initialized = true;
|
||||
ESP_LOGD(TAG, "%s - move_count=%08x", __func__, (uint32_t)this->state.move_count);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -217,20 +242,25 @@ esp_err_t WL_Flash::recoverPos()
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
size_t position = 0;
|
||||
ESP_LOGV(TAG, "%s start", __func__);
|
||||
for (size_t i = 0; i < this->state.max_pos; i++) {
|
||||
uint8_t pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, &pos_bits, 1);
|
||||
WL_RESULT_CHECK(result);
|
||||
bool pos_bits = false;
|
||||
position = i;
|
||||
if (pos_bits == 0xff) {
|
||||
result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
pos_bits = this->OkBuffSet(i);
|
||||
WL_RESULT_CHECK(result);
|
||||
ESP_LOGV(TAG, "%s - check pos: result=%i, position=%i, pos_bits=0x%08x", __func__, (uint32_t)result, (uint32_t)position, (uint32_t)pos_bits);
|
||||
if (pos_bits == false) {
|
||||
break; // we have found position
|
||||
}
|
||||
}
|
||||
|
||||
this->state.pos = position;
|
||||
if (this->state.pos == this->state.max_pos) {
|
||||
this->state.pos--;
|
||||
}
|
||||
ESP_LOGD(TAG, "%s - this->state.pos=0x%08x, result=%08x", __func__, this->state.pos, result);
|
||||
ESP_LOGD(TAG, "%s - this->state.pos=0x%08x, position=0x%08x, result=%08x, max_pos=%08x", __func__, (uint32_t)this->state.pos, (uint32_t)position, (uint32_t)result, (uint32_t)this->state.max_pos);
|
||||
ESP_LOGV(TAG, "%s done", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -248,10 +278,11 @@ esp_err_t WL_Flash::initSections()
|
||||
this->state.version = this->cfg.version;
|
||||
this->state.block_size = this->cfg.page_size;
|
||||
this->used_bits = 0;
|
||||
this->state.device_id = rand();
|
||||
|
||||
this->state.max_pos = 1 + this->flash_size / this->cfg.page_size;
|
||||
|
||||
this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, sizeof(wl_state_t) - sizeof(uint32_t));
|
||||
this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, offsetof(wl_state_t, crc));
|
||||
|
||||
result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
@ -273,6 +304,108 @@ esp_err_t WL_Flash::initSections()
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t WL_Flash::updateVersion()
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
result = this->updateV1_V2();
|
||||
if (ESP_OK == result) return result;
|
||||
// check next version
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t WL_Flash::updateV1_V2()
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
// Check crc for old version and old version
|
||||
ESP_LOGV(TAG, "%s start", __func__);
|
||||
int check_size = offsetof(wl_state_t, crc) - sizeof(uint32_t);
|
||||
// Chech CRC and recover state
|
||||
uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
|
||||
// For V1 crc in place of device_id and version
|
||||
uint32_t v1_crc = this->state.device_id;
|
||||
|
||||
ESP_LOGD(TAG, "%s - process crc1=0x%08x v1_crc=0x%08x, version=%i", __func__, crc1, v1_crc, this->state.version);
|
||||
|
||||
if ((crc1 == v1_crc) && (this->state.version == 1)){
|
||||
// Here we have to update all internal structures
|
||||
ESP_LOGV(TAG, "%s Update from V1 to V2", __func__);
|
||||
uint32_t pos = 0;
|
||||
|
||||
for (size_t i = 0; i < this->state.max_pos; i++) {
|
||||
uint8_t pos_bits = 0;
|
||||
result = this->flash_drv->read(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, &pos_bits, 1);
|
||||
WL_RESULT_CHECK(result);
|
||||
ESP_LOGV(TAG, "%s- result=%i, pos=%i, pos_bits=0x%08x", __func__, (uint32_t)result, (uint32_t)pos, (uint32_t)pos_bits);
|
||||
pos = i;
|
||||
if (pos_bits == 0xff) {
|
||||
break; // we have found position
|
||||
}
|
||||
}
|
||||
if (pos == this->state.max_pos) {
|
||||
pos--;
|
||||
}
|
||||
WL_RESULT_CHECK(result);
|
||||
|
||||
this->state.version = 2;
|
||||
this->state.pos = 0;
|
||||
this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, offsetof(wl_state_t, crc));
|
||||
this->state.device_id = rand();
|
||||
|
||||
result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
result = this->flash_drv->write(this->addr_state1, &this->state, sizeof(wl_state_t));
|
||||
WL_RESULT_CHECK(result);
|
||||
|
||||
memset(this->temp_buff, 0, this->cfg.wr_size);
|
||||
for (int i=0 ; i< pos; i++) {
|
||||
this->fillOkBuff(i);
|
||||
result = this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
|
||||
result = this->flash_drv->erase_range(this->addr_state2, this->state_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
|
||||
WL_RESULT_CHECK(result);
|
||||
ESP_LOGD(TAG, "%s - move_count=%08x, pos=%08x, ", __func__, this->state.move_count, this->state.pos);
|
||||
|
||||
memset(this->temp_buff, 0, this->cfg.wr_size);
|
||||
for (int i=0 ; i< pos; i++) {
|
||||
this->fillOkBuff(i);
|
||||
result = this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + i * this->cfg.wr_size, this->temp_buff, this->cfg.wr_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
this->state.pos = pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
void WL_Flash::fillOkBuff(int n)
|
||||
{
|
||||
uint32_t* buff = (uint32_t*)this->temp_buff;
|
||||
|
||||
for (int i=0 ; i< 4 ; i++) {
|
||||
buff[i] = this->state.device_id + n*4 + i;
|
||||
buff[i] = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&buff[i], sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
bool WL_Flash::OkBuffSet(int n)
|
||||
{
|
||||
bool result = true;
|
||||
uint32_t* data_buff = (uint32_t*)this->temp_buff;
|
||||
for (int i=0 ; i< 4 ; i++) {
|
||||
uint32_t data = this->state.device_id + n*4 + i;
|
||||
uint32_t crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&data, sizeof(uint32_t));
|
||||
if (crc != data_buff[i]) result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t WL_Flash::updateWL()
|
||||
{
|
||||
esp_err_t result = ESP_OK;
|
||||
@ -316,15 +449,16 @@ esp_err_t WL_Flash::updateWL()
|
||||
// Here we will update structures...
|
||||
// Update bits and save to flash:
|
||||
uint32_t byte_pos = this->state.pos * this->cfg.wr_size;
|
||||
this->used_bits = 0;
|
||||
this->fillOkBuff(this->state.pos);
|
||||
// write state to mem. We updating only affected bits
|
||||
result |= this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + byte_pos, &this->used_bits, this->cfg.wr_size);
|
||||
result |= this->flash_drv->write(this->addr_state1 + sizeof(wl_state_t) + byte_pos, this->temp_buff, this->cfg.wr_size);
|
||||
if (result != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s - update position 1 result=%08x", __func__, result);
|
||||
this->state.access_count = this->state.max_count - 1; // we will update next time
|
||||
return result;
|
||||
}
|
||||
result |= this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + byte_pos, &this->used_bits, this->cfg.wr_size);
|
||||
this->fillOkBuff(this->state.pos);
|
||||
result |= this->flash_drv->write(this->addr_state2 + sizeof(wl_state_t) + byte_pos, this->temp_buff, this->cfg.wr_size);
|
||||
if (result != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s - update position 2 result=%08x", __func__, result);
|
||||
this->state.access_count = this->state.max_count - 1; // we will update next time
|
||||
@ -340,7 +474,7 @@ esp_err_t WL_Flash::updateWL()
|
||||
this->state.move_count = 0;
|
||||
}
|
||||
// write main state
|
||||
this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, sizeof(wl_state_t) - sizeof(uint32_t));
|
||||
this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, offsetof(wl_state_t, crc));
|
||||
|
||||
result = this->flash_drv->erase_range(this->addr_state1, this->state_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
@ -350,7 +484,7 @@ esp_err_t WL_Flash::updateWL()
|
||||
WL_RESULT_CHECK(result);
|
||||
result = this->flash_drv->write(this->addr_state2, &this->state, sizeof(wl_state_t));
|
||||
WL_RESULT_CHECK(result);
|
||||
ESP_LOGD(TAG, "%s - move_count=%08x", __func__, this->state.move_count);
|
||||
ESP_LOGD(TAG, "%s - move_count=%08x, pos=%08x, ", __func__, this->state.move_count, this->state.pos);
|
||||
}
|
||||
// Save structures to the flash... and check result
|
||||
if (result == ESP_OK) {
|
||||
@ -369,7 +503,7 @@ size_t WL_Flash::calcAddr(size_t addr)
|
||||
} else {
|
||||
result += this->cfg.page_size;
|
||||
}
|
||||
ESP_LOGV(TAG, "%s - addr=0x%08x -> result=0x%08x", __func__, (uint32_t) addr, (uint32_t) result);
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -396,7 +530,7 @@ esp_err_t WL_Flash::erase_sector(size_t sector)
|
||||
if (!this->initialized) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ESP_LOGV(TAG, "%s - sector=0x%08x", __func__, (uint32_t) sector);
|
||||
ESP_LOGD(TAG, "%s - sector=0x%08x", __func__, (uint32_t) sector);
|
||||
result = this->updateWL();
|
||||
WL_RESULT_CHECK(result);
|
||||
size_t virt_addr = this->calcAddr(sector * this->cfg.sector_size);
|
||||
@ -410,7 +544,7 @@ esp_err_t WL_Flash::erase_range(size_t start_address, size_t size)
|
||||
if (!this->initialized) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ESP_LOGV(TAG, "%s - start_address=0x%08x, size=0x%08x", __func__, (uint32_t) start_address, (uint32_t) size);
|
||||
ESP_LOGD(TAG, "%s - start_address=0x%08x, size=0x%08x", __func__, (uint32_t) start_address, (uint32_t) size);
|
||||
size_t erase_count = (size + this->cfg.sector_size - 1) / this->cfg.sector_size;
|
||||
size_t start_sector = start_address / this->cfg.sector_size;
|
||||
for (size_t i = 0; i < erase_count; i++) {
|
||||
@ -427,7 +561,7 @@ esp_err_t WL_Flash::write(size_t dest_addr, const void *src, size_t size)
|
||||
if (!this->initialized) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ESP_LOGV(TAG, "%s - dest_addr=0x%08x, size=0x%08x", __func__, (uint32_t) dest_addr, (uint32_t) size);
|
||||
ESP_LOGD(TAG, "%s - dest_addr=0x%08x, size=0x%08x", __func__, (uint32_t) dest_addr, (uint32_t) size);
|
||||
uint32_t count = (size - 1) / this->cfg.page_size;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t virt_addr = this->calcAddr(dest_addr + i * this->cfg.page_size);
|
||||
@ -446,10 +580,11 @@ esp_err_t WL_Flash::read(size_t src_addr, void *dest, size_t size)
|
||||
if (!this->initialized) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ESP_LOGV(TAG, "%s - src_addr=0x%08x, size=0x%08x", __func__, (uint32_t) src_addr, (uint32_t) size);
|
||||
ESP_LOGD(TAG, "%s - src_addr=0x%08x, size=0x%08x", __func__, (uint32_t) src_addr, (uint32_t) size);
|
||||
uint32_t count = (size - 1) / this->cfg.page_size;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t virt_addr = this->calcAddr(src_addr + i * this->cfg.page_size);
|
||||
ESP_LOGV(TAG, "%s - real_addr=0x%08x, size=0x%08x", __func__, (uint32_t) this->cfg.start_addr + virt_addr, (uint32_t) size);
|
||||
result = this->flash_drv->read(this->cfg.start_addr + virt_addr, &((uint8_t *)dest)[i * this->cfg.page_size], this->cfg.page_size);
|
||||
WL_RESULT_CHECK(result);
|
||||
}
|
||||
@ -473,6 +608,6 @@ esp_err_t WL_Flash::flush()
|
||||
esp_err_t result = ESP_OK;
|
||||
this->state.access_count = this->state.max_count - 1;
|
||||
result = this->updateWL();
|
||||
ESP_LOGV(TAG, "%s - result=%08x", __func__, result);
|
||||
ESP_LOGD(TAG, "%s - result=%08x, move_count=%08x", __func__, result, this->state.move_count);
|
||||
return result;
|
||||
}
|
||||
|
@ -66,11 +66,17 @@ protected:
|
||||
uint8_t *temp_buff = NULL;
|
||||
size_t dummy_addr;
|
||||
uint8_t used_bits;
|
||||
uint32_t pos_data[4];
|
||||
|
||||
esp_err_t initSections();
|
||||
esp_err_t updateWL();
|
||||
esp_err_t recoverPos();
|
||||
size_t calcAddr(size_t addr);
|
||||
|
||||
esp_err_t updateVersion();
|
||||
esp_err_t updateV1_V2();
|
||||
void fillOkBuff(int n);
|
||||
bool OkBuffSet(int n);
|
||||
};
|
||||
|
||||
#endif // _WL_Flash_H_
|
||||
|
@ -19,7 +19,15 @@
|
||||
* @brief This structure is used to store current state of flash access
|
||||
*
|
||||
*/
|
||||
typedef struct WL_State_s {
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGNED_(x) __declspec(align(x))
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct ALIGNED_(32) WL_State_s {
|
||||
public:
|
||||
uint32_t pos; /*!< current dummy block position*/
|
||||
uint32_t max_pos; /*!< maximum amount of positions*/
|
||||
@ -28,6 +36,7 @@ public:
|
||||
uint32_t max_count; /*!< max access count when block will be moved*/
|
||||
uint32_t block_size; /*!< size of move block*/
|
||||
uint32_t version; /*!< state id used to identify the version of current libary implementaion*/
|
||||
uint32_t device_id; /*!< ID of current WL instance*/
|
||||
uint32_t crc; /*!< CRC of structure*/
|
||||
} wl_state_t;
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "freertos/portable.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_clk.h"
|
||||
#include "soc/cpu.h"
|
||||
|
||||
TEST_CASE("wl_unmount doesn't leak memory", "[wear_levelling]")
|
||||
{
|
||||
@ -27,19 +29,26 @@ TEST_CASE("wl_mount check partition parameters", "[wear_levelling][ignore]")
|
||||
memcpy(&fake_partition, test_partition, sizeof(fake_partition));
|
||||
wl_handle_t handle;
|
||||
size_t size_before, size_after;
|
||||
wl_unmount(WL_INVALID_HANDLE);
|
||||
|
||||
// test small partition
|
||||
fake_partition.size = SPI_FLASH_SEC_SIZE;
|
||||
size_before = xPortGetFreeHeapSize();
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, wl_mount(&fake_partition, &handle));
|
||||
size_after = xPortGetFreeHeapSize();
|
||||
TEST_ASSERT_EQUAL_HEX32(size_before, size_after);
|
||||
// currently this test leaks memory
|
||||
esp_partition_erase_range(test_partition, test_partition->address, test_partition->size);
|
||||
// test small partition: result should be error
|
||||
for (int i=0 ; i< 5 ; i++)
|
||||
{
|
||||
fake_partition.size = SPI_FLASH_SEC_SIZE*(i);
|
||||
size_before = xPortGetFreeHeapSize();
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, wl_mount(&fake_partition, &handle));
|
||||
size_after = xPortGetFreeHeapSize();
|
||||
TEST_ASSERT_EQUAL_HEX32(size_before, size_after);
|
||||
printf("Test for size 0x%08x passed\n", fake_partition.size);
|
||||
// currently this test leaks memory
|
||||
}
|
||||
|
||||
// test slightly bigger partition
|
||||
fake_partition.size = SPI_FLASH_SEC_SIZE * 3;
|
||||
// test minimum size partition: result should be OK
|
||||
fake_partition.size = SPI_FLASH_SEC_SIZE * 5;
|
||||
size_before = xPortGetFreeHeapSize();
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, wl_mount(&fake_partition, &handle));
|
||||
TEST_ESP_OK(wl_mount(&fake_partition, &handle));
|
||||
wl_unmount(handle);
|
||||
size_after = xPortGetFreeHeapSize();
|
||||
TEST_ASSERT_EQUAL_HEX32(size_before, size_after);
|
||||
// currently this test hangs
|
||||
@ -151,3 +160,79 @@ TEST_CASE("multiple tasks can access wl handle simultaneously", "[wear_levelling
|
||||
vSemaphoreDelete(args4.done);
|
||||
wl_unmount(handle);
|
||||
}
|
||||
|
||||
#define TEST_SECTORS_COUNT 8
|
||||
|
||||
static void check_mem_data(wl_handle_t handle, uint32_t init_val, uint32_t* buff)
|
||||
{
|
||||
size_t sector_size = wl_sector_size(handle);
|
||||
|
||||
for (int m=0 ; m < TEST_SECTORS_COUNT ; m++) {
|
||||
TEST_ESP_OK(wl_read(handle, sector_size * m, buff, sector_size));
|
||||
for (int i=0 ; i< sector_size/sizeof(uint32_t) ; i++) {
|
||||
uint32_t compare_val = init_val + i + m*sector_size;
|
||||
TEST_ASSERT_EQUAL( buff[i], compare_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We write complete memory with defined data
|
||||
// And then write one sector many times.
|
||||
// A data in other secors should be the same.
|
||||
// We do this also with unmount
|
||||
TEST_CASE("multiple write is correct", "[wear_levelling]")
|
||||
{
|
||||
const esp_partition_t *partition = get_test_data_partition();
|
||||
esp_partition_t fake_partition;
|
||||
memcpy(&fake_partition, partition, sizeof(fake_partition));
|
||||
|
||||
fake_partition.size = SPI_FLASH_SEC_SIZE*(4 + TEST_SECTORS_COUNT);
|
||||
|
||||
wl_handle_t handle;
|
||||
TEST_ESP_OK(wl_mount(&fake_partition, &handle));
|
||||
|
||||
size_t sector_size = wl_sector_size(handle);
|
||||
// Erase 8 sectors
|
||||
TEST_ESP_OK(wl_erase_range(handle, 0, sector_size * TEST_SECTORS_COUNT));
|
||||
// Write data to all sectors
|
||||
printf("Check 1 sector_size=0x%08x\n", sector_size);
|
||||
// Set initial random value
|
||||
uint32_t init_val = rand();
|
||||
|
||||
uint32_t* buff = (uint32_t*)malloc(sector_size);
|
||||
for (int m=0 ; m < TEST_SECTORS_COUNT ; m++) {
|
||||
for (int i=0 ; i< sector_size/sizeof(uint32_t) ; i++) {
|
||||
buff[i] = init_val + i + m*sector_size;
|
||||
}
|
||||
TEST_ESP_OK(wl_erase_range(handle, sector_size*m, sector_size));
|
||||
TEST_ESP_OK(wl_write(handle, sector_size*m, buff, sector_size));
|
||||
}
|
||||
|
||||
check_mem_data(handle, init_val, buff);
|
||||
|
||||
uint32_t start;
|
||||
RSR(CCOUNT, start);
|
||||
|
||||
|
||||
for (int m=0 ; m< 100000 ; m++) {
|
||||
uint32_t sector = m % TEST_SECTORS_COUNT;
|
||||
for (int i=0 ; i< sector_size/sizeof(uint32_t) ; i++) {
|
||||
buff[i] = init_val + i + sector*sector_size;
|
||||
}
|
||||
TEST_ESP_OK(wl_erase_range(handle, sector_size*sector, sector_size));
|
||||
TEST_ESP_OK(wl_write(handle, sector_size*sector, buff, sector_size));
|
||||
check_mem_data(handle, init_val, buff);
|
||||
|
||||
uint32_t end;
|
||||
RSR(CCOUNT, end);
|
||||
uint32_t ms = (end - start) / (esp_clk_cpu_freq() / 1000);
|
||||
printf("loop %4i pass, time= %ims\n", m, ms);
|
||||
if (ms > 10000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buff);
|
||||
wl_unmount(handle);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
||||
#endif //WL_DEFAULT_START_ADDR
|
||||
|
||||
#ifndef WL_CURRENT_VERSION
|
||||
#define WL_CURRENT_VERSION 1
|
||||
#define WL_CURRENT_VERSION 2
|
||||
#endif //WL_CURRENT_VERSION
|
||||
|
||||
typedef struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user