espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.42k stars 7.37k forks source link

NVS involuntary resetting memory #9911

Open Samuel-Oliveira-BR opened 3 months ago

Samuel-Oliveira-BR commented 3 months ago

Board

ESP32-WROOM-32UE-N8

Device Description

Device is used for wifi comunicate (master) with other device by wifi (slave). The problem founded in the master.

Hardware Configuration

Input: IO32, IO33, IO34, IO35 Output: IO16 Using serial port

Version

v2.0.2

IDE Name

Arduino

Operating System

Windows 10

Flash frequency

80Mhz

PSRAM enabled

no

Upload speed

921600

Description

We have a serious problem now about the NVS memory partition using, Library preferences and the program developed on Arduino IDE (version 2.0.2). After turn off, delay around 10 minutes and turn on (around 43 times the procedure) the NVS data was deleted.

The NVS memory is used for save the wifi code for close the communication between the master and slave. When the NVS reset, the master lost the code.

Could you please help me to fix this big problem? Please, is urgent.

Ps: Library: https://docs.espressif.com/projects/arduino-esp32/en/latest/tutorials/preferences.html

Sketch

void configuracoesIniciais(){
  rtc_wdt_feed();
  if(!LittleFS.begin()){
    delay(2000);
    printSerial("SW403LTF|Error");
  }
  rtc_wdt_feed();
  configFabrica = preferences.getUChar("configFabrica", 170);

  if(configFabrica == 170){
   preferences.clear();
   preferences.putUChar("configurado", 170);
   preferences.putBool("desativaBlq", 0); //Desabilita a ação de bloqueio.
   preferences.putBool("verificaAE", 1);
   preferences.putBool("verificaJmm", 1);
   preferences.putBool("verificaSV", 1);
   preferences.putBool("desativaRtz", 0);
   preferences.putBool("rtzAtivada", 0);
   preferences.putUChar("erroDw", 0); //Erro de download.
   preferences.putUChar("funcaoSaida", 1);
   preferences.putUChar("alimentacaoBlq", 1);
   preferences.putUChar("numBloqueadores", 1);
   preferences.putUChar("fcAtivo", 0);
   preferences.putUChar("canal", 1); //Canal 1, padrão do Wifi.
   preferences.putUChar("modoBloqueio", 5);
   preferences.putUShort("tempoAtrasoJMM", 3); //3 minutos.
   preferences.putUShort("tempoAtrasoSV", 3);  //3 minutos.
   preferences.putUShort("tempoAtrasoFC", 5);  //5 minutos.
   preferences.putUShort("tempoAtrasoAE", 5); //5 segundos.
   preferences.putUShort("tempoAtrasoFR", 60); //60 segundos.
   preferences.putUShort("tempoDbqAuto", 0); //0 minutos, desativado.
   preferences.putUShort("tempoAtrasoBlq", 2); //2 minutos.
   preferences.putString("tag", "tag");
   preferences.putString("dns", "dns.sgbras.com:1000");
   preferences.putString("versao", Versao);
   preferences.putString("nomeRt", "/rt.bin");
   preferences.putString("nomeZn", "/zn.bin");
   preferences.putUChar("configFabrica", 0);
  }

  Chave.verificaAE = preferences.getBool("verificaAE", 0);
  Chave.verificaJmm = preferences.getBool("verificaJmm", 0);
  Chave.verificaSV = preferences.getBool("verificaSV", 0);
  Chave.funcaoSaida = preferences.getUChar("funcaoSaida", 1);
  Chave.alimentacaoBlq = preferences.getUChar("alimentacaoBlq", 1);
  Chave.configurado = preferences.getUChar("configurado", 0);
  numBloqueadores = preferences.getUChar("numBloqueadores", 0);
  tempoAtrasoJMM = preferences.getUShort("tempoAtrasoJMM", 3) * 60000;
  tempoAtrasoSV = preferences.getUShort("tempoAtrasoSV", 3) * 60000;
  tempoAtrasoFC = preferences.getUShort("tempoAtrasoFC", 5) * 60000;
  tempoAtrasoAE = preferences.getUShort("tempoAtrasoAE", 5) * 1000;
  tempoAtrasoFR = preferences.getUShort("tempoAtrasoFR", 60) * 1000;
  tempoDbqAuto = preferences.getUShort("tempoDbqAuto", 0) * 60000;
  tempoAtrasoBlq = preferences.getUShort("tempoAtrasoBlq", 2) * 60000;
  rtzAtivada = preferences.getBool("rtzAtivada", 0);
  desativaBlq = preferences.getBool("desativaBlq", 0);
  fcAtivo = preferences.getUChar("fcAtivo", 0);
  nomeRt = preferences.getString("nomeRt", "/rt.bin");
  nomeZn = preferences.getString("nomeZn", "/zn.bin");
  canal = preferences.getUChar("canal", 1);

  if(rtzAtivada) {
    desativaRtz();
    //ativaRtz();
  }
}

Debug Message

No debug problem detected

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

Samuel-Oliveira-BR commented 3 months ago

One time more in the field. But now without disconnect the device. The device just stopped to work and after turn off and turn on the NVS was cleared.

atanisoft commented 3 months ago

Are you being sure to call preferences.end() after you modify things to ensure it is stored/committed to flash?

Xylopyrographer commented 3 months ago

Couple of things:

All the getX() methods commit to NVS before returning so unless the device resets at that exact time they should be safe.

Samuel-Oliveira-BR commented 3 months ago

Are you being sure to call preferences.end() after you modify things to ensure it is stored/committed to flash?

Hi. Thank you about your comment. Yes. The end are in a function in the final.

Samuel-Oliveira-BR commented 3 months ago

Couple of things:

  • The code posted is only part of the overall sketch? There is not shown the .begin() nor the .end() statements.
  • The code uses, for example, preferences.getUChar("configFabrica", 170); which in this form will return the default value you specify of 170 if there is an error when doing the getX(). If the Preferences namespace it not properly initialized or opened with a .begin() then this may appear like the NVS has issues.

All the getX() methods commit to NVS before returning so unless the device resets at that exact time they should be safe.

Hi. Thanks about your comment. Yes is in the setup.

The problem heppening not in the first time when turn of the devie. The problem start after some hours the device on or when turn on and turn of several times.

me-no-dev commented 3 months ago

Any chance you can try with newer version? 2.0.17 or 3.0.1? 2.0.2 is really old (and all 2.0.x will be EOL next month).

Samuel-Oliveira-BR commented 3 months ago

Any chance you can try with newer version? 2.0.17 or 3.0.1? 2.0.2 is really old (and all 2.0.x will be EOL next month).

Samuel-Oliveira-BR commented 3 months ago

Any chance you can try with newer version? 2.0.17 or 3.0.1? 2.0.2 is really old (and all 2.0.x will be EOL next month).

Dear me-no-dev, sorry close your comment. The chat is new for me. But update the IDE is not the solution. I think the problem is with the hardware.

Samuel-Oliveira-BR commented 3 months ago

I think the problem of reset the NSV is from hardware. Do you know about some similar problem?

lbernstone commented 3 months ago

NVS is essentially a file system on the same flash as your firmware. So, if your firmware is being loaded, your hardware is working. If you think there might be interference on the device, you can lower the performance of the flash by setting it to DIO@40MHz. Flash memory does wear out if heavily used. If you are overwriting the contents of the NVS continuously, you may wear out those sectors (there are only 5x4K sectors in the default partition scheme). This will cause the NVS to be initialized fresh every time, and so your default settings will be pulled. The begin() and each of those put() entries returns a result. If you get a zero on any of them, the write to disk has failed.

Samuel-Oliveira-BR commented 3 months ago

NVS is essentially a file system on the same flash as your firmware. So, if your firmware is being loaded, your hardware is working. If you think there might be interference on the device, you can lower the performance of the flash by setting it to DIO@40MHz. Flash memory does wear out if heavily used. If you are overwriting the contents of the NVS continuously, you may wear out those sectors (there are only 5x4K sectors in the default partition scheme). This will cause the NVS to be initialized fresh every time, and so your default settings will be pulled. The begin() and each of those put() entries returns a result. If you get a zero on any of them, the write to disk has failed.

Hi. Let me explain to you how we using the NVS memory: The firmware is inserted just one time. But the wifi parameters, delay time, and some other configuration remotely. But not change all the time. The problem is: After turn on and turn off the device, the NVS delete but the firmware work normally.

lbernstone commented 3 months ago

Does the StartCounter example work on the device? Does the NVS fail only one time in every 43 boots? Your code has no error checking (neither does the example). You should check the result when you begin() the Preferences object.

TD-er commented 3 months ago

Does the NVS fail only one time in every 43 boots?

That's an awful specific number. Any known issue regarding that number?

Samuel-Oliveira-BR commented 3 months ago

Does the StartCounter example work on the device? Does the NVS fail only one time in every 43 boots? Your code has no error checking (neither does the example). You should check the result when you begin() the Preferences object.

Hi. Yes, the firmware compiled withou error. Thedevices is installed in more than 400 machines. The number 43 was one example. But, yes. the NVS memory erased 1 time in 43. Now we are simulatingin the lab and the momory erasing.

Yes, we are using the begin(). I sent to you just part of the program where we record in the nvs momory.

Samuel-Oliveira-BR commented 3 months ago

Does the NVS fail only one time in every 43 boots?

That's an awful specific number. Any known issue regarding that number?

No has exacly quantity. Yesterday fr example the device loked to work and reset the momory without turn off.

rrtandler commented 3 months ago

Hi @Samuel-Oliveira-BR, Could you please clarify following points:

  1. You have posted just the function configuracoesIniciais but you are also talking about "wifi parameters, delay time, and some other configuration". Could you post the code fragment showing how you initialise and work with that set of parameters ?
  2. You have stated, that sometimes the NVS preferences got lost "without turn off". How did you realise the moment, that preferences are cleared ?
  3. Plese provide list of all namespaces (the first parameter after .begin(...)) your program is using.
  4. In the post you are convinced the bug is in hardware rather than in library / it's use. Could you please try to deploy the example as suggested here and let us know the result ?

I'll try to give you some guidance, once the above gets more clear.

Samuel-Oliveira-BR commented 3 months ago

Hi @Samuel-Oliveira-BR, Could you please clarify following points:

  1. You have posted just the function configuracoesIniciais but you are also talking about "wifi parameters, delay time, and some other configuration". Could you post the code fragment showing how you initialise and work with that set of parameters ?
  2. You have stated, that sometimes the NVS preferences got lost "without turn off". How did you realise the moment, that preferences are cleared ?
  3. Plese provide list of all namespaces (the first parameter after .begin(...)) your program is using.
  4. In the post you are convinced the bug is in hardware rather than in library / it's use. Could you please try to deploy the example as suggested here and let us know the result ?

I'll try to give you some guidance, once the above gets more clear.

Hi @rrtandler, In accord of our test, the problem is during the of brown-out and the NVS not closing. Now we are creating a routine for generate a interruption for close the NVS and little when the brown-out is detected.

atanisoft commented 3 months ago

the problem is during the of brown-out and the NVS not closing.

In general, I'd recommend initialize/use/close the NVS interactions all in one area and store retrieved values in memory somewhere and not to leave the NVS open globally across the runtime.

You may also benefit from using the NVS blob storage approach which allows storage of a struct with data types embedded into it rather than loading/storing individual values.

rrtandler commented 3 months ago

@Samuel-Oliveira-BR From your answer, I am assuming, that you have some vital parameters (wifi password, for example) that are not changing frequently and another set of parameters like runtime parameters (velocity ...) that changes more often. You may consider using different NVS partitions for these 2 groups of data. The standard use of preferences.begin("some_namespace") uses the default NVS partition in the flash. For your frequently changing data, you can call preferences.begin("some_namespace", true, "mynvs") to specify custom NVS partition name (here called "mynvs"). In order to use custom NVS partition, you have to extend the partition table of your Arduino project. See documentation. For this particular example, you will have to add a row to the end of partition table. I.e. mynvs, data, nvs, , 20K, This approach splits the probability of full NVS erase as a result of brown-out data corruption to 2 independent groups based on data write frequency. The recommendation is to keep data not changing frequently in one group and the data changing more often in another.