Надо будет запилить свою статью, как в 42 года соскочить с менеджера по закупкам, стать embedded разработчиком на С/С++ и в 46 устроиться в международную компанию с релокацией;)
Решительно поддерживаю автора в стремлении использовать современные плюсы в мк. Но дабы сохранить коллегам автора и ревьюерам его кода зубную эмаль, неизбежно страдающую от зубовного скрежета, когда в проектах под мк они видят «virtual bool init(uint32_t val)», не менее настоятельно советую автору оперативно проштудировать MUST READ минимум:
a) Б. Страуструп «Программирование: принципы и практика использования С++» глава 25;
б) С. Мейерс «Эффективное использование С++ во встроенных системах»
с) Alex Robenko «Practical guide to bare metal c++»
плюс полезно будет посмотреть отличный доклад Карины Дорожкиной с конференции CPP Russia 2019, www.youtube.com/watch?v=Yv4nMocX78Q
Уверен, это даст автору отсутствующее сейчас (на мой взгляд) важное понимание, что у с++ «под капотом» в части использования в ембеде, и как правильно с этим жить. И в итоге поможет ему сойти с ошибочной тропы, которая привела его к написанию этого материала.
PS. Касаемо virtual. Вызов виртуальной функции примерно в 10 раз медленнее обычной (плюс оверхед на хранение таблицы указателей). Смотрим тесты, например здесь (взято у Ф. Пикуса ) quick-bench.com/q/42iKBatMiDjQtRHIcIWb3hLgbU8
Успехов!
Правда ваша, что в статье нужно было привести пример с рантаймовыми данными.
Исправляюсь: gcc.godbolt.org/z/nhhK64drr
(спойлер: тоже все весьма достойно)
Исключительно добротный материал. Проработанная и качественная подача материала, отличное оформление статьи. Номинируйтесь на Технотекст 2021, с удовольствием проголосую.
В далеком уже 2010 г. на плюсах для AVR-ок(!) писали так:
// создаем произвольный список пинов с разных(!) портов
PinList<Pa1, Pa2, Pa3, Pb3, Pb4> MyPins;
// записываем значение в этот список
MyPins::Write(0x55);
// смотрим ассемблерный выхлоп:
//вывод в PORTA
in r24, 0x1b
andi r24, 0xF1
ori r24, 0x0A
out 0x1b, r24
//вывод в PORTB
in r24, 0x18
andi r24, 0xE7
ori r24, 0x10
out 0x18, r24
Компилятор в компайл тайм сам рассчитал все битовые маски и логические значения, не оставив ничего лишнего на рантайм. Никаких динамических аллокаций, предельная детерминированность и нулевой оверхед. И это при возможностях языка и компиляторов 10-ти летней давности. Источник здесь.
Возможно этот простой пример подтолкнет Вас провести ревизию предубеждений касаемо обоснованности С++ во встроенных решениях.
Вы верно указали на пробелы в статье. Концепт ОС - ну совсем новорожденный. Торопился в публикации поделиться самой идеей "корутины + примитивы синхронизации с универсальным интерфейсом на базе co_await + переключение контекста". Вопросы сравнения с существующими ОС интересуют не меньше вашего, обязательно потестирую, главное чтобы работа оставила время...
Действительно, писал статью по ощущением моряка на мачте: "Земля! Земля!"
Захватила сама идея: воспроизвести базовый функционал ОС на новейшем стандартном инструменте С++20 - корутинах. Ранее аналогичных материалов не встречал, торопился первым ступить на новые земли... Тщеславен немного, каюсь)
Оценка преимуществ моего подхода (и есть ли таковые по факту) - чуть позже или отдельным материалом, или дополнением к этой статье.
Ну, фактически отправка символа по SWO это запись в регистр ITM->PORT. А ДМА в режиме MEM_TO_PERIPH для этого и предназначено. Другой вопрос, дотянется ли он до адреса 0xE0000000 (ITM). Не задумывался над этим… Сомневаюсь, но можно будет полюбопытствовать в RM.
AVI-crak, доброе утро! Признателен за ваше внимание к моей статье. Когда около 3-х лет назад я решил сменить профессию и засел за изучение МК и С/С++, неоднократно встречал ваши заметки в разных сообществах. Нередко они помогали разобраться в тех или иных вопросах.
Теперь по существу вашего отзыва:
… нужно делать иначе — использовать внешний буфер для дма при работе с физикой...
Так у меня ровно так и реализовано.
H7 умеет прекрасно умножать и делить, и не только целые числа.
Бесспорно. Вот только основной посыл моей статьи был о том, как заменить именно интерфейс printf-а, используя возможности самого последнего, 20-го плюсового стандарта. И честно указал, что позаимствовал алгоритмы и код конвертации в строку. Можно ли переписать и улучшить заимствованный код с учетом эволюции камней? Весьма вероятно, просто не это основная тема конкретно этой статьи. Ссылку на вашую имплементацию обязательно посмотрю, поэкспериментирую.
При этом печать массивов — самая большая глупость что можно придумать...
Резковато, конечно, но почему? Разве не удобно, напечатав два символа <<, быстро вывести в терминал фрагмент массива с «сырыми» данными любого числового типа? Или, использовав функционал views, прямо в операторе вывода сразу как-то отфильтровать их, выделить поддиапазон etc.?
… время преобразования в строку для одинарной или двойной точности 2us...
У меня за 9 мкс выводится не одно значение, а пример суммарно с 8 значениями разных типов, 2 строковых литерала с операциями выделения поддиапазона и реверса. Вы воспроизвели эти же условия?
Ну и еще раз подчеркну, цель у меня была понять, что могут дать современные плюсы с 20-м стандартом в задаче замены интерфейса printf-a. Насколько универсальным, лаконичным, эффективным и эффектным может выглядеть решение. На мой взгляд, чуть менее 180 строк кода, чтобы получить вполне функциональный аналог стандартного stream-а для embbed-a, это неплохо.
Доброе утро! А разве пример в самом начале статьи не очень убедительно это показывает? Когда единственный оператор вывода из двух печатных знаков работает со всеми форматами чисел, строковыми литералами и контейнерами, а также трансформациями над ними? Или я не совсем понял ваше сомнение? Тогда попрошу пример удобного на Ваш взгляд варианта. Спасибо за отзыв!
Их можно понять, Си в умелых руках — напалм. Вот только лучше компилятора умеют писать единицы, а грамотный плюсовой код даст ассемблерный выхлоп подчас эффективнее, чем на Си. Не уверен, что мне это удалось, но стараться надо — камни становятся мощнее/ жирнее, программы сложнее и уже нужен новый уровень абстракции.
У вас был опыт поднять boost::sml на МК? Моя предыдущая статья почти об этом. Я там пробовал как раз альтернативу sml от чародея из Яндекса — отъела сразу 200Кб + typeid + exceptions. Для МК это перебор. Предполагаю, что у boost::sml будет схожий результат. Если ошибаюсь, поправьте меня.
В классе ParserInterface необходимо добавить определение функций getDataImpl() и getIDImpl() по умолчанию, на случай если в классе-наследнике одна из них не нужна. Сейчас, если в наследнике «забыть» определить любую из них, будет ошибка компиляции. А так код сохранит работоспособность, просто при вызове из объекта базового класса ParserInterface, параметризованого классом с отсутствующим методом, будет вызвана «заглушка» определенная в базовом классе. Аналог виртуальной функции.
Надо будет запилить свою статью, как в 42 года соскочить с менеджера по закупкам, стать embedded разработчиком на С/С++ и в 46 устроиться в международную компанию с релокацией;)
a) Б. Страуструп «Программирование: принципы и практика использования С++» глава 25;
б) С. Мейерс «Эффективное использование С++ во встроенных системах»
с) Alex Robenko «Practical guide to bare metal c++»
плюс полезно будет посмотреть отличный доклад Карины Дорожкиной с конференции CPP Russia 2019, www.youtube.com/watch?v=Yv4nMocX78Q
Уверен, это даст автору отсутствующее сейчас (на мой взгляд) важное понимание, что у с++ «под капотом» в части использования в ембеде, и как правильно с этим жить. И в итоге поможет ему сойти с ошибочной тропы, которая привела его к написанию этого материала.
PS. Касаемо virtual. Вызов виртуальной функции примерно в 10 раз медленнее обычной (плюс оверхед на хранение таблицы указателей). Смотрим тесты, например здесь (взято у Ф. Пикуса ) quick-bench.com/q/42iKBatMiDjQtRHIcIWb3hLgbU8
Успехов!
Исправляюсь: gcc.godbolt.org/z/nhhK64drr
(спойлер: тоже все весьма достойно)
Исключительно добротный материал. Проработанная и качественная подача материала, отличное оформление статьи. Номинируйтесь на Технотекст 2021, с удовольствием проголосую.
В далеком уже 2010 г. на плюсах для AVR-ок(!) писали так:
Компилятор в компайл тайм сам рассчитал все битовые маски и логические значения, не оставив ничего лишнего на рантайм. Никаких динамических аллокаций, предельная детерминированность и нулевой оверхед. И это при возможностях языка и компиляторов 10-ти летней давности. Источник здесь.
Возможно этот простой пример подтолкнет Вас провести ревизию предубеждений касаемо обоснованности С++ во встроенных решениях.
Спасибо за внимание и комментарий!
Вы верно указали на пробелы в статье. Концепт ОС - ну совсем новорожденный. Торопился в публикации поделиться самой идеей "корутины + примитивы синхронизации с универсальным интерфейсом на базе co_await + переключение контекста". Вопросы сравнения с существующими ОС интересуют не меньше вашего, обязательно потестирую, главное чтобы работа оставила время...
Спасиибо за внимание к моей статье и поддержку)
Спасибо за внимание к моей статье и комментарий.
Действительно, писал статью по ощущением моряка на мачте: "Земля! Земля!"
Захватила сама идея: воспроизвести базовый функционал ОС на новейшем стандартном инструменте С++20 - корутинах. Ранее аналогичных материалов не встречал, торопился первым ступить на новые земли... Тщеславен немного, каюсь)
Оценка преимуществ моего подхода (и есть ли таковые по факту) - чуть позже или отдельным материалом, или дополнением к этой статье.
Спасибо за отзыв!
После планируемых тестов и доработок, послесловием к статье, добавлю более приближенный к реальному применению пример.
Теперь по существу вашего отзыва:
Так у меня ровно так и реализовано.
Бесспорно. Вот только основной посыл моей статьи был о том, как заменить именно интерфейс printf-а, используя возможности самого последнего, 20-го плюсового стандарта. И честно указал, что позаимствовал алгоритмы и код конвертации в строку. Можно ли переписать и улучшить заимствованный код с учетом эволюции камней? Весьма вероятно, просто не это основная тема конкретно этой статьи. Ссылку на вашую имплементацию обязательно посмотрю, поэкспериментирую. Резковато, конечно, но почему? Разве не удобно, напечатав два символа <<, быстро вывести в терминал фрагмент массива с «сырыми» данными любого числового типа? Или, использовав функционал views, прямо в операторе вывода сразу как-то отфильтровать их, выделить поддиапазон etc.? У меня за 9 мкс выводится не одно значение, а пример суммарно с 8 значениями разных типов, 2 строковых литерала с операциями выделения поддиапазона и реверса. Вы воспроизвели эти же условия?
Ну и еще раз подчеркну, цель у меня была понять, что могут дать современные плюсы с 20-м стандартом в задаче замены интерфейса printf-a. Насколько универсальным, лаконичным, эффективным и эффектным может выглядеть решение. На мой взгляд, чуть менее 180 строк кода, чтобы получить вполне функциональный аналог стандартного stream-а для embbed-a, это неплохо.