Комментарии 47
Начиная с определенной сложности задачи, использование легковесных ОС вроде FreeRTOS оправдано и активно применяется в Embedded разработке. И даже на более слабых контроллерах, а ESP8266 обладает довольно внушительными ресурсами (существенно превышает "народные" ATMega или STM32F1xx). Правда с памятью там проблемы были, вроде как.
А задача работы WiFi и IP стеком уже весьма серьезная. Так аналог ESP8266 — RTL87xx/RTL95xx (и прочие модули серии) имеют в SDK FreeRTOS по-умолчанию и никак иначе.
Должен пояснить, что в своем проекте использую СТМку, которая снимает показания амперметров с трёх фаз, меряет обороты двигателя, щёлкает релюшкой и отправляет показания/принимает команды по mqtt, и чудесно со всем этим справляется без дополнительной прослойки в виде ОС.
Спасибо ответившим.
А вас точно интересует ответ? ;)
В общем, разным задачам — разные решения. На определённых задачах и ОС вам понадобится.
Вы лучше некуда разъяснили ситуацию.
Сколь много ресурсов железяки отнимает freertos(прошивка/озу)?
Жаль, не могу истово плюсануть.
Не за что. :) По поводу ресурсов — на практике всё различается, но чтобы просто представить себе порядок цифр, можно поглядеть на их официальный FAQ по потреблению памяти. Если вкратце, то:
- 5-10 Кб флэша в минимальной конфигурации на STR71x с полной оптимизацией и четырьмя приоритетами задач. На других машинках может быть и меньше; если добавлять фич, то больше — по опыту, разбухает не очень сильно.
- Оперативной памяти, на той же машинке:
- 236 байт на само ядро.
- 76 байт на каждую очередь, плюс размер очереди (сколько данных хочется там хранить, сами выбираете).
- 64 байта на каждую задачу (при максимальной длине имени задачи 4 символа), плюс сколько отведёте на стек задачи. Задач из коробки будет одна или две (idle task и, если сконфигурируете, timer task).
По опыту — больше всего оперативной займут стеки задач, если задач много и им приходится давать много стека (например, printf()
много стека ест при вызове) то расходов действительно будет порядком. Но всё в ваших руках, если иерархия вызовов не очень глубокая и ничего жадного до стека не используется (вызовы вроде printf(), большие локальные структуры или массивы), то стеки могут быть маленькими. Для задач вроде интерфейса (лампочки, пищалки и т.п.) можно использовать корутины. Они ограничены простыми задачами, но собственного стека у них нет (все корутины бегут на выбранной вами задаче, обычно idle task, и используют её стек), поэтому они совсем легковесные.
Вопрос с влиянием на быстродействие не очень однозначный. RTOS, в отличие от привычных крупных настольных ОС, в принципе не обязана чем-то шуршать в отсутствие внешних раздражителей, затрачивать процессорное время на поддержание себя самой. Большая часть накладных расходов будет приходиться на переключение контекста. Если упрощённо, то переключение контекста может произойти в таких случаях:
- Вы вызвали блокирующий системный вызов (начали ждать очереди, семафора, или просто решили поспать заданное время). Внутри вызова планировщик занесёт задачу в список ждущих и переключится в наиболее приоритетную свободную задачу.
- Произошло какое-нибудь прерывание, в котором вы разблокировали какую-то задачу (отправили что-то в очередь, которую задача читает, отдали семафор и т.п.). При этом вызовется планировщик и переключит задачу, и из прерывания вы вернётесь уже в другую (если у неё приоритет).
- Вызвалось прерывание системных часов (tick) и планировщик (который вызывается внутри) решил, что пришло время бежать другой задаче (к примеру, истёк период сна). Насколько часто вызывается прерывание, настраиваете вы, от этого будет зависеть гранулярность системных часов и всяких периодов сна и таймаутов. Есть режим, при котором вообще можно без регулярных тиков (но ему нужен один аппаратный таймер или, например, RTC).
В том же официальном FAQ по ссылке выше есть пример для определённых условий (Keil, Cortex-M3, без stack overflow checking, без статистики, оптимизация на скорость). При этом на переключение контекста уходит 84 такта (на самом деле — на работу планировщика, даже если он решил не переключать контекст). Можно (очень грубо) прикинуть сценарии и сколько при этом будет накладных расходов. Например:
- Машинка работает на тактовой 16 МГц, частота системного таймера 100 Гц (гранулярность 10 мс). Если всё в покое, прерывания не вызываются, ничего кроме системного таймера не бежит, то планировщик вызывается 100 раз в секунду, на сумму в 8400 тактов. Это примерно 0.05% процессорного времени. Если частота системы ниже, то накладные расходы в сравнении больше — при 1 МГц будет уже 0.84%.
- То же самое, плюс каждые 5 мс вызывается прерывание контроллера DMA, оно посылает блок данных задаче-обработчику. Каждый посланный блок вызывает два переключения контекста (прерывание вызывает переключение из idle task в обработчик, обработчик закругляется с данными и засыпает в ожидании новых — контект переключается обратно в idle task). Теперь в секунду происходит 500 переключений контекста, 42000 тактов накладных расходов. Это уже 0.26% процессорного времени на накладные расходы (на 1 МГц — 4.2%).
Это очень примерно, я мог что-то не учесть (если что, надеюсь, меня поправят), на других машинах/компиляторах/настройках тоже будет различаться, так что это для того, чтобы общее ощущение создалось. Пример тоже слегка экстремальный, обычно такой яростной активности нет, к тому же есть много способов не переключаться так часто (например, если вы можете в прерывании буферизировать данные и посылать в задачу кусками побольше). Режим tickless idle позволит сэкономить на системном таймере при необходимости, чтобы в отсутствие активности накладных расходов совсем не было. В общем, примерно такая картина.
Простой пример в виде задачи. Есть контроллер, которые меряет n каналов АЦП и обрабатывает их (скажем 10 мс на одну выборку). Есть RS485 по которому нужно передавать обработанные данные с минимальной задержкой (максимальное время ответа — 1 мс).
Такую задачу решить с RTOSом — раз плюнуть.
Тем более суффикс OS не говорит о том, что там сверхсложная система, которая требует кучу памяти, ресурсов и т.п. FreeRTOS, например, требует мало ресурсов.
Под ESP8266 можно писать на C(++), сомнений нет. Какая роль в этом проекте FreeRTOS — не понял :(
— LUA/MicroPython с прошивкой NodeMCU
— ESP без OS
— ESP с FreeRTOS
т. к. проект just for fun и для самообучения, я выбрал вариант 3, в котором помимо самой ESP я познакомлюсь еще и с FreeRTOS…
У каждого свои критерии выбора, не о том вопрос.
Например, программа для ESP в Arduino-style выгдядит так:
void setup ()
{
}
void main()
{
while (1) {
do_something();
yield(); // выполнять код, который остался "под капотом". Сеть, таймеры..
}
}
Стоит в главном цикле запустить "тяжелый" код — можно получить побочные эффекты (обрывы сети как минимум).
RTOS как-то позволяет обходить это ограничение?
Если ошибаюсь — поправьте.
Вопрос в том что будет если код выполняется очень долго, в Arduino для этого надо расставлять yield (или delay), иначе отвалится вайфай а потом придет wdt reset.
Не ради спора, а просто уточнения ради, хочу дополнить что у FreeRTOS, во-первых, режим вытесняющей многозадачности конфигурируется (настройка configUSE_PREEMTION
во FreeRTOSConfig.h
), а во-вторых у пользователя есть возможность руками переключить контекст (вызвав taskYIELD()
, хотя при включённой вытесняющей многозадачности это по идее никогда не понадобится). Ну и, конечно, проверка необходимости переключения просходит в системных вызовах — когда вы отдаёте семафор, пишете в очередь, ставите флаг и т.п., так что если вы запишете в очередь в прерывании, то вернуться вы можете уже в освободившуюся задачу, а не в ту, которую это прерывание прервало. Это просто чтобы не создалось впечатление, что переключение происходит только на тактах.
Таким вот нехитрым образом, с помощью языка C и рук с небольшим радиусом кривизныНаверное, подразумевался все же большой радиус кривизны :)
Из PlatformIO пытаюсь пользовать — задача не запускается (пример rtos_blink), да и SDK старый, 2017 года.
Ломают сложности установки, хотя ну ооочень хочется задействовать RTOS на данном чипе, учитывая, что до этого пользовал Arduino SDK, а там NONOS_SDK
Немного о программировании ESP8266 на C под FreeRTOS