我正在尝试为我的ESP32项目创建一个保存系统,我有以下代码:
void write_string_nvs(char *memorySlot, String key, String value)
{
nvs_handle my_handle;
esp_err_t err = nvs_open(memorySlot, NVS_READWRITE, &my_handle);
if (err == ESP_OK)
{
int kL = key.length();
int vL = value.length();
char keyA[kL + 1];
key.toCharArray(keyA, kL + 1);
char valueA[vL + 1];
value.toCharArray(valueA, vL + 1);
Serial.println("Storing \"" + String(keyA) + "\"(" + String(kL) + ")>\"" + String(valueA) + "\"(" + String(vL) + ") in NVS.");
esp_err_t err = nvs_set_blob(my_handle, keyA, &valueA, vL);
if (err == ESP_OK)
{
err = nvs_commit(my_handle);
if (err == ESP_OK)
Serial.println("Correctly saved \"" + key + "\" in " + String(memorySlot));
else
Serial.println("write_string_nvs::commit -> Could not save \"" + key + "\" in " + String(memorySlot) + ": " + esp_err_toString(err, true));
}
else
Serial.println("write_string_nvs::nvs_set_blob -> Could not save \"" + key + "\" in " + String(memorySlot) + ": " + esp_err_toString(err, true) + "");
nvs_close(my_handle);
}
else
Serial.println("Could not initialize " + String(memorySlot) + " NVS slot: " + esp_err_toString(err, true) + "");
}我从一个串行命令中以如下方式调用它:
...
String params[3];
split(serialRead, ' ', params);
String s = params[0];
String k = params[1];
String v = params[2];
bool error = false;
if (s.length() <= 0) {
error = true;
Serial.println("Please, specify an storage name");
}
if (k.length() <= 0) {
error = true;
Serial.println("Please, specify a key");
}
if (v.length() <= 0) {
error = true;
Serial.println("Please, specify a value");
}
if (!error) {
String slotName = "";
if (startsWithIgnoreCase(s, "main")) {
slotName = "storage";
}
if (startsWithIgnoreCase(s, "wifi")) {
slotName = "wifi";
}
if (slotName.length() > 1) {
Serial.println("Writing \"" + v + "\"" + " at \"\"" + k + "\" in " + slotName);
char slot[slotName.length()];
slotName.toCharArray(slot, slotName.length());
write_string_nvs(slot, k, v);
} else
Serial.println("Specified invalid slot");
}通过这样做,我试图创建一个命令解析器来存储值,然后使用以下命令读取它们:storage write <wifi/main> <key> <value>和storage read <wifi/main> <key>。
但是当我尝试输入write命令时,问题出现了,代码执行时,ESP32串行返回:
assertion "heap != NULL && "realloc() pointer is outside heap areas"" failed: file "/Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/heap/heap_caps.c", line 285, function: heap_caps_realloc
abort() was called at PC 0x40152903 on core 1
Backtrace: 0x40091ca4:0x3ffce0c0 0x40091ed5:0x3ffce0e0 0x40152903:0x3ffce100 0x400847a9:0x3ffce130 0x4008483d:0x3ffce150 0x4008b2e9:0x3ffce170 0x4000bedd:0x3ffce190 0x400dd4e2:0x3ffce1b0 0x400dd544:0x3ffce1d0 0x400dd6a6:0x3ffce1f0 0x400dd6d1:0x3ffce210 0x400d1b06:0x3ffce240 0x400d5939:0x3ffce260 0x400de489:0x3ffce7d0 0x40094135:0x3ffce7f0
Rebooting...我不知道该怎么做,我已经尝试了一些不同的写和读代码,但我找不到任何正确存储值的代码。read命令可以工作,但很明显,它不会返回任何内容,因为内存是空的。下面是read命令,如果你想看看它的话:
String read_string_nvs(char *memorySlot, String key)
{
nvs_handle my_handle;
esp_err_t err = nvs_open(memorySlot, NVS_READWRITE, &my_handle);
String espErrStr = esp_err_toString(err, true);
char *value;
if (err == ESP_OK || startsWithIgnoreCase(espErrStr, "ESP_OK"))
{
size_t string_size;
int kL = key.length();
char wifi_slot[kL + 1];
key.toCharArray(wifi_slot, kL + 1);
esp_err_t err = nvs_get_str(my_handle, wifi_slot, NULL, &string_size);
value = (char *)malloc(string_size);
err = nvs_get_str(my_handle, wifi_slot, value, &string_size);
nvs_close(my_handle);
return String(value);
}
else
Serial.println("Could not open memory (\"" + espErrStr + "\")");
return espErrStr;
}我已经处理这个问题有几个星期了,我真的不知道该怎么办,也许系统对我想要的东西不好,或者我做错了什么。
为了进行开发,我使用带有PlatformIO的VSCode。
请看一看,如果你能告诉我哪里出了问题,或者该怎么办,我会很高兴的。
提前谢谢。
发布于 2019-04-05 18:12:00
我正忙于解决同样的问题(我将使用4Mb的闪存作为nvs分区),并且我找到了一些线索:
看起来问题出在RAM大小上--系统需要一个RAM来创建nvs-pages-map,如果它不足以完成这个任务,它就会调用系统中止。
附注:我用地址和汇编程序代码将我的firmware.elf解码成firmware.lst,回溯是这样的:
->ZN3nvs_Storage_populateBlobIndicesIntrusiveList -> initArduino -> nvs_flash_init -> nvs_flash_init_partition -> nvs_flash_init_custom -> ZN3nvs_storage_init_Ejj -> _Znwj -> _cxa_allocate_exception -> terminatev -> cxabiv111_terminateEPFvvE -此处系统中止
要将工具链解码为xtensa-esp32-elf-objdump.exe -只需将工具链复制到包含.elf的文件夹(可能在.platformio\ .lst \ firmware.elf \.lst-xtensa32\ firmware.elf中),然后在命令提示符- xtensa-esp32-elf-objdump.exe -S -l -d firmware.elf> YourFileName.lst中运行
发布于 2019-03-26 23:37:08
这些代码行有问题:
char slot[slotName.length()];
slotName.toCharArray(slot, slotName.length());
write_string_nvs(slot, k, v);slotName.length()将返回slotName中的字符数。slot是一个C字符串,它的末尾需要一个空的终止字符(\0),因此需要用比字符串中的字符数多一个字节来声明它。您的声明太短。
您可以通过重写以下代码行来回避这个问题:
write_string_nvs(slotName.c_str(), k, v);String已经在内部将其内容存储为C字符串,因此c_str()方法只为您提供了一个指向它管理的缓冲区的指针。注意这一点,在String对象变为无效之后,该指针将不再有效,因此如果String是函数或代码块中的变量,则当您离开该函数或代码块时,其c_str()将停止有效。
由于这是某种堆或内存分配问题,所以bug可能在您共享的代码之外。我会检查所有代码,查找将String转换为C字符数组的实例,并尝试使用c_str()习惯用法。
这是一个让很多程序员头疼的常见问题。
也有可能问题出在您的write_string_nvs()实现中。
https://stackoverflow.com/questions/55359865
复制相似问题