Код крашит ESP8266

sadman41
Offline
Зарегистрирован: 19.10.2016

Столкнулся со странной проблемой, при попытке перелицевать некоторый код с AVR на ESP8266, причину которой осознать не получается. Может сам дурак. Надеюсь на подсказку коллективного разума.

Что тут имеет значение - не знаю, напишу всё.

Итак, есть Wemos D1 (клон с Али), на нем припаян ESP8266MOD. Типа такого:

В Arduino IDE 1.8.9 подгружен фреймворк (Arduino Wiring-based Framework (ESP8266 Core)) для поддержки ESP8266, версия - 2.4.7. Ставил через настройки, как полагается: прописывал тудыть https://arduino.esp8266.com/stable/package_esp8266com_index.json и далее по инструкции.

Контроллером выбрал LOLIN(WEMOS) D1 Mini Lite, опции оставил в дефолте.

Загружаю скетч (небольшой, в большом вообще всё плохо - падает даже если просто в функции сделать присвоение аргументу, переданному по ссылке):

#pragma GCC optimize ("O0")

#pragma pack(push,1)
typedef struct {
  uint32_t justNumber;
} testStruct_t;
#pragma pack(pop)

void testFunc(const char* _str, uint32_t& _number) {
  char str1[] = "0x1234";
  //_number = 0x4321;
  _number = strtoul(str1, NULL, 0x00);
}


void setup() {
  const char src[] = "0x1234";
  uint32_t testLongUInt= 0x00;
  testStruct_t testStruct;

  Serial.begin(74880);
  Serial.println("\nESP8266 Struct test");

  //testFunc(src, testLongUInt); Serial.println(testLongUInt, HEX);
  testFunc(src, testStruct.justNumber); Serial.println(testStruct.justNumber, HEX);
}

void loop() {}

 ...и ESP начинает крашится/бутится по кругу с сообщением:

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Exception (9):
epc1=0x4020105e epc2=0x00000000 epc3=0x00000000 excvaddr=0x3fffff9b depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffdc0 end: 3fffffc0 offset: 0190
3fffff50:  40201144 3ffee314 3ffe8630 4020105a  
3fffff60:  32317830 00003433 3ffee314 4020136c  
3fffff70:  3fffff94 3fffff9b 3ffee314 40201390  
3fffff80:  feefeffe 00000000 3fffff90 402010ab <
3fffff90:  00000000 32317830 fe003433 feefeffe  
3fffffa0:  feefeffe feefeffe 3ffee37c 40201a4c  
3fffffb0:  feefeffe feefeffe 3ffe84e0 40100bd5  
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Что переводится как


Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
PC: 0x4020105e: testFunc(char const*, unsigned int&) at C:\Users\sadman\Documents\Arduino\ESP8266_struct/ESP8266_struct.ino line 12
EXCVADDR: 0x3fffff9b

Decoding stack results
0x40201144: HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\sadman\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/HardwareSerial.h line 164
0x4020105a: testFunc(char const*, unsigned int&) at C:\Users\sadman\Documents\Arduino\ESP8266_struct/ESP8266_struct.ino line 12
0x4020136c: Print::println() at C:\Users\sadman\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\Print.cpp line 186
0x40201390: Print::println(char const*) at C:\Users\sadman\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\Print.cpp line 198
0x402010ab: setup() at C:\Users\sadman\Documents\Arduino\ESP8266_struct/ESP8266_struct.ino line 25
0x40201a4c: loop_wrapper() at C:\Users\sadman\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\core_esp8266_main.cpp line 194

Методом научного тыка выяснил, что если совать в функцию не член структуры, а обычную переменную uint32_t - всё ОК. Коли убрать #pragma pack - тоже вроде помогает. Но, иногда, при перестановке строк кода или, например, добавлении в структуру нескольких членов, перестает крашится и без убирания pragma. Но не всегда. Системности, словом, я не заметил (например - чтобы структура была кратна 32 байтам или ещё как-то).  

Вопрос - чего я не так сделал? В коде что-то не так? При Сталине такого не бы... Т.е. на AVR я постоянного ребута или подвисания не наблюдал вовсе. 

rkit
Offline
Зарегистрирован: 23.11.2016

Ну ты написал #pragma pack(push,1) зачем-то. В этом твоя ошибка

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Далеко не все машинные команды позволяют писать (читать) куда (откуда) попало. Некоторые требуют обязательного выравнивания аргумента по некоторой границе. Не знаю, что там за команды у ESP, но сообщение

Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address

навевает на мысль, что здесь именно такой случай.

sadman41
Offline
Зарегистрирован: 19.10.2016

Про выравнивание я тоже покопал сначала, но меня смутила неуправляемость ситуации с отключенной (теоретически) оптимизацией. Запихиваешь в структуру под pack ещё одну байтовую переменную (итого 5 байт) - не крашится. Добавишь ещё кода в другое место- крашится.

Сейчас упаковку снял - и в большом коде всё вроде нормализовалось.

Но некоторая проблема осталось - для передачи в другую систему мне как-то хочется дырки в структуре убрать. Между одинаковыми архитектурами передам, конечно, но как с 32-битной ESP на 8-битный AVR и обратно погнать данные. Раньше всё просто делал - указатель на структуру к uint8_t привёл, размерность указал и write() это дело, а на другой стороне - read() в такой же указатель. А тут ESP дырок от бублика напихает AVR-ке...

Что делать?  

rkit
Offline
Зарегистрирован: 23.11.2016

Написать нормальную сериализацию.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Что делать?  

Если не сходить с ума на тему "ой, а тут лишний байт передаётся", то можно поставить выравнивание структуры не на байт, а на границу слова - оно везде будет так выравниваться и можно передавать так же, как и сейчас.