0

Background: I know nothing about hardware.

I am writing a small project with Arduino IDE, ESP8266 library, and my board is ESP8266 V3 ESP-12N F NodeMcu Lua CP2102.

Now I get Exception 29 and I don't know why.

Sketch and server code(written in Python) github link (I also posted the client and server code at the bottom)


Module: [NodeMCU 1.0 (ESP-12E Module)]
Flash Size: [4MB]
lwip Variant: [v2 Lower Memory]
Flash Frequency: [40Mhz]
CPU Frequency: [80Mhz]
Upload Using: [SERIAL]
Upload Speed: [115200] 

Stack Dump:

Exception 29: StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores
PC: 0x4000e1c3
EXCVADDR: 0x00000018
Decoding stack results
0x40100908: malloc(size_t) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\umm_malloc\umm_malloc.cpp line 511
0x40100b6e: calloc(size_t, size_t) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\umm_malloc\umm_malloc.cpp line 826
0x40100b60: calloc(size_t, size_t) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\umm_malloc\umm_malloc.cpp line 820
0x4020318b: loop_task(ETSEvent*) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 188
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x402109ff: tcp_output at core/tcp_out.c line 1259
0x4020216a: ClientContext::wait_until_sent(int) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\libraries\ESP8266WiFi\src/include/ClientContext.h line 331
0x40100908: malloc(size_t) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\umm_malloc\umm_malloc.cpp line 511
0x402151c0: mem_malloc at core/mem.c line 210
0x4020f104: pbuf_alloc_LWIP2 at core/pbuf.c line 284
0x40214732: ip4_output_if at core/ipv4/ip4.c line 1550
0x4020fe90: tcp_write at core/tcp_out.c line 263
0x402031dc: __esp_yield() at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 100
0x4020378e: __delay(unsigned long) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_wiring.cpp line 54
0x4020230f: ClientContext::_write_from_source(DataSource*) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\libraries\ESP8266WiFi\src/include/ClientContext.h line 464
0x4020239d: WiFiClient::write(unsigned char const*, unsigned int) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\libraries\ESP8266WiFi\src/include/ClientContext.h line 364
0x40204c30: WiFiClient::write(unsigned char) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\libraries\ESP8266WiFi\src\WiFiClient.cpp line 217
0x40201bc4: DataSource::~DataSource() at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\libraries\ESP8266WiFi\src/include/DataSource.h line 12
0x402026c9: WiFiClient::flush(unsigned int) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\libraries\ESP8266WiFi\src\WiFiClient.cpp line 318
0x40201113: loop() at C:\Users\ptq00\Documents\Arduino\sketch_jan03b/sketch_jan03b.ino line 44
0x40100154: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x402032f4: loop_wrapper() at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp82662円.6.3\cores\esp8266\core_esp8266_main.cpp line 180

Sketch(Client) Code:

#include <ESP8266WiFi.h>
const char ssid[] = "luminous";
const char pass[] = "zxcv78()[]";
//Mac IP 192.168.1.101 
//PC IP 192.168.1.103
IPAddress server(192,168,0,103);
int port = 12700;
WiFiClient client;
void setup() {
 // put your setup code here, to run once:
 Serial.begin(115200);
 Serial.println("");
 WiFi.begin(ssid, pass);
 delay(500);
 while(WiFi.status() != WL_CONNECTED){
 delay(500);
 Serial.print(".../"); 
 }
 Serial.println("");
 //WiFi is connected
 if(client.connect(server, port)){
 Serial.println("connected to server");
 }
}
// 3s client read timeout. I set this value casually. The server has a 5s timeout when reading data from client.
const unsigned long clientTimeout = 3000; 
void loop() {
 // put your main code here, to run repeatedly:
 if(client.connected()){
 client.write(WiFi.RSSI());
 delay(100); // Add for nothing. Not sure if it's useful
 unsigned long timeout = millis();
 //Client timeout, if client can't reach the server, it should start to reconnect the server
 while(client.available() == 0){
 if (millis() - timeout >= clientTimeout){
 Serial.println(">>> Client Timetout !");
 client.stop();
 break;
 }
 }
 //Client is connected and has data to read
 //discard all data
 client.flush();
 }else{
 //Try to reconnect to the server
 client.connect(server,port);
 delay(500); // Add for nothing. Not sure if it's useful
 while(!client.connected()){
 //failed to reconnect
 Serial.println("Failed to reconnect...");
 delay(500);
 client.connect(server,port);
 }
 //succeed reconnecting
 Serial.println("Succeeded reconnecting..");
 }
}

Server Code:

import socket
HOST = '0.0.0.0'
PORT = 12700
catSafeZone = False
serverTimeout = 3
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1);
 s.bind((HOST, PORT))
 s.listen()
 print("Start listening")
 print("Device is not conncted")
 while True:
 conn, addr = s.accept()
 try:
 with conn:
 print("Connected by", addr)
 print("Cat is online")
 conn.settimeout(serverTimeout)
 # client won't try to disconnect on its own.
 # So we only need to capture connection timeout exception
 while True:
 data = conn.recv(128)
 if data:
 if catSafeZone == False:
 catSafeZone = True
 print("Cat is in safe zone.")
 conn.send(b'1')
 else:
 print("Unexpected condition")
 print("Client disconnected on its own.")
 raise Exception("server data NULL")
 # Code that is used for wifi signal strength detection:
 #
 # if not data:
 # break
 # wifiStrength = int.from_bytes(data, byteorder='big', signed=True)
 # print(wifiStrength)
 except socket.timeout:
 print("!!!Cat is out of safe zone")
 # Warn user in some ways
 catSafeArea = False
# never reach here
print("Server shutdown")
asked Jan 3, 2020 at 14:15
2
  • First: If you haven't already; please change your AP password, as you have included it in the code. Are your neighbors all friends? ;-) It seems as if the MCU tries to store data in a page where it is not allowed. But I confess, I see nothing in the code that could cause this behavior. Does it occur every time you run the code or is it a race condition? From the stack trace it seems as if the stack is used by multiple threads or interrupt routines. Perhaps two allocation accesses disturb each other. Because LUA is active that might also interfere with your code. Just guesses. Commented Jan 3, 2020 at 17:24
  • Ah, wait I've seen something: I add an answer because I use code to explain. Commented Jan 3, 2020 at 17:34

2 Answers 2

2

In your code there is a possibility that you stop the client and then flush it after. That could lead to the observed error.

// Client timeout, if client can't reach the server, 
// it should start to reconnect the server
while(client.available() == 0)
{
 if (millis() - timeout >= clientTimeout)
 {
 Serial.println(">>> Client Timetout !");
 client.stop(); // <----- HERE is the STOP !!!!!!
 break;
 }
}
//Client is connected and has data to read
//discard all data
client.flush(); <-- Then a flush on a stopped client !!!!!

I have no chance to try the following code, so use it as an example of what I would suggest you could try out. Attention: I've grayed out the last IP number and the SSID and the password.

#include <ESP8266WiFi.h>
const char ssid[] = "XXXXXXXXXXXXXXX";
const char pass[] = "XXXXXXXXXXXXXXX";
IPAddress server(192,168,0,XXX);
int port = 12700;
WiFiClient client;
void setup() 
{
 Serial.begin(115200);
 WiFi.begin(ssid, pass);
 delay(500);
 while(WiFi.status() != WL_CONNECTED)
 {
 delay(500);
 Serial.print(".../"); 
 }
 // New line after .../.../... 
 Serial.println("");
 if( client.connect(server, port) )
 {
 Serial.println("connected to server");
 }
}
// 3s client read timeout. I set this value casually. 
// The server has a 5s timeout when reading data from client.
const unsigned long clientTimeout = 3000; 
void loop() 
{
 while( ! client.connected() )
 {
 //failed to reconnect
 Serial.println("Failed to reconnect...");
 client.connect(server,port);
 delay(500);
 } 
 client.write(WiFi.RSSI());
 // Add for nothing. Not sure if it's useful
 // PPK: Me too ;-)
 delay(100); 
 unsigned long timemark = millis();
 // Client timeout, if client can't reach the server, 
 // it should start to reconnect the server
 while( client.available() == 0 )
 {
 if (millis() - timemark >= clientTimeout)
 {
 Serial.println(">>> Client timed out !");
 client.stop();
 break;
 }
 }
 if ( client.connected() && client.available() > 0 )
 {
 // remove bytes in the read buffer
 client.flush(); 
 } 
}
answered Jan 3, 2020 at 17:55
4
  • I still get Exception 29 error with your code Commented Jan 4, 2020 at 4:19
  • Thank you @Peter. I fixed the problem by checking the 8266 documentation and the source file shown in stack dump. And I use your code which is better than mine. :p Commented Jan 4, 2020 at 6:05
  • Oh. I also delete the whole client timeout procedure, which I think that while(client.connected()) has already done the work. Commented Jan 4, 2020 at 6:06
  • @Rick Your welcome. As I said, I could not try the code, I had just an idea ;-). I appreciate your answer. I confess I did not realize that you have to use read instead of flush. So I learned a bit more, thank you. I hope you check your answer as the accepted one when it is possible. Commented Jan 4, 2020 at 10:02
2

I fixed the problem. It turned out to be that the flush function in Arduino WiFi library has toally different meaning from the one that defined in ESP8266WiFi librarry.

From https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/client-class.html:

flush() returning true indicates that output data have effectively been sent, and false that a timeout has occurred.

This acts more like a flush stdout buffer in a typical C program.

Then I replaced client.flush() with:

 while(client.connected() && client.available() > 0){
 client.read();
 }

And everything works well then.


And I use your code with a little bit modification.

#include <ESP8266WiFi.h>
const char ssid[] = "luminous";
const char pass[] = "xxxxxxxx";
IPAddress server(192,168,0,101);
int port = 12700;
WiFiClient client;
void setup() {
 // put your setup code here, to run once:
 Serial.begin(115200);
 Serial.println("");
 WiFi.begin(ssid, pass);
 delay(500);
 while(WiFi.status() != WL_CONNECTED){
 delay(500);
 Serial.print(".../"); 
 }
 Serial.println("");
 //WiFi is connected
 if(client.connect(server, port)){
 Serial.println("connected to server");
 }else{
 Serial.println("Failed to connnect to server at setup().");
 }
}
int needToReconnect = 0;
void loop() {
 // put your main code here, to run repeatedly:
 while(!client.connected()){
 //failed to reconnect
 needToReconnect = 1;
 Serial.println("Failed to reconnect...");
 delay(500);
 client.connect(server,port);
 }
 // Use a flag to indicate if client was in reconnect procedure
 if(needToReconnect){
 Serial.println("Succeeded reconnecting...");
 needToReconnect = 0;
 }
 client.write(WiFi.RSSI());
 delay(100); // Add for nothing. Not sure if it's useful
 while(client.connected() && client.available() > 0){
 client.read();
 }
}
answered Jan 4, 2020 at 6:03

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.