Skip to content

Commit 4621cd5

Browse files
committed
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.
1 parent 870aa2d commit 4621cd5

File tree

2 files changed

+71
-17
lines changed

2 files changed

+71
-17
lines changed

ports/esp32s2/common-hal/nvm/ByteArray.c

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#include <string.h>
28+
2729
#include "common-hal/nvm/ByteArray.h"
30+
#include "bindings/espidf/__init__.h"
2831

2932
#include "py/runtime.h"
33+
#include "py/gc.h"
3034
#include "nvs_flash.h"
3135

3236
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) {
5054
}
5155
}
5256

57+
// Get a copy of the nvm data, or an array initialized to all 0 bytes if it is not present
58+
static esp_err_t get_bytes(nvs_handle_t handle, uint8_t **buf_out) {
59+
size_t size;
60+
void *buf;
61+
esp_err_t result = nvs_get_blob(handle, "data", NULL, &size);
62+
if (result == ESP_ERR_NVS_NOT_FOUND) {
63+
size = CIRCUITPY_INTERNAL_NVM_SIZE;
64+
} else if (result != ESP_OK) {
65+
*buf_out = NULL;
66+
return result;
67+
}
68+
buf = gc_alloc(size, 0, false); // this SHOULD be the same as
69+
if (result == ESP_OK) {
70+
result = nvs_get_blob(handle, "data", buf, &size);
71+
} else {
72+
result = ESP_OK;
73+
}
74+
*buf_out = buf;
75+
return result;
76+
}
77+
5378
bool common_hal_nvm_bytearray_set_bytes(nvm_bytearray_obj_t *self,
5479
uint32_t start_index, uint8_t *values, uint32_t len) {
55-
char index[9];
5680

5781
// start nvs
5882
nvs_handle_t handle;
5983
get_nvs_handle(&handle);
6084

61-
// stage flash changes
62-
for (uint32_t i = 0; i < len; i++) {
63-
sprintf(index, "%i", start_index + i);
64-
if (nvs_set_u8(handle, (const char *)index, values[i]) != ESP_OK) {
65-
return false;
66-
}
85+
// get from flash
86+
uint8_t *buf = NULL;
87+
esp_err_t result = get_bytes(handle, &buf);
88+
if (result != ESP_OK) {
89+
gc_free(buf);
90+
nvs_close(handle);
91+
raise_esp_error(result);
92+
}
93+
94+
// erase old data, including 6.3.x incompatible data
95+
result = nvs_erase_all(handle);
96+
if (result != ESP_OK) {
97+
gc_free(buf);
98+
nvs_close(handle);
99+
raise_esp_error(result);
100+
}
101+
102+
// make our modification
103+
memcpy(buf + start_index, values, len);
104+
105+
result = nvs_set_blob(handle, "data", buf, CIRCUITPY_INTERNAL_NVM_SIZE);
106+
if (result != ESP_OK) {
107+
gc_free(buf);
108+
nvs_close(handle);
109+
raise_esp_error(result);
67110
}
68111

69-
// commit flash changes
70-
if (nvs_commit(handle) != ESP_OK) {
71-
return false;
112+
result = nvs_commit(handle);
113+
if (result != ESP_OK) {
114+
gc_free(buf);
115+
nvs_close(handle);
116+
raise_esp_error(result);
72117
}
73118

74119
// close nvs
120+
gc_free(buf);
75121
nvs_close(handle);
76122
return true;
77123
}
78124

79125
void common_hal_nvm_bytearray_get_bytes(nvm_bytearray_obj_t *self,
80126
uint32_t start_index, uint32_t len, uint8_t *values) {
81-
char index[9];
82127

83128
// start nvs
84129
nvs_handle_t handle;
85130
get_nvs_handle(&handle);
86131

87132
// get from flash
88-
for (uint32_t i = 0; i < len; i++) {
89-
sprintf(index, "%i", start_index + i);
90-
if (nvs_get_u8(handle, (const char *)index, &values[i]) != ESP_OK) {
91-
mp_raise_RuntimeError(translate("NVS Error"));
92-
}
133+
uint8_t *buf;
134+
esp_err_t result = get_bytes(handle, &buf);
135+
if (result != ESP_OK) {
136+
gc_free(buf);
137+
nvs_close(handle);
138+
raise_esp_error(result);
93139
}
94140

141+
// copy the subset of data requested
142+
memcpy(values, buf + start_index, len);
143+
95144
// close nvs
145+
gc_free(buf);
96146
nvs_close(handle);
97147
}

ports/esp32s2/mpconfigport.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,12 @@
4242

4343
#define CIRCUITPY_INTERNAL_NVM_START_ADDR (0x9000)
4444

45+
// 20kB is statically allocated to nvs, but when overwriting an existing
46+
// item, it's temporarily necessary to store both the old and new copies.
47+
// Additionally, there is some overhad for the names and values of items
48+
// in nvs. So, set the size at 9/20ths of the allocated space
4549
#ifndef CIRCUITPY_INTERNAL_NVM_SIZE
46-
#define CIRCUITPY_INTERNAL_NVM_SIZE (20 * 1024)
50+
#define CIRCUITPY_INTERNAL_NVM_SIZE (9 * 1024)
4751
#endif
4852

4953
#endif // __INCLUDED_ESP32S2_MPCONFIGPORT_H

0 commit comments

Comments
 (0)