esp32s2: update how nvm is mapped onto nvs
The old way mapped each byte of nvm onto a distinct nvs key, but this allowed storage of only a very small number of bytes out of the theoretical capacity. Reworked like this, about half of the nvs capacity can be used for nvm, so you're guaranteed the ability to store 9kB this way.
This commit is contained in:
parent
870aa2d79d
commit
4621cd54fb
|
@ -24,9 +24,13 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common-hal/nvm/ByteArray.h"
|
||||
#include "bindings/espidf/__init__.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
uint32_t common_hal_nvm_bytearray_get_length(nvm_bytearray_obj_t *self) {
|
||||
|
@ -50,48 +54,94 @@ static void get_nvs_handle(nvs_handle_t *nvs_handle) {
|
|||
}
|
||||
}
|
||||
|
||||
// Get a copy of the nvm data, or an array initialized to all 0 bytes if it is not present
|
||||
static esp_err_t get_bytes(nvs_handle_t handle, uint8_t **buf_out) {
|
||||
size_t size;
|
||||
void *buf;
|
||||
esp_err_t result = nvs_get_blob(handle, "data", NULL, &size);
|
||||
if (result == ESP_ERR_NVS_NOT_FOUND) {
|
||||
size = CIRCUITPY_INTERNAL_NVM_SIZE;
|
||||
} else if (result != ESP_OK) {
|
||||
*buf_out = NULL;
|
||||
return result;
|
||||
}
|
||||
buf = gc_alloc(size, 0, false); // this SHOULD be the same as
|
||||
if (result == ESP_OK) {
|
||||
result = nvs_get_blob(handle, "data", buf, &size);
|
||||
} else {
|
||||
result = ESP_OK;
|
||||
}
|
||||
*buf_out = buf;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool common_hal_nvm_bytearray_set_bytes(nvm_bytearray_obj_t *self,
|
||||
uint32_t start_index, uint8_t *values, uint32_t len) {
|
||||
char index[9];
|
||||
|
||||
// start nvs
|
||||
nvs_handle_t handle;
|
||||
get_nvs_handle(&handle);
|
||||
|
||||
// stage flash changes
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
sprintf(index, "%i", start_index + i);
|
||||
if (nvs_set_u8(handle, (const char *)index, values[i]) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// commit flash changes
|
||||
if (nvs_commit(handle) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// close nvs
|
||||
nvs_close(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void common_hal_nvm_bytearray_get_bytes(nvm_bytearray_obj_t *self,
|
||||
uint32_t start_index, uint32_t len, uint8_t *values) {
|
||||
char index[9];
|
||||
|
||||
// start nvs
|
||||
nvs_handle_t handle;
|
||||
get_nvs_handle(&handle);
|
||||
|
||||
// get from flash
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
sprintf(index, "%i", start_index + i);
|
||||
if (nvs_get_u8(handle, (const char *)index, &values[i]) != ESP_OK) {
|
||||
mp_raise_RuntimeError(translate("NVS Error"));
|
||||
uint8_t *buf = NULL;
|
||||
esp_err_t result = get_bytes(handle, &buf);
|
||||
if (result != ESP_OK) {
|
||||
gc_free(buf);
|
||||
nvs_close(handle);
|
||||
raise_esp_error(result);
|
||||
}
|
||||
|
||||
// erase old data, including 6.3.x incompatible data
|
||||
result = nvs_erase_all(handle);
|
||||
if (result != ESP_OK) {
|
||||
gc_free(buf);
|
||||
nvs_close(handle);
|
||||
raise_esp_error(result);
|
||||
}
|
||||
|
||||
// make our modification
|
||||
memcpy(buf + start_index, values, len);
|
||||
|
||||
result = nvs_set_blob(handle, "data", buf, CIRCUITPY_INTERNAL_NVM_SIZE);
|
||||
if (result != ESP_OK) {
|
||||
gc_free(buf);
|
||||
nvs_close(handle);
|
||||
raise_esp_error(result);
|
||||
}
|
||||
|
||||
result = nvs_commit(handle);
|
||||
if (result != ESP_OK) {
|
||||
gc_free(buf);
|
||||
nvs_close(handle);
|
||||
raise_esp_error(result);
|
||||
}
|
||||
|
||||
// close nvs
|
||||
gc_free(buf);
|
||||
nvs_close(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void common_hal_nvm_bytearray_get_bytes(nvm_bytearray_obj_t *self,
|
||||
uint32_t start_index, uint32_t len, uint8_t *values) {
|
||||
|
||||
// start nvs
|
||||
nvs_handle_t handle;
|
||||
get_nvs_handle(&handle);
|
||||
|
||||
// get from flash
|
||||
uint8_t *buf;
|
||||
esp_err_t result = get_bytes(handle, &buf);
|
||||
if (result != ESP_OK) {
|
||||
gc_free(buf);
|
||||
nvs_close(handle);
|
||||
raise_esp_error(result);
|
||||
}
|
||||
|
||||
// copy the subset of data requested
|
||||
memcpy(values, buf + start_index, len);
|
||||
|
||||
// close nvs
|
||||
gc_free(buf);
|
||||
nvs_close(handle);
|
||||
}
|
||||
|
|
|
@ -42,8 +42,12 @@
|
|||
|
||||
#define CIRCUITPY_INTERNAL_NVM_START_ADDR (0x9000)
|
||||
|
||||
// 20kB is statically allocated to nvs, but when overwriting an existing
|
||||
// item, it's temporarily necessary to store both the old and new copies.
|
||||
// Additionally, there is some overhad for the names and values of items
|
||||
// in nvs. So, set the size at 9/20ths of the allocated space
|
||||
#ifndef CIRCUITPY_INTERNAL_NVM_SIZE
|
||||
#define CIRCUITPY_INTERNAL_NVM_SIZE (20 * 1024)
|
||||
#define CIRCUITPY_INTERNAL_NVM_SIZE (9 * 1024)
|
||||
#endif
|
||||
|
||||
#endif // __INCLUDED_ESP32S2_MPCONFIGPORT_H
|
||||
|
|
Loading…
Reference in New Issue