Как стать автором
Обновить

Комментарии 47

Зачем вообще на микроконтроллере использовать ОС и тратить на нее ограниченные ресурсы, если можно написать компактный и эффективный код под конкретную задачу?
Лично для меня, как для Java программиста, контроллер без OC слишком низкоуровнево и, пока что, геморройно. А так получается, использование FreeRTOS в данном конкретном случае ESP8266 — золотая середина между низкоуровневым программированием без ОС и скриптовыми языками типа LUA. Хотя доводилось в университете программировать 8-битные PIC на ассемблере, и там для ОС точно места нет.
Так там ведь от той ОС планировщик, очередь да таймер по хорошему. Куда уж компактнее

Начиная с определенной сложности задачи, использование легковесных ОС вроде FreeRTOS оправдано и активно применяется в Embedded разработке. И даже на более слабых контроллерах, а ESP8266 обладает довольно внушительными ресурсами (существенно превышает "народные" ATMega или STM32F1xx). Правда с памятью там проблемы были, вроде как.


А задача работы WiFi и IP стеком уже весьма серьезная. Так аналог ESP8266 — RTL87xx/RTL95xx (и прочие модули серии) имеют в SDK FreeRTOS по-умолчанию и никак иначе.

Шибко грамотные специалисты переполнившись ядом негодования, кинулись минусить безобидный вопрос менее опытного.
Должен пояснить, что в своем проекте использую СТМку, которая снимает показания амперметров с трёх фаз, меряет обороты двигателя, щёлкает релюшкой и отправляет показания/принимает команды по mqtt, и чудесно со всем этим справляется без дополнительной прослойки в виде ОС.

Спасибо ответившим.

А вас точно интересует ответ? ;)

Вне всяких сомнений.
Выложите код на GitHub и можно будет более предметно обсудить преимущества и недостатки ОС в embeded. Сам придерживаюсь подхода — каждой задаче свой инструмент.
Для своих проектов я использую Mercurial, так что до гитхаба код вряд ли дойдет. Но подумаю о том, чтобы открыть репозиторий на BitBucket.
даже lwip можно запустить без ОС, но зачем? на самом деле ос — сильно облегчает многозадачность и вопрос стоит по другому — зачем изобретать велосипед, если все это решается ОС. ЗЫ: сейчас делаю проект без ос на STM8S003, потому что реально нет места — используется 7733 байта из 8192 на максимальном уровне оптимизации, и надо будет еще добавлять функционал :(, но если ресурсы позволяют — ось рулит.
То что вы описали про свой проект, спокойно умешается в тысяче строк и паре циклов. Есстественно там не нужна ось. А вот когда устройство например имеет свой графический интерфейс (ессно самописный), то без банального планировщика что то многозадачное писать муторно. Хотя я все таки предпочитаю использовать свой планировщик в стиле ентить в HLSDK.
Просто вы сформулировали вопрос как утверждение, отсюда и минусы. Отвечая на него — вы, конечно, можете обойтись без ОС. Но в какой-то момент вам понадобится, например, делать длинную обработку своих показаний и, одновременно, скажем, данных с датчика вибрации. Вы решаете, что это не проблема, и пишете в своём главном цикле оркестровку обработок данных из прерываний — мальчики амперметры налево, девочки вибрация направо. Это вносит зависимость между (например) концептуально независимыми потоками данных. Потом вы обнаруживаете, что у вас есть другой датчик, данные от которого надо обработать срочно, сразу по пришествию, но обработка слишком длинная для прерывания, а пускать их в главный цикл — не получается, цикл то и дело занят обработкой амперметра, и надо её как-то прерывать и заниматься срочными данными. Потом вы решаете использовать DMA для записи на SD-карту, у вас появляется ещё один асинхронный процесс (начали пересылку, теперь можно что-то другое делать пока DMA-контроллер не просигналит, что пересылка кончилась), и вы начинаете городить конечный автомат, что само по себе не плохо, но ваш код начинает размазываться по разным состояниям. И в какой-то момент вы приходите к осознанию того, что вы написали собственную ОС. :)

В общем, разным задачам — разные решения. На определённых задачах и ОС вам понадобится.
Спасибо за глубокий ответ. Действительно, примерно что-то такое и началось, когда в довесок ко всему решил прикрутить вывод на экран 5010.
Вы лучше некуда разъяснили ситуацию.
Сколь много ресурсов железяки отнимает 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 позволит сэкономить на системном таймере при необходимости, чтобы в отсутствие активности накладных расходов совсем не было. В общем, примерно такая картина.

FreeRTOS — это система реального времени. Без систем реального времени многие задачи будет почти невозможно выполнять.
Простой пример в виде задачи. Есть контроллер, которые меряет n каналов АЦП и обрабатывает их (скажем 10 мс на одну выборку). Есть RS485 по которому нужно передавать обработанные данные с минимальной задержкой (максимальное время ответа — 1 мс).
Такую задачу решить с RTOSом — раз плюнуть.

Тем более суффикс OS не говорит о том, что там сверхсложная система, которая требует кучу памяти, ресурсов и т.п. FreeRTOS, например, требует мало ресурсов.

Под ESP8266 можно писать на C(++), сомнений нет. Какая роль в этом проекте FreeRTOS — не понял :(

Когда я выбирал на чем писать, выбор был из 3-х вариантов:
— 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 как-то позволяет обходить это ограничение?


Если ошибаюсь — поправьте.

В FreeRTOS, насколько я знаю, нет определяемого программистом «главного цикла». Просто несколько задач с разными, или не очень, приоритетами, которые управляются планировщиком, +прерывания.

Вопрос в том что будет если код выполняется очень долго, в Arduino для этого надо расставлять yield (или delay), иначе отвалится вайфай а потом придет wdt reset.

FreeRTOS это система вытесняющего типа, т.е. переключение происходит не по прямой команде пользователя, а планировщиком. Проверка необходимости переключения происходит каждый системный такт (1мс по умолчанию). Если в такой такт обнаруживается задача готовая к выполнению с приоритетом не ниже текущей, то происходит переключение. Про ваш пример с wdt — оптимально сделать его задачей высшего приоритета, которая будет в постоянном ожидании семафора на выполнение. Получив такой, обнулять таймер и снова в ожидание. А семафоры раздавать в остальных задачах, что будет свидетельствовать об отсутствии зацикленности там где ее не ждете.

Не ради спора, а просто уточнения ради, хочу дополнить что у FreeRTOS, во-первых, режим вытесняющей многозадачности конфигурируется (настройка configUSE_PREEMTION во FreeRTOSConfig.h), а во-вторых у пользователя есть возможность руками переключить контекст (вызвав taskYIELD(), хотя при включённой вытесняющей многозадачности это по идее никогда не понадобится). Ну и, конечно, проверка необходимости переключения просходит в системных вызовах — когда вы отдаёте семафор, пишете в очередь, ставите флаг и т.п., так что если вы запишете в очередь в прерывании, то вернуться вы можете уже в освободившуюся задачу, а не в ту, которую это прерывание прервало. Это просто чтобы не создалось впечатление, что переключение происходит только на тактах.

я для своего проекта использовал esp-open-sdk, это было NOSDK версия, но там был хорошо спрятанный баг, который вроде бы решили.
Три esp8266 трудятся в так называемом продакшене с freertos у разных заказчиков. Удобно, не напряжно, разделил на модули, модули в таски и все. Правильно автор что freertos заюзал. А кто говорит что без ОС лучше, ну не знаю, может Вы не разобрались… Не те задачи и не те ресурсы что бы спички считать.
Подскажите, что почитать с примерами, чтобы разобраться новичку.
Смотря в чем разобраться — если конкретно с ESP8266 — в SDK есть много разных примеров…
Для начала с чего-нибудь попроще, типа Maple mini. Примеры в том числе с работой с самой SDK.
Я пока только с ESP знаком, сейчас вот ESP32 палочкой с разных сторон тыкаю. С другими контроллерами не разбирался, и посоветовать не могу ничего.
jonic писал, что «возможно не разобрались с RTOS», я для своих задач плюсов не вижу, но разобраться хочу, поэтому и спросил. Т.е. практически безотносительно железа.
Если тыкнете носом в пошаговое руководство по ESPшной SDK буду тоже благодарен.
Не знаю даже, есть ли пошаговые руководства вообще. Я просто открывал официальную документацию по SDK, описание API FreeRTOS, lwip и разбирался. Начинал с попыток завести официальный SDK, прошить свой хеллоуворлд. После неудачи с этими инструментами нагуглил ESP Open RTOS, и с ним завелось. На том и остановился.
Вот побольше бы таких пошаговых писали, а то большинство документации или примеров напоминают мем «как нарисовать сову». У меня хоть и коряво получается писать, но на другом ресурсе пару примеров hello world со скриншотами попытался описать по теме в которой сам немножко разобрался.
могу дать исходник своего проекта, если интересно, извините за поздний ответ) весь в работе, не слежу
Мне если честно сейчас больше mtk7688 и платы на ней симпатизируют, потому что не так уж и дороже и openwrt. Например из коробки отлично работают usb звуковые карты с али по 1$, а так же из коробки можно сделать флешку с системой и файлами приличного размера. Да и платы стоят в районе 700-800 рублей, что не дорого считаю за вполне крутые характеристики
Дороговатые они как-то. И как у них с энергопотреблением?
Их точно не стоит от батарейки питать, мы сейчас говорим про SoC с вынесенной памятью(до 256мб) и флешем, поэтому рассуждать о потреблении одного чипа было бы не совсем корректным. У меня специфика что постоянное питание присутствует) а 12$ за готовый модуль с 700mhz SoC 32 ROM и 128 RAM я бы не сказал что дорого
Спасибо за интересную статью! А MQTT сервер какой использовался?
Пока разворачиваю свой, тестирую на www.cloudmqtt.com. Там есть бесплатный план с кучей ограничений, но для тестов хватает.
А данные делите на два потока для чётных и нечётных минут? Зачем так сделано?
Один поток делает замеры, второй отправляет результаты… Дальше буду подбирать интервал отправки (и добавлю глубокий сон) так, чтобы меньше тратилось энергии…
Я к тому, что у вас сбор данных раз в минуту, а отправка раз в две минуты как я понял. Почему нельзя было отправлять сразу после измерения? А так принятые пары значений потом придётся специально «разносить» по времени, т.к. все стандартные сервисы берут время приёма mqtt сообщения как я понимаю.
Время замера сохраняется на самой ESP, которая, в свою очередь, синхронизируется по SNTP… Так что отправлять можно и раз в 30 минут, время каждого замера не потеряется…
Я понимаю, что не потеряется, но отправляете то вы их через mqtt, соответственно нужно отправлять пару значение-время и потом руками разбирать. Стандартные системы умных домов по-моему такого не поддерживают (я просто из текста не очень понял куда и чем вы эти данные принимаете и складываете).
Принимаю через MQTT самописным сервером на Java. Насчет стандатрных систем умных домов я не в курсе, даже не исследовал, что вообще в этой области есть.
Таким вот нехитрым образом, с помощью языка C и рук с небольшим радиусом кривизны
Наверное, подразумевался все же большой радиус кривизны :)
Пробовал и с OpenSDK, и с ESP8266_RTOS_SDK — не заводятся, хотя делаю по инструкции((
Из PlatformIO пытаюсь пользовать — задача не запускается (пример rtos_blink), да и SDK старый, 2017 года.
Ломают сложности установки, хотя ну ооочень хочется задействовать RTOS на данном чипе, учитывая, что до этого пользовал Arduino SDK, а там NONOS_SDK
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории