Комментарии 74
Опять же ИМХО, но для себя выбрал путь «Си для драйверов + Lua для логики». Поскольку в моей практике редко встречаются устройства с «золотой серединой». Это либо совсем уж «преобразователи протоколов» (там нет никакой Lua. Драйвера и пара функций). Либо уж совсем монстры (GUI, логика переходов сравнимая с игровыми ботами...). Но к Rust присматриваюсь чисто в академических целях. Может в будущем займусь всерьез.
Как только вы начинаете решать с помощью RTOS задачи, для которых не нужно реальное время, что-то начинает идти не так...
+ к этому — на этом же контроллере работает основная логика устройства.
Сможете сами посчитать сколько потоков (задач) крутиться одновременно?
LWIP — сам по себе отжирает 1 поток в «стандартной поставке».
ModbusRTU — у меня живет в прерываниях + 1 поток для ответов (на каждого клиента, понятное дело)
HTTP — т.к. это по сути TCP, то 1 поток. Суммарно я смогу даже с учетом 4-х клиентов выделить около 10.
И что из этого требует реального времени?
Особенно, если планируется дальнейшая поддержка и модификация проекта.
Вам тогда нужна просто ОС, а не ОСРВ.
А обычный Linux не подходит?
За свою карьеру я научился понимать, что стоимость владения и сопровождения конкретной технологии зависит от очень многих факторов, которые не всегда бросаются в глаза при первоначальном выборе.
Поднять freertos может и легче, чем Linux, но найти разработчиков и техническую поддержку для Linux, я думаю, гораздо легче, чем для freertos… как пример.
Удобно оно пока работает, а если уж такого не получилось, то проще переписать без нее, чем разбираться.
А еще, чтобы облегчить себе жизнь, есть инструменты вроде
www.state-machine.com/qm
www.uppaal.org
и.т.п.
А если серьезно, то правильно настроив NVIC — можно получить такой код, когда такой проблемы не возникает.
Насколько я знаю, еще есть средства самого языка для атомарного доступа. Но ими я не пользовался, увы. Не было необходимости. Так что буду знать, если знатоки напомнят. std::...;
Иногда приходилось применять «костыль» с блокировкой всех прерываний и последующим возобновлением. Так как это дело пары команд ассемблера, то ничего ИМХО, страшного.
we.easyelectronics.ru/STM32/atomarnye-operacii-v-cortex-m3.html
Но опять же это к вопросу умения работы с периферией.
— умение работать с периферией ортогонально использованию ОС.
— что за жуткие таймеры занимающие 1кб? для того что бы использовать один аппаратный таймер для отметки 10 интервалов достаточно 10 32-битных переменных или task_sleep. Неумение использовать таймеры никоим образом не относится к недостаткам ОС. А для аппаратных таймеров найдутся другие важные задачи. У меня в одном из проектов аппаратными задачами были заняты 11 таймеров из 13, и как быть по вашему, если нужно 5 интервалов?
— какая религия запрещает использовать конечные автоматы совместно с ОС?
Я не фанат ОС, использую приблизительно в 1 из 3 проектов, и не всегда FreeRtos, где полегче TNKernel и ее форк TNeo использую, но Ваши аргументы абсолютно неубедительны и сводятся к тому, что инструмент в кривых руках работает криво. Так это вроде очевидно и не только к ОС и МК относится.
И да, применяя такой сложный инструмент, как OC, нужно знать её сильные и слабые стороны и понимать цену её применения.
Это к тому, что та же RTOS воспринимается у неискушенных разработчиков типа меня, прежде всего как универсальное средство решения широкого круга задач, что, в свою очередь, побуждает пихать её в большинство домашних проектов, даже не особо задумываясь о целесообразности. Простота этих проектов не дает возможности наступить на грабли, что в свою очередь вызывает ложное ощущение профессонализма.
Замечательно что статьи, подобные этой, позволяют развернуть дискуссию и обратить внимание на интересные мнения, Ваше в том числе, и более критически оценить собственные навыки и стереотипы.
На мой взгляд основной минус использования ОС — это трудноуловимые баги. Два дня сидишь, взявшись за голову, потому что вообще непонятно, что происходит. Просто HardFault в случайный момент времени, в стеке вызовов мусор.
При использовании FreeRTOS на stm32 прерывания, которые используют системные вызовы, обязательно должны иметь приоритет ниже, чем прерывание, которое вызывает диспетчер. Источник. Конечно, это должен проверять ассерт, жаль, что он по-умолчанию выключен!
что в какой-то момент происходило прерывание, которое переполняло стек текущего потока, залезая в стек другого потока, который падал в совсем другой момент.
И это я молчу про "классические" обычные многопоточные баги.
Если же все написано в автоматном стиле, то все как-то сильно проще отлаживается.
По второму тоже самое, но дам подсказку: www.freertos.org/Stacks-and-stack-overflow-checking.html
Учитесь сначала читать документацию, а потом использовать все доступные средства. А если все делать методом "тыка", то да, баги становятся трудноуловимыми…
Спасибо, я уже в курсе.
По первому — да, конечно, кто ж спорит. Только вот ссылку на это я сейчас полчаса искал — и это я знал, что искать! Документация на FreeRTOS оставляет желать лучшего, прямо скажем.
По второму — как вы, наверное, тоже в курсе, эта защита от переполнения не является идеальной (по вашей ссылке так и написано); полностью спастись можно только с MPU, которое есть далеко не всегда.
Или, например, если переполнение вызвано прерыванием и приведет к hard fault'у до проверки. Вариантов достаточно много.
Разумеется, проверки — вещь не бесполезная, просто нужно осознавать, что это не панацея.
Может быть, вы имеете в виду, что регистр SP другой (не MSP, а PSP)?
Всё так, только полностью наоборот. MSP который использовался в системе без ос — теперь обслуживает прерывания. PSP предназначен для задач, и его можно переключать из прерывания.
Каждый объект имеет функцию processEvents() в которой он проверяет, нужно ли ему что-то сделать, выполняет это, или сразу делает возврат из функции.
В main() у меня бесконечный цикл, в котором для каждого объекта вызывается processEvents():
for(;;) {
uart.processEvents();
spi.processEvents();
webServer.processEvents();
...
sleep();
}
В конце цикла сон. Возврат из сна по любому прерыванию, включая systick.
Преимущества такого подхода:
1. Все предельно просто. Не нужно никаких RTOS, есть только одна функция, которая периодически вызывается.
2. Не нужны мьютексы для синхронизации между задачами. Однако, не забываем про прерывания!
3. Не нужно выделять память на каждую задачу отдельно. Достаточно такого количества памяти, что потребляет самая ресурсоемкая задача.
Недостатки:
1. Не так круто, когда у тебя под капотом банальный бесконечный цикл, а не RTOS.
2. Время исполнения задачи не должно быть слишком большим. Это не значит что нельзя делать какой-то очень длительный расчет, просто придется его бить на части и запоминать промежуточные результаты.
3. Возможно, не так энергоэффективно, как RTOS. Хотя если работы у задач нету, они все быстро исполнятся и CPU уйдет в сон.
С RTOS мне лично не понравился именно момент с назначением количества памяти каждой задаче. Мало дашь — получишь очень трудноуловимый баг с порчей соседних задач. Много дашь — памяти не хватит, задач то много.
Но куда проще взять чужой непроверенный код, а потом жаловаться, что "RTOS — это плохо". Если там ошибка, которая заставляет её срать в память, что точно так же она может убить что-нибудь и без RTOS. Причем если это не выяснится при написании(и вы будете думать, что все хорошо), то выяснится уже в продакшене, что гораздо хуже.
Однако в большинстве случаев эта мысль ошибочна. И в данной статье я расскажу, почему.
И… не рассказали.
Дана противоположная точка зрения вида «можно выделить часть ресурсов под ОС, получив взамен понятность кода». Дана ваша точка зрения о том, что можно было в таких и таких случаях сделать иначе.
Но нет описания и примеров того, где выделение ресурсов под ОС оказалось фатальной ошибкой.
Чем плоха стыковка через очередь — из этого описания непонятно. Т.е. если это съедает слишком много ресурсов, что становится критичным — тогда вопросов нет. Но иначе-то — в чем проблема использования такой абстракции?
Принимаемые данные с последовательного порта клались в очередь, а затем раз в 20 мс выдавались пачкой по другому интерфейсу. Проблема в том, что это нагружало процессор очень значительно. Поскольку прием велся по DMA на частоте примерно 1 мегабит, вызывались прерывания, там вызывалось добавление в очередь ресурсом до 50к элементов, а затем другой поток раз в 20 мс извлекал в массив данные и по DMA отправлял в другой порт. А ведь можно было убрать этот уровень абстракции с очередью и просто использовать кольцевые буферы. Поскольку никакой проверки на корректность не производится (по ТЗ).
Задача приема реализует кольцевой буфер. Вызывается шедулером каждую мс, проверяет совпадает ли NTDR с сохраненным значением, если нет — выгребает все что принято. В таком случае прерывания от UART пообще не нужны.
Задача передачи вызывает функцию у задачи приема "дай мне порцию данных". В этой функции задача приема использует мютекс, который захватывается так же при добавлении данных в кольцевой буфер — и никакие очереди не нужны.
Понятно, что можно наворотить все что угодно, насоздавать кучу задач, а потом ругать RTOS.
Ну а вообще да. Не вина ОС, что ее используют через одно место. Сам использую ОС периодически. Проблема в том, как ее МОЖНО при КРИВЫХ РУКАХ использовать. Что и происходит периодически.
Речь о чём, сам вопрос надо ставить подругому: не злоупотребление, а почему пользователь выбирает вариант с РТОС. Чем-то же ртос завлекает, быстрым получением работающей поделки, ненужностью разбираться в периферии и тд, а вовсе не необходимостью «паралелить» процессы. Когда есть хороший набор типовых библиотек позволяющий не напрягаться на работе — мало кто спрыгнет на ртос ;P С другой стороны сейчас не 2000год, есть куча РТОС для МК которые позволяют вообще не вспоминать о регистрах периферии, потому и
Все потому, что народ не хочет заниматься проектированием архитектуры своего софта. Т.е. что и когда надо опросить, где хранить, и кому и когда нужны будут полученные данные, разбить задачу на более мелкие и оценить их время выполнения и дедлайны. Выделить задачи, не требующие реального времени. Тогда все становится понятно.
А с РТОС — бах-бах и в продакшн.
Человек просто берёт готовый пример, адаптирует под свои условия, и наслаждается готовым результатом. Ничего плохого в этом нет.
Трудно быть первопроходцем: когда примеров нет, публичных библиотек нет, и вокруг одни юзвери — умеющие только скачивать готовое.
Куда столько?
обслуживание wdt (если ОС упала, то задача его не сбросит и устройство перезагрузится);
Если ос упала — значит девайс глюкавый, и требует на выбор: тотальной отладки или утилизации. Перезапуск — это для простых устройств, типа примитивных конечных автоматов. Там даже ос не нужна.
А для сложных девайсов циклический перезапуск — повышает шанс пожара или удара током, или всё вместе.
Ну и насчёт собаки.
Выгуливать её должна одна задача, в идеале — системная. Уж если цикл системной задачи перестаёт корректно выполняться, то всё остальное уже не так важно. Сама системная задача может контролировать что угодно — у неё для этого есть все ресурсы и права.
Обрабатывать событие собаки необходимо отдельным ресурсом, который гарантированно будет выполняться, в не зависимости от общей температуры больных. В самом простом случае — это набор средств тушения пожара: корректное закрытие записи во флешь память, принудительная установка ног мк в состояние стоп, сохранение отчёта или отправка отчёта, и ожидание отключения питания. У вас уже сбой — изображать бурную деятельность не стоит.
Событие собаки никто не обрабатывает. Собака все убивает, если ее не сбросить.
Надо отметить, что в устройствах с которыми я работаю — нет надобности в «закрытии сессии» (за исключением пары случаев, но они блокируются при нормальной работе).
Под первый вариант попадают все вторичные системы, временный глюк которых не приводит к необратимой катастрофе.
Второй вариант…
— Шеф, у нас тут верхний ключ на 600А пробило, и линия зависла на отметке 1200В. Давай ещё раз стартанём, вдруг её отпустит…
В этом случае нужно не только корректно завершить работу, но и запретить дальнейшую эксплуатацию до завершения ремонта.
А вот в работе. Тут вопрос. И, кроме резервирования, ничего в голову не приходит.
Но это совсем отдельная тема. Хотя, весьма интересная.
О злоупотреблении использования операционной системы в проектах под микроконтроллеры