I've written an example sketch which it's thought for both Arduino (with Ethernet shield) and ESP8266.
It compiles fine for both targets and executes fine on Arduino but on ESP8266 causes an Exception 9.
The sketch implements a simple server which waits to receive some messages via UDP and it should parse them properly writing in console if the message is an AckMessage, a NackMessage, a DataMessage or something else.
Once decoded the exception it seems that the method which causes the crash is the type() one of my class GenericMessage (its the parent one of the others and it's abstract).
That method is a getter which returns the type ID of the message (that is represented by an uint32_t attribute).
All attributes of the classes have been defined as uint32_t just to avoid some alignment problems but probably it isn't enough....
This is the exception decoded:
Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
PC: 0x4020514c: GenericMessage::type() at /home/ervito/Arduino/libraries/EasyMessages/utility/GenericMessage.cpp line 13
EXCVADDR: 0x3ffef91d
Decoding stack results
0x4020126e: loop() at /home/ervito/Arduino/EasyMessagesServer/EasyMessagesServer.ino line 114
0x4010017c: ets_post(uint8, ETSSignal, ETSParam) at /home/ervito/.arduino15/packages/esp8266/hardware/esp8266/2.7.2/cores/esp8266/core_esp8266_main.cpp line 177
0x40203634: loop_wrapper() at /home/ervito/.arduino15/packages/esp8266/hardware/esp8266/2.7.2/cores/esp8266/core_esp8266_main.cpp line 197
Ant this is my example sketch:
#include <EasyMessages.h>
/**/
#define ENABLE_WIFI /**/
/**
#define DEBUG_DISABLED /* Remember to disable debug with Arduino UNO. */
/* Put this define before include SerialDebug.h. */
#include <SerialDebug.h>
#ifdef ENABLE_WIFI
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
/* WIFI CONSTANTS DECLARATIONS */
const char *WIFI_SSID = "";
const char *WIFI_PWD = "";
/* WiFi-specific variables. */
WiFiUDP dataChannel;
#else
#include <Ethernet.h>
#include <EthernetUdp.h>
/* Ethernet-specific variables. */
byte macAddr[] = { 0x90, 0xA2, 0xDA, 0x0F, 0xAE, 0xF3 };
EthernetUDP dataChannel;
#endif
const uint16_t LOCAL_PORT = 12345;
const uint16_t TIMEOUT = 10000;
char message[DATA_MESSAGE_SIZE];
uint8_t receivedBytes;
void setup() {
Serial.begin(115200);
Serial.println("\n");
Serial.println("EasyMessages server example\n");
Serial.println("ID | Message | Size");
Serial.println("==========================");
printID(MessageTypeAck::instance()->id());
Serial.print(" | AckMessage | ");
Serial.println(ACK_MESSAGE_SIZE);
printID(MessageTypeData::instance()->id());
Serial.print(" | DataMessage | ");
Serial.println(DATA_MESSAGE_SIZE);
Serial.print(" - | GenericMessage | ");
Serial.println(GENERIC_MESSAGE_SIZE);
printID(MessageTypeNack::instance()->id());
Serial.print(" | NackMessage | ");
Serial.println(NACK_MESSAGE_SIZE);
Serial.println();
#ifdef ENABLE_WIFI
uint16_t notTimeout;
do {
notTimeout = TIMEOUT;
Serial.print("Connecting to wifi...");
WiFi.begin(WIFI_SSID, WIFI_PWD);
while (WiFi.status() != WL_CONNECTED && notTimeout) {
delay(500);
Serial.print(".");
notTimeout -= 500;
}
if (! notTimeout)
Serial.println("timeout.");
} while (! notTimeout);
#else
Serial.print("Initializing ethernet...");
if (Ethernet.begin(macAddr) == 0) {
Serial.println("failed.");
while(1);
}
#endif
Serial.println("done.");
Serial.print("Initializing channel...");
if (!dataChannel.begin(LOCAL_PORT)) {
Serial.println("failed.");
while(1);
}
Serial.println("done.");
Serial.print("IP: ");
#ifdef ENABLE_WIFI
Serial.println(WiFi.localIP());
#else
Serial.println(Ethernet.localIP());
#endif
debugSetLevel(DEBUG_LEVEL_INFO);
}
void loop() {
delay(500);
if ((uint8_t)dataChannel.parsePacket() >= GENERIC_MESSAGE_SIZE) {
dataChannel.read(message, GENERIC_MESSAGE_SIZE);
if (((GenericMessage*)message)->type() == MessageTypeAck::instance()->id())
Serial.println("Received ACK message");
if (((GenericMessage*)message)->type() == MessageTypeData::instance()->id()) {
while((uint8_t)dataChannel.available() < DATA_MESSAGE_SIZE-GENERIC_MESSAGE_SIZE);
for (; receivedBytes < DATA_MESSAGE_SIZE; receivedBytes++)
message[receivedBytes] = dataChannel.read();
Serial.println("Received data message");
}
if (((GenericMessage*)message)->type() == MessageTypeNack::instance()->id())
Serial.println("Received NACK message");
}
}
void printID(uint16_t id) {
if (id < 10)
Serial.print("0");
Serial.print(id);
}
I've already tested the type() method writing a sketch which instantiates some messages (both on the stack and on the heap) and invokes the method on the objects and it tries to cast a message* to a GenericMessage* and it executes fine.
Once done some tests I suppose that the problem is in the way that the received bytes are stored and then the cast to GenericMessage* breaks all but it's my guess....
Any help would be really appreciated.
Thank you in advance for your attention and collaboration.
Best regards
Marco