Comments 35
Без простыни дефайнов ну никак жить нельзя
Есть задачи, которые не решаются без макросов(некоторые пока что)
Пара примеров:
* Q_OBJECT
* SCOPED_EXIT
* библиотека nan — там можно без макросов, но какой смысл
* включение различных участков кода
* поключение различных заголовочных файлов
У вас в исходниках thread.hpp опечаточка закралась: GetTaskHanlde
А ядро — это действительно треды, шедулер и IPC. Остальное не его забота.
void Button::HandleInterrupt() {
myTask.Signal();
}
Но обвязку сделать уже не дело ОСРВ, так как этот механизм можно сделать по разному, можно сделать быстрым но жрущим много памяти, можно чтобы быстро, мало памяти, но много ручной работы,… т.е. не дело обертке решать за пользователя, как это реализовывать, так как зависит от конкретного проекта и контретных требований. Например, реализую я этот механизм с помощью шаблона подписчик, так чтобы любой мог подписаться на прерывание, но сколько этих подписчитков может быть? 10-100, динамически выделять память я же запретил себе :) Придется память выделить, а может у вас уже памяти нет. Поэтому пусть пользователь сам решает, как ему прерывание обрабатывать.
Для Cortex M4 «все» операционки используют 3 прерывания, прерывания System tick timer, System Service call via SWI instruction, Pendable request for system service, которые собственно в основном для ОСРВ и были придуманы
Есть нюанс. Tickless-системы — а это направление модное и правильное, вон Mbed сделали tickless с полгода назад — SysTick не используют, т.к. им by design не нужен регулярно тикающий таймер. За счёт этого у них ниже энергопотребление.
То, что tickless-ядро не использует регулярно стучащий таймер не означает, что ей вовсе не нужен таймер. Он просто переустанавливает таймер каждый раз на время минимального ожидания из необходимых
Большой труд проделан. Подобная обёртка уже есть в CMSIS: CMSIS-RTOS
Насчет отказа от динамического выделения памяти — не согласен. У меня есть пару проектов, где контроллер работает в разных режимах, с разными наборами запущенных тасков, и без динамического выделения памяти — никак.
И все эти наслоения макросов из кишков фриртос никуда не деваются. И если использование операционки с этой прослойкой, действительно, должно упроститься, при отладке, если туда понадобится-таки лезть, мы опять упрёмся в void*, который надо привести к нужному типу, достать оттуда ещё один указатель, ещё раз привести…
Насчет кастинга — соглашусь, но частично. С одной стороны — это потенциальное место для ошибок, нужно быть внимательным. Но, если говорить о С без ++, то не всегда кастинга можно избежать так, чтоб код существенно не "распух" в размерах. Это пожалуй на целую статью потянет.
По поводу макросов. Их обилие связано с стремлением создать универсальный код, с возможностью гибкого конфигурирования. Например, в некоторых проектах могут быть нужны очереди, а в некоторых — нет, а макросы позволяют исключить лишний функционал. Боюсь, что кроме макросов и дирректив условной компиляции, нет другого способа решения такой задачи.
И там не пахнет не то чтоб плюсами, там банальных инлайн-функций вместо всех этих макросов нету…
Авторов FreeRTOS с таким подходом понять можно. Простить — сложнее :-)
В общем, моё мнение — эту обёртку можно использовать в каких-то особо странных случаях («мне нужно только freertos, потому что у неё сертификат, но самой freertos я видеть не хочу»). Иначе, если не хочется видеть фриртос — ей можно просто не пользоваться, благо альтернативы есть…
сначала мы использовали одну операционную систему, потом я для своих нужд начал использовать FreeRTOS, потом мы перешли на другую
А можно раскрыть тему: ЗАЧЕМ?!
Для Cortex M4 «все» операционки используют 3 прерывания, прерывания System tick timer, System Service call via SWI instruction, Pendable request for system service, которые собственно в основном для ОСРВ и были придуманы.
Для работы используются два — для переключения задач (обычно — PendSV_Handler) и для системного таймера (и тот только в обычном, не tickless, режиме).
SWI + SVC_Handler — это такой фриртосный костылик для запуска самой первой задачи.
1. Зачем создавать враппер над «тредами», «семафорами», «мьютексами» и тп. если это уже было сделано в boost а также в стандартной библиотеке начиная с C++11.
(для использования достаточно создать POSIX совместимый враппер на С)
2. Любое упоминание об отказе от чего либо это всегда холивар. Вот выше у вас написано что вы не любите приведение типов и тут же приводите код который ими пестрит.
(С привидениями нет проблем если соблюдать правила описанные в соответсвующем стандарте)
3. Без динамической памяти жить в современном мире разработки очень и очень трудно. Например банальный паттерн PIMPL без ухищрений. Если необходимо уйти от фрагментации можно использовать memory pool, а также placement new.
Как жить без std::string и std::vector?
В любом случае идея написать враппер очень правильная и нужная. Сам писал в свое время(свой клас тред с шаблонным параметром размера стека, мьютексы и тп). Посмотрите в сторону использования библиотеки boost она не такая страшная как ее обычно рисуют в мире embedded.
2. Написано, что не отказ, а по возможности, это не моя прихоть, а требования стандартов надежности, да приведение типов есть, но они все из-за того, что по другому никак. Но избегать надо.
3. Вектор помогает, согласен, но жить без него можно :) также как и без стринга, когда у вас ограничения в ОЗУ. Boost хорошая библиоткеа, но половина из неё не будет работать с IAR, как не работает полностью atomic.
Мое мнение что мир emdedded разделен все таки на три части — 1 — это те кто делает, что-то на основе, чего-то типа Linux, вторые это те кто юзает большие микроконтроллеры с 1 МБ ПЗУ и 512 ОЗУ и третьи это те кто юзает небольшие до 256 кБайт ПЗУ и 32 кБ ОЗУ микро для датчиков — вот, я думаю, что как раз моя статься ориентирована на них, чтобы продвигать переход на С++. А так я полностью согласен с вами, чем больше уже готовых решений принимать, тем лучше, но все таки специфика есть везде…
враппер над «тредами», «семафорами», «мьютексами» и тп. если это уже было сделано в boost а также в стандартной библиотеке начиная с C++11
Очевидно, треды и средства их синхронизации должны взаимодействовать с ядром ОС. Т.е. надо писать порт STL на конкретную операционку. Пока, к сожалению, таких супергероев не видно…
С привидениями нет проблем
Да нету никаких проблем с приведениями типов. Если никогда не ошибаться. А если в макрос, внутри которого cast на cast'е, передать что-то не то, компилятор это тихо сожрёт без каких-то варнингов.
Как жить без std::string и std::vector?
Продумать и описать протоколы, по которым идёт взаимодействие с внешним миром, статически выделить необходимые буферы (хоть сишные, хоть std::array), и жить…
Посмотрите в сторону использования библиотеки boost
В описываемом случае (контроллер относительно мелкий, malloc по каким-то соображениям не используется) лучше смотреть куда-то в район etlcpp.com. Бустом, правда, я никогда не пользовался — посмотрел, испугался, и закрыл.
С++ обертка для «всех» Операционных Систем Реального Времени для CortexM4