-
Notifications
You must be signed in to change notification settings - Fork 13.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WiFi config corrupted after multiple restarts #1054
Comments
the Soft WDT was triggert that mean you have some while / for loop in you code what take to much time without calling delay. |
Thanks for your reply. I don't think that is the case since the code runs fine for a few days and then doesnt work anymore. My code:
The module gets stuck in the connectAp() function (actually, in any other Wifi function that is called, but this happens to be the first one in this code):
|
Does it behave any better if you take that "web.connectAp();" line out of loop() and instead just do it once at the end of setup() ? I have similar code here, but not using "web" objects or deepsleep. |
I tried that, it didnt work :/ So, this is the "timeline" to summarize what the problem is and when it appears
It seems like the MCU is alright, but when I call any Wifi function the code gets stuck in some sort of loop and the wdt resets the MCU. I have a few ideas of what is causing the problem, but I am not sure how to investigate them:
Thanks for your help |
Could you please upload your sketch and .elf output file so I can analyse the stack trace for you? |
You can download the files from: https://www.dropbox.com/s/sqv405zq991ei6k/firmware_v1_github.zip?dl=0 the serial output for this code is:
Let me know if you need anything else. I really appreaciate the help :) |
So, each time this happens, your module is essentially "bricked" w.r.t. Wifi.. no future sketches will work if they use WiFi (as best you can tell)? So some persistent state is being changed after a while. Either a microseconds counter is overflowing in permanent storage, or a log file or DHCP lease file (or similar) is getting corrupted or running out of space. Persistent state can be stored in EEPROM, and there are example sketches to examine/modify EEPROM storage. It can also be stored on the flash file system, in the 3M partition as well as the 1M partition. And the RTC has a tiny bit of storage too. Without knowing much about this specific platform (only just started using it three weeks ago), those are areas I would consider poking around at, especially the flash file system. |
Interesting, I will take a look at these EEPROM scketches. Another useful information: At some point, I was trying to "unbrick" the module and decided to upload the nodeMCU firmware (https://github.com/nodemcu/nodemcu-firmware) and give it a try. Interesting fact is that with the LUA-based firmware, the same "bricked" module worked fine when I tried to connect to a Wifi AP, with no reboots. When I switched back to this arduino-based firmware, the problem came back. I guess that possibly relates to what you are saying about the memory partitions. Perhaps the LUA firmware was not using some corrupted part of memory that was being used by the arduino code. food for thought... |
Looking at the stack trace, WDT reset happens inside SDK functions. Call chain looks like this:
This is in line with your observation that some persistent corruption happens to the module configuration. |
I see that on each power up you do WiFi.mode(WIFI_STA);
WiFi.begin(id, pass); Each time this is done, SDK writes these settings to flash memory. Depending on you wakeup frequency, this might result in some wear to these sectors of flash memory. I will add some additional checks which will bypass SDK functions in case SSID/psk match the ones already present in Flash. This will reduce the number of flash writes (i.e. it will only be written when SSID/psk actually change). |
I wonder why the code feels that it is necessary to write those parameters to flash at all? Thanks |
This is Espressif SDK functionality — it stores WiFi configuration parameters to flash each time these parameters change. There is no API in the SDK to disable this feature. |
So, if I remove these two functions and let the module connect to the Wifi AP using the ssid and password stored in flash the problem will be solved? |
I'm the developer of the ESP Easy sensor project (www.esp8266.nu) and users can also enable deepsleep on the webgui. My sketch also stores it's own wifi config version and sets this at boot time. So if this is true, we will soon face similar "brick" issues. I think I have to warn about this on our forum. But on the other hand, if we would compare things with AVR, where the guaranteed EEPROM write cycles are at least 100.000, writing a config every minute (so 1440/day) would still work for 100.000/1440 = 69 days before EEPROM starts to wear out. Am I right? Or is the write cycle life time for these flash chips on ESP a lot lower? |
Flash memory is external to the ESP8266, and ESP-xx module vendor(s) may use different ICs. I have a few modules which started showing flash-related issues after about 100 flash operations. This may very well be due to low quality/defective ICs used. So the actual mileage will vary. I will push the fix today. Need to do a few more tests. |
I guess the same applies for these commands which are used in our sketch at boot time: |
Setting mode after calling |
I think that flash cell wear should be protected at the lowest level possible. I'm also using sector writes to flash, but maybe I need change the routine to check if the 4k block is actually changed for at least one byte before it's written back to flash. Of course it would be nice it this is already protected at the core level or sdk level. Maybe we need to check this and write wrappers around all flash related stuff to protect the chip. Risk that a sketch runs into a loop writing same data to the same cell in a high frequency is just to high! So using this stuff could be dangerous: if(spi_flash_erase_sector(_sector) == SPI_FLASH_RESULT_OK) I guess I should be safe it it's done like this: // 'newdata' comes as parameter... uint8_t* data = new uint8_t[FLASH_EEPROM_SIZE]; boolean changed = false; if (changed) But this also consumes some extra MCU processing time... |
Doing this kind of check by default is a pessimization which will become a major performance hit for, e.g., SPIFFS, which does wear levelling internally. If you want wear levelling, you might just use SPIFFS instead of raw flash interface for your application. |
I'm aware of the performance loss. We started to "avoid" using spiffs because of it's costs in terms of program size and RAM usage. We only needed a single 32k block to store all configuration structs and that's why I decided to use some small dedicated functions. Currently without 'wear leveling' but that would be impossible if you only want to use 32k in total (has to work on 512k ESP models) Using the EEPROM library (emulated in flash) actually has the same risk that probably most users are unaware off. It they mistakenly update the same data to eeprom in a loop (or due to a bug) the cell would soon be worn out and fail. Of course we would still have no protection if a bug results into writing different data to the same cell in a loop... |
This is what I use. Its a function that first tries to use stored credentials, so if the ESP has connected before it uses those (nothing is written to flash), then if that fails it tries to use hard coded credentials, then if that fails it creates an AP. From following this thread, if u've connected to the SSID before, it should just reconnect without writing anything. What i've not implemented is a comparison function between what is stored and what is hard coded. should be possible though.
|
I was looking through the SDK docs and found that we now do have a way to set WiFi configurations without writing anything to flash ( Perhaps adding some parameter new parameter (i.e. |
I don't expect it to be a common thing for sketches to change their hardcoded SSID/passwd etc.. Or at least not any of my own sketches. So limiting the damage by getting rid of unnecessary calls to wifi_station_set_config() is good enough for me. But exposing more of the SDK is probably also a Good Thing. --- esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp.orig 2015-11-21 10:00:46.860166073 -0500
+++ esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp 2015-11-21 10:01:05.988228854 -0500
@@ -132,7 +132,13 @@
}
ETS_UART_INTR_DISABLE();
- wifi_station_set_config(&conf);
+ struct station_config old;
+ wifi_station_get_config(&old);
+ if (old.bssid_set != conf.bssid_set
+ || (old.bssid_set && memcmp(old.bssid, conf.bssid, 6))
+ || strcmp((char *)(old.ssid), (char *)(conf.ssid))
+ || strcmp((char *)(old.password), (char *)(conf.password)))
+ wifi_station_set_config(&conf);
wifi_station_connect();
ETS_UART_INTR_ENABLE(); |
I think the problem is in ESP8266WiFiClass::softAP at:
softap_config_equal returns true if conf and conf_current are the same. So, I guess it should be:
|
@rafaelmendes thanks for spotting this. Fixed in 6be74ec. |
On a related note, the ESP no refuses to change away from any custom name. I loaded the example WifiAccessPoint, and now every subsequent AP has the name "ESPap", regardless of what I set. In other news, computers and cellphones now refuse to connect to the device... |
Are you using the latest git version? After 6be74ec the problem I was having with the AP id was fixed. |
I hand-modified the fix that was mentioned (removing the !) and now seem to get the opposite problem.... Will try a full git pull. |
This is probably a separate issue. I am having great difficulty connecting to the network with any laptop I have. Even the cellphone goes through a few cycles of connecting-disconnecting-connecting. Power supply to the ESP module has 22uF caps, and is rated for 600mA, so no issue there. Distance is about 20 cms. |
@ibaranov-cp : I have a similar issue than you with my laptop. Strangely with other laptops of my co-workers and every smarphone I tried it works just fine. 100µF and laboratory supply and old firmware (like 2 months old) works. |
Please note that the AP ID issue is still present in the staging version. |
(1) I am assuming the the "WiFi.persistent(false)" setting is NOT retained during "ESP.deepSleep", so needs to be re-issued after every wake-from-deepSleep. Is this correct? (2) I am also assuming the "WiFi.persistent(false)" setting ONLY affects what happens for the calls to "WiFi.begin(ssid,pw)" and "WiFi.softAP(ssid,pw)". Is this correct? – Update: also used by “WiFi.mode(..)” and other commands – see below! (3) If (2) is correct, then I am assuming that "WiFi.persistent(false)" ONLY needs to be issued before a "WiFi.begin(ssid,pw)" or "WiFi.softAP(ssid,pw)". IE. if not using either of these commands during a wake-period, then it is NOT necessary to re-issue the WiFi.persistent(false)" after wake from "ESP.deepSleep". Is this correct? – Update: Partially INCORRECT – see below! (4) I am finally assuming that it does not matter if the "WiFi.persistent(false)" is issued either before or after the "WiFi.forceSleepWake()" or "WiFi.mode(WIFI_STA)" commands, as neither of these commands are affected by it. Is this correct? – Update: Partially INCORRECT – see below! If any of the above assumptions are incorrect, any clarification would be appreciated! |
Waking-up from DeepSleep is equivalent to reset. Anything about .persistent can be found inside ESP8266WiFiGeneric.cpp in ESP8266WiFiGenericClass so you can take a look... |
Pablo2048 – many thanks for the pointer! I must start by stressing that I am no expert in interpreting these .cpp files, but these files seem to say that the [persistent] setting is used to decide if to save stuff in flash by the following processes: (1) From [ESP8266WiFiGeneric.cpp]:
(2) From [ESP8266WiFiAP.cpp]:
(3) From [ESP8266WiFiAP.cpp]:
(A) Thus is would seem necessary to set “WiFi.persistent(false)” after every DeepSleep wake, BEFORE any of the “WiFi.mode” or “WiFi.begin” or “WiFi.softAP” or disconnect commands. (But I note that neither “WiFi.forceSleepBegin()” and “WiFi.forceSleepWake()” seem to use the [persistent] setting.) (B) As “forceSleepBegin” does not do anything if [!mode(WIFI_OFF)], the “WiFi.forceSleepBegin();delay(1);” commands needs to be after “WiFi.mode(WIFI_OFF)” (C) I note that “forceSleepWake” first does a “Wake ESP8266 up from MODEM_SLEEP_T force sleep”, and then uses the [WIFI_STA] and [_forceSleepLastMode] variables to decide if to do a “wifi_station_connect”. However as neither of these 2 variables are likely to have been retained after a DeepSleep, it would appear not to matter if the “WiFi.forceSleepWake()” command is before or after the “WiFi.mode(WIFI_STA)” command. But I note that most users seem to issue it BEFORE the “WiFi.mode(WIFI_STA)” command, so it is possible that “WiFi.forceSleepWake();delay(1);” is better to put first (perhaps because this ensures it does NOT try a “wifi_station_connect”)!? (D) I also note that the [persistent] setting is used to save variables into flash by both “(STA)disconnect” and “softAPdisconnect”. This appears to be because the data saved (being of [struct station_config]) includes the [bssid] (aka MAC address of the WiFi-router), which might not have been available when the initial SSID/PW data was saved in “WiFi.begin(..)”. [Interestingly, this would seem to suggest that if you are (manually) connecting & disconnecting from APs frequently, and didn't need the [bssid] saving, you could still save the [ssid/pw] but reduce [flash-save usage] by ~50% just by issuing a "WiFi.persistent(false)” before the “WiFi.disconnect()” command - although in these instances it would probably not even be necessary to save the [ssid/pw] either...!?] (E) Finally, I note that the ESP8266 does retain some data through a DeepSleep or Reset (eg. the RTC-Memory, and data sufficient for it to identify what the reset-reason was after a Reset/Wake (ie. using “system_get_rst_info”).) However, as it seems most users re-set “WiFi.persistent(false)” after waking from a DeepSleep, this would suggest that the [persistent] setting is NOT retained during DeepSleep (or a Reset). So, in summary, best option if using DeepSleep seems to be issuing “WiFi.persistent(false)” at top of [setup()], as there is no penalty for doing this here. And then if necessary/required, issuing a “WiFi.persistent(true)” just before any "WiFi.begin(..)" or "WiFi.softAP(..)" commands (and a “WiFi.persistent(false)” after them if you dont want any subsequent “WiFi.disconnect()” commands to save data into flash)!? If any of the above deductions are incorrect, clarification would be appreciated! |
I've installed the git version (following the instructions) as pointed out in several duplicate issues, but I still see the wrong SSID. It should be I'm using an ESP8266-12E board with an integrated 128x32 OLED display What am I doing wrong?
Thank you |
Probably bad credentials? See https://www.quora.com/Why-does-WiFi-password-should-have-minimum-of-only-8-characters |
That was the problem @Pablo2048 : now it's all working |
So just to be clear after so many posts - does WiFi.begin("network-name", "pass-to-network") overwrites the FLASH if the settings are the same with what's on the FLASH or not if "persistent" is true ? |
Hi guys,
I am using an ESP12E to read a temperature sensor every minute and post the data to a webserver. The module reads the data from the sensor, post it and go into deepsleep for 60 seconds. My code works fine for some time (for some modules days, for other it takes weeks) but then the module starts to reset itself with no apparent reason. The weird part is that the MCU still works fine after that: if I upload a new code with no Wifi function (like blink led) the module works alright. However, if I use ANY Wifi function, the code runs up to the point where the function is called and then the module reboots, printing the following message:
The same problem happened to five modules now. I am not sure if it is a hardware problem or a bug in my firmware.
I've been facing this problem for almost 2 months now. I first thought that there was some sort of memory leak causing it so I started to print the free heap available every time the module woke up from deepsleep. Even after the module was "bricked", the heap was still ok.
I ve got no ideas left to solve it, any help will be appreciated.
Thanks,
Rafael
The text was updated successfully, but these errors were encountered: