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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.6.3\libraries\ESP8266WiFi\src/include/ClientContext.h line 331
0x40100908: malloc(size_t) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.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\esp8266\2.6.3\cores\esp8266\core_esp8266_main.cpp line 100
0x4020378e: __delay(unsigned long) at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.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\esp8266\2.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\esp8266\2.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\esp8266\2.6.3\libraries\ESP8266WiFi\src\WiFiClient.cpp line 217
0x40201bc4: DataSource::~DataSource() at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.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\esp8266\2.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\esp8266\2.6.3\cores\esp8266\core_esp8266_main.cpp line 160
0x402032f4: loop_wrapper() at C:\Users\ptq00\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.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")
  • 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. – Peter Paul Kiefer Jan 3 at 17:24
  • Ah, wait I've seen something: I add an answer because I use code to explain. – Peter Paul Kiefer Jan 3 at 17:34
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();  
  }   
}
  • I still get Exception 29 error with your code – Rick Jan 4 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 – Rick Jan 4 at 6:05
  • Oh. I also delete the whole client timeout procedure, which I think that while(client.connected()) has already done the work. – Rick Jan 4 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. – Peter Paul Kiefer Jan 4 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();
  }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.