Официальный сайт компании Arduino по адресу arduino.cc
Код крашит ESP8266
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Столкнулся со странной проблемой, при попытке перелицевать некоторый код с 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 я постоянного ребута или подвисания не наблюдал вовсе.
Ну ты написал
#pragma pack(push,1)
зачем-то. В этом твоя ошибкаДалеко не все машинные команды позволяют писать (читать) куда (откуда) попало. Некоторые требуют обязательного выравнивания аргумента по некоторой границе. Не знаю, что там за команды у ESP, но сообщение
Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
навевает на мысль, что здесь именно такой случай.
Про выравнивание я тоже покопал сначала, но меня смутила неуправляемость ситуации с отключенной (теоретически) оптимизацией. Запихиваешь в структуру под pack ещё одну байтовую переменную (итого 5 байт) - не крашится. Добавишь ещё кода в другое место- крашится.
Сейчас упаковку снял - и в большом коде всё вроде нормализовалось.
Но некоторая проблема осталось - для передачи в другую систему мне как-то хочется дырки в структуре убрать. Между одинаковыми архитектурами передам, конечно, но как с 32-битной ESP на 8-битный AVR и обратно погнать данные. Раньше всё просто делал - указатель на структуру к uint8_t привёл, размерность указал и write() это дело, а на другой стороне - read() в такой же указатель. А тут ESP дырок от бублика напихает AVR-ке...
Что делать?
Написать нормальную сериализацию.
Что делать?
Если не сходить с ума на тему "ой, а тут лишний байт передаётся", то можно поставить выравнивание структуры не на байт, а на границу слова - оно везде будет так выравниваться и можно передавать так же, как и сейчас.