Skip to content

Commit 24065c6

Browse files
committed
refactor(examples/storage): update nvs_rw_blob and nvs_rw_value examples
1 parent e4e56a4 commit 24065c6

File tree

6 files changed

+318
-260
lines changed

6 files changed

+318
-260
lines changed

examples/storage/nvs/nvs_rw_blob/README.md

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Example also shows how to implement diagnostics if read / write operation was su
1414

1515
Detailed functional description of NVS and API is provided in [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/nvs_flash.html).
1616

17-
If not done already, consider checking simpler example *storage/nvs_rw_value*, that has been used as a starting point for preparing this one.
17+
If not done already, consider checking simpler example *storage/nvs/nvs_rw_value*, that has been used as a starting point for preparing this one.
1818

1919
## How to use example
2020

@@ -36,34 +36,27 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
3636

3737
## Example Output
3838

39-
First run:
4039
```
41-
Restart counter = 0
42-
Run time:
43-
Nothing saved yet!
44-
```
45-
46-
At this point, press "Boot" button and hold it for a second. The board will perform software restart, printing:
47-
48-
```
49-
Restarting...
50-
```
51-
52-
After booting again, restart counter and run time array will be printed:
53-
54-
```
55-
Restart counter = 1
56-
Run time:
57-
1: 5110
58-
```
59-
60-
After pressing "Boot" once more:
61-
62-
```
63-
Restart counter = 2
64-
Run time:
65-
1: 5110
66-
2: 5860
67-
```
68-
69-
To reset the counter and run time array, erase the contents of flash memory using `idf.py erase-flash`, then upload the program again as described above.
40+
...
41+
I (288) main_task: Calling app_main()
42+
I (298) nvs_blob_example: Saving test data blob...
43+
I (308) nvs_blob_example:
44+
Reading updated blob data:
45+
I (308) nvs_blob_example: Reading test data blob:
46+
I (308) nvs_blob_example: ID: 123
47+
I (308) nvs_blob_example: Name: Test Sample
48+
I (308) nvs_blob_example: Values: 3.140, 2.718, -0.000, 0.000
49+
I (318) nvs_blob_example: Flags: 0xABCD1234
50+
I (318) nvs_blob_example: Counts: -100, 100
51+
I (328) nvs_blob_example: Active: true
52+
I (328) nvs_blob_example:
53+
Reading array data blob:
54+
I (338) nvs_blob_example: Array[0] = 30
55+
I (338) nvs_blob_example: Array[1] = 20
56+
I (338) nvs_blob_example:
57+
Blob operations completed. Monitoring GPIO for reset...
58+
I (348) gpio: GPIO[0]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
59+
...
60+
```
61+
62+
To reset nvs data, erase the contents of flash memory using `idf.py erase-flash`, then upload the program again as described above.

examples/storage/nvs/nvs_rw_blob/main/nvs_blob_example_main.c

Lines changed: 131 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -19,62 +19,76 @@
1919
#include "freertos/FreeRTOS.h"
2020
#include "freertos/task.h"
2121
#include "esp_system.h"
22+
#include "esp_log.h"
2223
#include "nvs_flash.h"
2324
#include "nvs.h"
2425
#include "driver/gpio.h"
2526

2627
#define STORAGE_NAMESPACE "storage"
28+
#define BLOB_EXAMPLE_DATA_SIZE 256
29+
30+
static const char *TAG = "nvs_blob_example";
2731

2832
#if CONFIG_IDF_TARGET_ESP32C3
2933
#define BOOT_MODE_PIN GPIO_NUM_9
3034
#else
3135
#define BOOT_MODE_PIN GPIO_NUM_0
3236
#endif //CONFIG_IDF_TARGET_ESP32C3
3337

34-
/* Save the number of module restarts in NVS
35-
by first reading and then incrementing
36-
the number that has been saved previously.
37-
Return an error if anything goes wrong
38-
during this process.
39-
*/
40-
esp_err_t save_restart_counter(void)
38+
/* Test data structure to demonstrate different data types in blob */
39+
typedef struct {
40+
uint8_t id;
41+
char name[32];
42+
float values[2];
43+
uint32_t flags;
44+
int16_t counts[2];
45+
bool active;
46+
} test_data_t;
47+
48+
/* Save test data as a blob in NVS */
49+
esp_err_t save_test_data(void)
4150
{
4251
nvs_handle_t my_handle;
4352
esp_err_t err;
4453

45-
// Open
54+
// Create sample test data
55+
test_data_t test_data = {
56+
.id = 123,
57+
.name = "Test Sample",
58+
.values = {3.14f, 2.718f},
59+
.flags = 0xABCD1234,
60+
.counts = {-100, 100},
61+
.active = true
62+
};
63+
64+
// Open NVS handle
4665
err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);
47-
if (err != ESP_OK) return err;
48-
49-
// Read
50-
int32_t restart_counter = 0; // value will default to 0, if not set yet in NVS
51-
err = nvs_get_i32(my_handle, "restart_conter", &restart_counter);
52-
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;
66+
if (err != ESP_OK) {
67+
ESP_LOGE(TAG, "Error (%s) opening NVS handle!", esp_err_to_name(err));
68+
return err;
69+
}
5370

54-
// Write
55-
restart_counter++;
56-
err = nvs_set_i32(my_handle, "restart_conter", restart_counter);
57-
if (err != ESP_OK) return err;
71+
// Write blob
72+
ESP_LOGI(TAG, "Saving test data blob...");
73+
err = nvs_set_blob(my_handle, "test_data", &test_data, sizeof(test_data_t));
74+
if (err != ESP_OK) {
75+
ESP_LOGE(TAG, "Failed to write test data blob!");
76+
nvs_close(my_handle);
77+
return err;
78+
}
5879

59-
// Commit written value.
60-
// After setting any values, nvs_commit() must be called to ensure changes are written
61-
// to flash storage. Implementations may write to storage at other times,
62-
// but this is not guaranteed.
80+
// Commit
6381
err = nvs_commit(my_handle);
64-
if (err != ESP_OK) return err;
82+
if (err != ESP_OK) {
83+
ESP_LOGE(TAG, "Failed to commit data");
84+
}
6585

66-
// Close
6786
nvs_close(my_handle);
68-
return ESP_OK;
87+
return err;
6988
}
7089

71-
/* Save new run time value in NVS
72-
by first reading a table of previously saved values
73-
and then adding the new value at the end of the table.
74-
Return an error if anything goes wrong
75-
during this process.
76-
*/
77-
esp_err_t save_run_time(void)
90+
/* Example of storing and appending array data as a blob */
91+
esp_err_t save_array_data(void)
7892
{
7993
nvs_handle_t my_handle;
8094
esp_err_t err;
@@ -83,116 +97,137 @@ esp_err_t save_run_time(void)
8397
err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);
8498
if (err != ESP_OK) return err;
8599

86-
// Read the size of memory space required for blob
87-
size_t required_size = 0; // value will default to 0, if not set yet in NVS
88-
err = nvs_get_blob(my_handle, "run_time", NULL, &required_size);
89-
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;
100+
// First, get the size of existing data (if any)
101+
size_t required_size = 0;
102+
err = nvs_get_blob(my_handle, "array_data", NULL, &required_size);
103+
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
104+
ESP_LOGE(TAG, "Error (%s) reading array size!", esp_err_to_name(err));
105+
nvs_close(my_handle);
106+
return err;
107+
}
90108

91-
// Read previously saved blob if available
92-
uint32_t* run_time = malloc(required_size + sizeof(uint32_t));
109+
// Allocate memory and read existing data
110+
uint32_t* array_data = malloc(required_size + sizeof(uint32_t));
93111
if (required_size > 0) {
94-
err = nvs_get_blob(my_handle, "run_time", run_time, &required_size);
112+
err = nvs_get_blob(my_handle, "array_data", array_data, &required_size);
95113
if (err != ESP_OK) {
96-
free(run_time);
114+
ESP_LOGE(TAG, "Error (%s) reading array data!", esp_err_to_name(err));
115+
free(array_data);
116+
nvs_close(my_handle);
97117
return err;
98118
}
99119
}
100120

101-
// Write value including previously saved blob if available
121+
// Append new value
102122
required_size += sizeof(uint32_t);
103-
run_time[required_size / sizeof(uint32_t) - 1] = xTaskGetTickCount() * portTICK_PERIOD_MS;
104-
err = nvs_set_blob(my_handle, "run_time", run_time, required_size);
105-
free(run_time);
123+
array_data[required_size / sizeof(uint32_t) - 1] = xTaskGetTickCount() * portTICK_PERIOD_MS;
106124

107-
if (err != ESP_OK) return err;
125+
// Save updated array
126+
err = nvs_set_blob(my_handle, "array_data", array_data, required_size);
127+
if (err != ESP_OK) {
128+
ESP_LOGE(TAG, "Error (%s) saving array data!", esp_err_to_name(err));
129+
}
130+
131+
free(array_data);
108132

109133
// Commit
110134
err = nvs_commit(my_handle);
111-
if (err != ESP_OK) return err;
135+
if (err != ESP_OK) {
136+
ESP_LOGE(TAG, "Error (%s) committing data!", esp_err_to_name(err));
137+
}
112138

113-
// Close
114139
nvs_close(my_handle);
115-
return ESP_OK;
140+
return err;
116141
}
117142

118-
/* Read from NVS and print restart counter
119-
and the table with run times.
120-
Return an error if anything goes wrong
121-
during this process.
122-
*/
123-
esp_err_t print_what_saved(void)
143+
/* Read and display all saved blobs */
144+
esp_err_t read_stored_blobs(void)
124145
{
125146
nvs_handle_t my_handle;
126147
esp_err_t err;
127148

128-
// Open
129-
err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);
149+
err = nvs_open(STORAGE_NAMESPACE, NVS_READONLY, &my_handle);
130150
if (err != ESP_OK) return err;
131151

132-
// Read restart counter
133-
int32_t restart_counter = 0; // value will default to 0, if not set yet in NVS
134-
err = nvs_get_i32(my_handle, "restart_conter", &restart_counter);
135-
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;
136-
printf("Restart counter = %" PRIu32 "\n", restart_counter);
137-
138-
// Read run time blob
139-
size_t required_size = 0; // value will default to 0, if not set yet in NVS
140-
// obtain required memory space to store blob being read from NVS
141-
err = nvs_get_blob(my_handle, "run_time", NULL, &required_size);
142-
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;
143-
printf("Run time:\n");
144-
if (required_size == 0) {
145-
printf("Nothing saved yet!\n");
146-
} else {
147-
uint32_t* run_time = malloc(required_size);
148-
err = nvs_get_blob(my_handle, "run_time", run_time, &required_size);
149-
if (err != ESP_OK) {
150-
free(run_time);
151-
return err;
152-
}
153-
for (int i = 0; i < required_size / sizeof(uint32_t); i++) {
154-
printf("%d: %" PRIu32 "\n", i + 1, run_time[i]);
152+
// 1. Read test data blob
153+
ESP_LOGI(TAG, "Reading test data blob:");
154+
test_data_t test_data;
155+
size_t test_data_size = sizeof(test_data_t);
156+
err = nvs_get_blob(my_handle, "test_data", &test_data, &test_data_size);
157+
if (err == ESP_OK) {
158+
ESP_LOGI(TAG, "ID: %d", test_data.id);
159+
ESP_LOGI(TAG, "Name: %s", test_data.name);
160+
ESP_LOGI(TAG, "Values: %.3f, %.3f, %.3f, %.3f",
161+
test_data.values[0], test_data.values[1],
162+
test_data.values[2], test_data.values[3]);
163+
ESP_LOGI(TAG, "Flags: 0x%08" PRIX32, test_data.flags);
164+
ESP_LOGI(TAG, "Counts: %d, %d", test_data.counts[0], test_data.counts[1]);
165+
ESP_LOGI(TAG, "Active: %s", test_data.active ? "true" : "false");
166+
} else if (err == ESP_ERR_NVS_NOT_FOUND) {
167+
ESP_LOGW(TAG, "Test data not found!");
168+
}
169+
170+
// 2. Read array data blob
171+
ESP_LOGI(TAG, "\nReading array data blob:");
172+
size_t required_size = 0;
173+
err = nvs_get_blob(my_handle, "array_data", NULL, &required_size);
174+
if (err == ESP_OK) {
175+
uint32_t* array_data = malloc(required_size);
176+
err = nvs_get_blob(my_handle, "array_data", array_data, &required_size);
177+
if (err == ESP_OK) {
178+
for (int i = 0; i < required_size / sizeof(uint32_t); i++) {
179+
ESP_LOGI(TAG, "Array[%d] = %" PRIu32, i, array_data[i]);
180+
}
155181
}
156-
free(run_time);
182+
free(array_data);
183+
} else if (err == ESP_ERR_NVS_NOT_FOUND) {
184+
ESP_LOGW(TAG, "Array data not found!");
157185
}
158186

159-
// Close
160187
nvs_close(my_handle);
161188
return ESP_OK;
162189
}
163190

164-
165191
void app_main(void)
166192
{
193+
// Initialize NVS
167194
esp_err_t err = nvs_flash_init();
168195
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
169-
// NVS partition was truncated and needs to be erased
170-
// Retry nvs_flash_init
171196
ESP_ERROR_CHECK(nvs_flash_erase());
172197
err = nvs_flash_init();
173198
}
174-
ESP_ERROR_CHECK( err );
199+
ESP_ERROR_CHECK(err);
200+
201+
// Save new test data
202+
err = save_test_data();
203+
if (err != ESP_OK) {
204+
ESP_LOGE(TAG, "Error (%s) saving test data!", esp_err_to_name(err));
205+
}
206+
207+
// Save new array data
208+
err = save_array_data();
209+
if (err != ESP_OK) {
210+
ESP_LOGE(TAG, "Error (%s) saving array data!", esp_err_to_name(err));
211+
}
175212

176-
err = print_what_saved();
177-
if (err != ESP_OK) printf("Error (%s) reading data from NVS!\n", esp_err_to_name(err));
213+
// Read updated data
214+
ESP_LOGI(TAG, "\nReading updated blob data:");
215+
err = read_stored_blobs();
216+
if (err != ESP_OK) {
217+
ESP_LOGE(TAG, "Error (%s) reading updated data!", esp_err_to_name(err));
218+
}
178219

179-
err = save_restart_counter();
180-
if (err != ESP_OK) printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
220+
ESP_LOGI(TAG, "\nBlob operations completed. Monitoring GPIO for reset...");
181221

222+
// Setup GPIO for reset monitoring
182223
gpio_reset_pin(BOOT_MODE_PIN);
183224
gpio_set_direction(BOOT_MODE_PIN, GPIO_MODE_INPUT);
184225

185-
/* Read the status of GPIO0. If GPIO0 is LOW for longer than 1000 ms,
186-
then save module's run time and restart it
187-
*/
188226
while (1) {
189227
if (gpio_get_level(BOOT_MODE_PIN) == 0) {
190228
vTaskDelay(1000 / portTICK_PERIOD_MS);
191229
if(gpio_get_level(BOOT_MODE_PIN) == 0) {
192-
err = save_run_time();
193-
if (err != ESP_OK) printf("Error (%s) saving run time blob to NVS!\n", esp_err_to_name(err));
194-
printf("Restarting...\n");
195-
fflush(stdout);
230+
ESP_LOGI(TAG, "Reset button pressed, restarting...");
196231
esp_restart();
197232
}
198233
}

0 commit comments

Comments
 (0)