• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Скетч выкидывает исключение - как понять где?

SuperBoss

Member
Друзья,

Есть весьма замысловатый код, с некоторым количеством библиотек. Выдает иногда вот такое вот исключение с последующим ребутом устройства:

Reset reason: Hardware Watchdog
Reset info: Fatal exception:4 flag:1 (WDT) epc1:0x40000f68 epc2:0x00000000 epc3:0x40000f68 excvaddr:0x00000000 depc:0x00000000

Согласно перечню прерываний это вот это вот:
Level1InterruptCause
Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register

Прерывания в моем скетче есть в двух местах, но непонятно, почему они вызывают фатальное исключение.

Поможите советами :)

Использую Arduino IDE с загрузкой в WeMos D1 R2 по Wi-Fi.....
 

Юрий Ботов

Moderator
Команда форума
Это же ватчдог... он где угодно может исключение дать, он же по времени срабатывает. Выключите его (ESP.wdtDisable();) или время от времени "кормите" (ESP.wdtFeed();)
 

SuperBoss

Member
Это же ватчдог... он где угодно может исключение дать, он же по времени срабатывает. Выключите его (ESP.wdtDisable();) или время от времени "кормите" (ESP.wdtFeed();)
Да, это хардверный сторожевой пес. Но похоже, что срабатывает он не из-за недокорма. Хардверный срабатывает через 6 секунд, до него должен сработать софтверный на 3-й секунде.
Насколько я понимаю, wdtDisable отключает только программный контроль, а аппаратный неотключаемый.
 

nikolz

Well-known member
Не надо отключать. Делайте его рестарт особенно в циклах.
 

SuperBoss

Member
Не надо отключать. Делайте его рестарт особенно в циклах.
Если применяется чужая библиотека, то кормить псину в ней никак. Я столкнулся с такой проблемой с DHT.h. Там пришлось именно отключать программную псину, поскольку некоторые циклы иногда работают больше 3-х секундов.

Но тут проблема не в софтверном псе, а в хардверном псе, который явно указывает на какую-то проблему с прерыванием. Но что оно значит и как найти место ее вызывающее - непонятно.
 

nikolz

Well-known member
Если применяется чужая библиотека, то кормить псину в ней никак. Я столкнулся с такой проблемой с DHT.h. Там пришлось именно отключать программную псину, поскольку некоторые циклы иногда работают больше 3-х секундов.

Но тут проблема не в софтверном псе, а в хардверном псе, который явно указывает на какую-то проблему с прерыванием. Но что оно значит и как найти место ее вызывающее - непонятно.
А разве исходников нет?
 

nikolz

Well-known member
поставьте вывод времени исполнения операторов и посмотрите где вывалится.
 

SuperBoss

Member
Похоже, что находится ошибка вызывающая эксепшн связанный с прерыванием :)
Люди с этого форума уже сталкивались с подобной напастью.

Проблема складывается сразу из трех факторов:
1. Наличие delay в loop;
2. Использование внешнего прерывания;
3. Использование стандартного web-сервера.

Собственно все три фактора есть и в моем скетче. Думаю как обойти проблем-с.
 

SuperBoss

Member
Так, похоже, что симптом частично подтвердился. На Delay в loop никак не реагирует. А вот совместное использование <ESP8266WebServer.h>, возможно <WiFiClient.h> и любого вида прерывания приводит рано или поздно к глюку и вываливанию с прерыванием. Причем реагирует как на внешнее прерывание через AttachInterrupt, так и на присоединение к таймеру через Ticker.
Т.е. если в коде есть любое прерывание, даже если оно локализовано четко в одном участке когда (через Attach/Detach) и где-то крутится server.handleClient(), то через минут 15-40 приезжает эксепшн. Если плата подключена к USB то она тупо зависает, если стоит сама по себе то перезагружается.
Прямо какая-то интересная мистика.

PS. Похоже, что виноват все же не ВебСервер однака. Без него тоже выскочило, правда гонялся скетч часов 5 или 6.

PSS. Похоже, что виноват таки не вебсервер. Вообще, как оказалось, в esp8266 под Arduino есть существенный косяк, связанные с любыми прерываниями и любой коммуникацией через Wi-Fi.
Фишка в том, что коммуникации очень важны по времени и там есть неотключаемые прерывания. Что в общем-то норм. Но вот пользовательские прерывания страдают от этого, в результате любое пользовательское прерывание, вызванное во время любой коммуникации (а именно там прерывания и требуются) ведет к возникновению описанного выше исключения. Что-то там связано с тем, что обработчик прерывания, т.е. функция используемая для вызова при наступлении прерывания должна быть загружена в памяти. Видимо как-то там на тайминги завязано.
Лечится все это весьма просто:
1. Добавляем макрос ICACHE_RAM_ATTR в описание функции, например так void ICACHE_RAM_ATTR resolver() { наш код }
2. Прописываем функцию из пункта 1 выше того места, где происходит AttachInterrupt или attach объекта Ticker.

По-идее должно работать. Но я буду еще тестировать.

PSSS. Все равно вылетает :-\
 
Последнее редактирование:

SuperBoss

Member
Ха, вопрос так и не решился на самом деле. Проблема присутствует. Вылетает WDT Reset без предварительного программного пса. Прерывания тут не причем. Возможно стоит переработать скетч с нуля. И возможно, что проблема уйдет. Выкину некоторые библиотеки, посмотрю, как пойдет дальше.
По этому поводу есть не один крик о помощи, например вот 4 ways to eliminate ESP8266 resets
 

nikolz

Well-known member
Ха, вопрос так и не решился на самом деле. Проблема присутствует. Вылетает WDT Reset без предварительного программного пса. Прерывания тут не причем. Возможно стоит переработать скетч с нуля. И возможно, что проблема уйдет. Выкину некоторые библиотеки, посмотрю, как пойдет дальше.
По этому поводу есть не один крик о помощи, например вот 4 ways to eliminate ESP8266 resets
В документации есть такое предупреждение:
upload_2016-9-5_19-52-52.png
 

SuperBoss

Member
@nikolz
Ну, собственно RTOS нам пока не светит, поскольку пишем под Arduino. В обработчике прерываний ничего не пишу :) Памятью не двигаю.
Процессор стараюсь не загружать, тем более понавтыкал везде, где можно кормления пса. Но проблема в том, что он не срабатывает. Срабатывает сразу аппаратный. Вот, кроме капитального рефакторинга даже ничего на ум не приходит :)
 

SuperBoss

Member
Друзья,

Похоже, что таки нашел проблему. По всей видимости оно связано с подтвержденным багом Arduino esp8266 SDK. Проблема с интенсивным PWM и Wi-Fi коммуникацией. У меня гонялся fade встроенного светодиода - туда/сюда.

Во время рефакторинга код оптимизировал до состояния порядка 300 микросекунд на Loop. Теперь мне не очень понятно, стоит ли добавлять delay(xx) в loop или нет.

С одной стороны loop забивает циклы процессора nop-ами, в результате меньше гоняется логика, меньше нагрев и меньше потребление энергии. С другой стороны оно итак все холодное (+2 гр над внешней температурой).
 

nikolz

Well-known member
Друзья,

Похоже, что таки нашел проблему. По всей видимости оно связано с подтвержденным багом Arduino esp8266 SDK. Проблема с интенсивным PWM и Wi-Fi коммуникацией. У меня гонялся fade встроенного светодиода - туда/сюда.

Во время рефакторинга код оптимизировал до состояния порядка 300 микросекунд на Loop. Теперь мне не очень понятно, стоит ли добавлять delay(xx) в loop или нет.

С одной стороны loop забивает циклы процессора nop-ами, в результате меньше гоняется логика, меньше нагрев и меньше потребление энергии. С другой стороны оно итак все холодное (+2 гр над внешней температурой).
Пишите на Си (UDK) и без loop.
Будет все понятно и компактно.
 
Сверху Снизу