А расскажите, пожалуйста, подробнее про реализацию? Первая версия, насколько я помню, имела ограничение - ее нельзя было вызывать в таймере.
Чтобы вызвать из таймера, надо в таймерную процедуру входить по другому. Это вроде описал уже. Но не обязательно использовать ets_set_idle_cb, т.к. исходники ets_run даны и вставьте туда что угодно.
Текущая версия не имеет каких-либо доп. условий для использования? Не произойдет ли переполнения стека (рекурсии)?
Данное решение потребляет во много раз меньше стека, чем решение от igrr.
Верно ли я понимаю что здесь, по сути, происходит передача на итерацию исполнения основному циклу задач espressif? Сходу не совсем понял, был бы благодарен ссылке где можно почитать подробнее про ets_idle_cb, ets_idle_arg и т.д.
Так сразу и сходу описать всё сложно. ets_idle_cb, ets_idle_arg запускаются сразу после выполнения по приоритету всяких тасков и таймеров в ets_run() или когда нет никаких актуальных/сработавших тасков и таймеров. Но чтобы цикл ets_run крутился, требуется прерывание. В ets_run всё останавливается на команде отключения проца и ожидания прерывания. После прерывания проверяются таблицы тасков и таймеров и если ничего нет, то опять встает на ожидание прерывания (малое потребление, т.к. проц заглушен).
Из стандартной ets_run "выхода нет"
, кроме как через ets_idle_cb после прерывания и проверки на сработавшие таймеры и назначенные 'таски'. И всё возвращается опять в ets_run.
Исходная ets_run из ROM-BIOS. Она вызывается после начальной инициализации, в конце call_user_start() и далее все процессы (и SDK и пользовательские) работают только из неё. По этому, если вы не завершили процедуру таймера (не передали управление в ets_run()), следующие таски и таймеры обрабатываться не будут (и не будут переключены флаги отработанных процедур в таблицах). Будут работать только аппаратные прерывания - данный глюк и наблюдаем с методом переключением контекста в Arduino IDE.
/* idle_cb(idle_arg) вызывает ets_run()
idle_cb 0x3FFFDAB0, idle_arg 0x3FFFDAB4 */
void ets_set_idle_cb(void * routine, void *arg)
{ idle_cb = routine; idle_arg = arg; }
SDK не пользуется ets_set_idle_cb().
Так-же не забываем, чтобы цикл в ets_run() "прокрутился" требуется аппаратное прерывание к примеру таймера. Иначе всё стоит на:
asm volatile ("waiti 0;"); // Wait for Interrupt
c ets_intr_lock(); !
WDT кроме его прерывания в SDK завязано теперь с таймером и проверкой исполнения тасков SDK по таблице. Если за определенное время не отработались указанные в таблице китайцев post - то будет перезагрузка.
Т.е. ArduinoIDE на сегодня = неработающая система
, а решать как это исправить придется вам - я ей не пользуюсь.