LINUX.ORG.RU

На чем все таки надо писать Embedded?

 , , ,


2

4

Относительно недавно начал работать программистом для встройки (stm32f0-f1-f3). Раньше делал только домашние проекты на сишке, потому что все книги и гайды пишут на сишке и я подумал что это идет как стандарт для встройки. Когда шел на работу, думал: «Ух, сейчас на сях попишу». Оказалось, что там пишут на плюсах, стиль там скорее как «си с классами», но потихоньку двигаются в сторону плюсовых подходов (например, хотим концепты затащить). Вот хотел бы выслушать людей с многолетним опытом, какие-то аргументы за C или С++ в embedded, потому что все что услышал тут: «Ну, не надо передавать ссылку на self в функции для работы со структурами».

★★★
Ответ на: комментарий от alysnix

это всё можно держать в голове. Конечно зачем, когда есть языки, которые это всё делают - не понятно, но всё это можно написать вручную. Да и нет в этом всё ничего строго-необходимо. просто пишешь обёртку создания объекта, которая вызывает и аллокатор, вот тебе и конструктор. Обычно ты заранее знаешь будет ли этот объект аллоцироваться или нет. Забыл вызвать деструктор - сам виноват. В c++ же пустой деструктор бы сам сгенерировался и вызывался бы всегда, так что когда объекту понадобилось бы добавить что-то в деструктор - вызовы бы уже были на месте, в си же можно что-то забыть и допустить утечку ресурса
Из фич именно языка пожалуй можно тут назвать только запекание конструкторов в init array так, что оно при загрузке модуля будет вызываться неявно. На embedded это не сильно релевантно в принципе, а большинство тулчейнов имеют способ сделать это и в си

mittorn ★★★★★
()
Ответ на: комментарий от alysnix

команда, что пишет на плюсах обгонит команду, что пишет на си и захватит рынок. потратит меньше времени, денег, и людей на разработку. пока вторая команда будет мусолить один проект, первая выпустит два. вот и вся калькуляция.

Надо писать на JS, истинно говорю!

pihter ★★★★★
()
Ответ на: комментарий от mittorn

Есть такой подход на Си, писать со счетчиком ссылок. ref/unref. Подход вполне стандартный, сложностей не вызывает. И деструктор вызвать забыть не получится. Если ты захватил объект, делаешь реф, когда закончил – анреф. Ничего сложного. Деструктор сам позовется, когда счетчик ссылок достигнет нуля. Я не знаю, как можно забыть сделать анреф. Если только специально.

hibou ★★★★★
()
Ответ на: комментарий от alysnix

ну то, что выходов из функции не должно быть слишком много, это понятно. Иначе сам запутаешься. Но это, мне кажется, и так хорошая рекомендация, для любого языка.

hibou ★★★★★
()
Ответ на: комментарий от hibou

Ранний выход из функции при несоблюдении условий - это важнейший метод обеспечения читаемости и понятности кода. Иначе нужно городить кучу goto в конец функции, где вызываются деструкторы, и ни в коем случае не перепутать при переходе метку, чтобы не освободить то, что еще не выделили.

annulen ★★★★★
()
Ответ на: комментарий от hibou

в плюсах конструкторы/деструкторы вызывают их у предка, а также всех полей в структуре у которых они есть, порядке декларации.

а в си чтобы это эмулировать, нужно и кода кучу написать, и порядок не перепутать.

опять же если есть виртуальные методы, конструктор/деструктор ставит сначала свою вируальную таблицу, чтобы не вызвать виртуальные методы потомка(ибо это некорректно).

ну вот и делай все это ручками.

alysnix ★★★
()
Ответ на: комментарий от hibou

Есть такой подход на Си, писать со счетчиком ссылок. ref/unref.

Это вообще о другом. Подсчет ссылок позволяет организовать совместное владение объектом (что нужно далеко не всегда), и вызов unref ничем по сути не отличается от вызова free() или функции-деструктора.

annulen ★★★★★
()
Ответ на: комментарий от slovazap

плюсах с шаблонами, прошивка ещё и становится меньше в разы.

далеко не всегда, шаблоны могут изрядно пожрать флеша (такова их природа). а вот быстрее - да, иногда даже банальный вывод в порт, работа с регистрами очень красиво оптимизируется (на хабре статейка была), плюс можно чудить полиморфизм без virtual/indirect call.

з.ы. пишем ембед только на плюсах, и все ок.

dib2 ★★★★★
()
Ответ на: комментарий от hibou

Я вангую обычно в таких применениях C++ используется без STL и с -fno-exceptions. Ибо первое действительно слишком жирное и универсальное, а второе убивает риалтайм, усложняет проверку корректности кода и тоже кушает флеш. В итоге на плюсах пишут в первую очередь саму бизнес логику, а плюсовые библиотеки либо не используют, либо используют специальные для embedded.

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 1)
Ответ на: комментарий от slovazap

Как начнешь понимать, сразу и поймешь. Но потом. «Скорее вбросить» — это вообще не про что-то нормальное. Это про «программные продукты»(ТМ), которые отличаются от программ, как «кефирные продукты» (ТМ) от кефира. Но ты кушай-кушай, тебе же нормально :)

slackwarrior ★★★★★
()
Ответ на: комментарий от hibou

Шаблоны, деструкторы. Шаблоны для эбдедеда вообще то что доктор прописал - конфигурировать какими ногами/интерфейсами пользоваться не через макропортянки. А ещё можно через constexpr делать всякие вычисления, которые не нужно делать на самом МК, таким образом уйдя от кодогенерации.

Банально какие-нибудь USB дескрипторы на шаблонах и constexpr описывать гораздо приятнее.

KivApple ★★★★★
()
Ответ на: комментарий от PPP328

Не вырождается, потому что даже при использовании сишных либ ТВОЙ код становится выразительнее по сравнению с Си. Больше вещей в твоём коде форсится компилятором, а не твоей памятью и внимательностью.

KivApple ★★★★★
()
Ответ на: комментарий от KivApple

Есть нюанс во всей этой теме, на который мы налетели когда даже не эмбед делали, а просто для Сбера терминалы - С++ и С код даже в месте пересечения совместимости нифига не совместим. Если у вас есть хэдеры для С для например STM32, то есть вероятность, что под С++ он либо не скомпилится либо будет работать не так как надо. С++ уже давно не надмножество С.

Я к тому, что хэдеров для эмбедных железяк под С много а под С++ мало.

P.S. У сбера был косяк в том что они написали extern C { … }, а внутри были С++ конструкции типа опускания слова struct, что С++ позволяет, а С нет.

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

когда придумывался си++, десктопы по мощности были приблизительно равны сегодняшним 32 битным микроконтроллерам. и уже тогда понимали, что на си много не напишешь, а мыслищи переполняли головы..

если б все рассуждали как вы, то плюсы и делать не стоило б.

alysnix ★★★
()
Ответ на: комментарий от slackwarrior

Но ты кушай-кушай, тебе же нормально :)

Ну если ты только в таком ключе способен вести диалог, то можно ответить разве что «пердолься дальше со своими адами, пока люди продукты делают» :))

slovazap ★★★★★
()

Использую оську на плюсах, библиотечку доступа к периферии на плюсах, чувствую себя отлично :-)

Пользуюсь только теми частями плюсов, которые не дают оверхеда и не тянут за собой динамического распределения памяти. Шаблоны, constexpr, атомики, array, варианты (с ограничениями), лямбды…

Beewek ★★★
()
Ответ на: комментарий от Beewek

А как используете шаблоны? Есть какие-то приемы, что позволяют избежать комбинаторного взрыва?

Ну и да, а за счет чего на STM работают атомики? Чисто интересно.

PPP328 ★★★★★
()
Последнее исправление: PPP328 (всего исправлений: 2)
Ответ на: комментарий от PPP328

Если у вас есть хэдеры для С для например STM32, то есть вероятность, что под С++ он либо не скомпилится либо будет работать не так как надо. С++ уже давно не надмножество С.

Если сишный хедер не компилится, то используют extern «C», и он компилируется по правилам C.

annulen ★★★★★
()
Ответ на: комментарий от annulen

Если сишный хедер не компилится, то используют extern «C», и он компилируется по правилам C.

Я уже привел пример когда большая компания не знает разницы между С и С++ и сует в extern C плюсовый код.

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

А как используете шаблоны? Есть какие-то приемы, что позволяют избежать комбинаторного взрыва?

Шаблоны использую в основном для настройки поведения классов, отделения уровней логики. Не представляю, откуда взяться комбинаторному взрыву. Просто не надо писать огромные шаблонные функции и потом инстанцировать их с кучей типов:)

Атомики для простых типов размером в слово работают элементарно - запись плюс барьер. Для более сложных - там LDREX/STREX, но я такие не использую.

Beewek ★★★
()
Ответ на: комментарий от sergej

ASM там не нужен от слова совсем, это же ARM ядро. Стартап файл на асме, да, но это какой-то пережиток полнейший, фиг знает зачем это делают.

Лучше всего, конечно, на C++ писать, потому что шаблоны (да и просто классы даже удобнее намного). Лично я смысла под них писать на C не вижу вообще.

James_Holden ★★★★
()
Ответ на: комментарий от James_Holden

Стартап файл на асме, да, но это какой-то пережиток полнейший, фиг знает зачем это делают.

Я не уверен, что на си/си++ можно как то заставить компилятор положить таблицу векторов в нулевой адрес.

snake266 ★★★
() автор топика
Последнее исправление: snake266 (всего исправлений: 1)
Ответ на: комментарий от snake266

Можно. Прямо на C++ даже. И за это, пожалуй, больше компоновщик отвечает. В коде надо только разметить секции, а дальше линковочный скрипт их развестит куда нужно.

James_Holden ★★★★
()

… какие-то аргументы за C или С++ в embedded?

  1. Моё твёрдое убеждение состоит в том, что прошивку микроконтроллера гораздо лучше напишет разработчик электронной аппаратуры ибо он узреет задачу шире изначально, подстрахуется где необходимо и допустит меньшей избыточности в целом.

  2. Если с детских лет подолгу сидеть возле телевизора или проводить время в мировой вычислительной сети вместо общения со сверстниками, то мышление человека оказывается неспособным к изобретательству, а годится лишь к переиспользованию где-либо увиденного. Проще говоря, старпёры, выросшие на книгах, мыслят стратегически и пишут свой код в стремлении к минимализму, а «цифровая» молодёжь изначально рыщет в поиске нужной библиотеки и втаскивает в код кучи стороннего кода.

  3. Какой подход предпочесть в итоге? Я бы смотрел как мыслит старший разработчик. Чтобы это понять нужно всего лишь узнать чем он занимается в свободное от работы время: сидит в «Инстаграмме», «В контакте» и «Твиттере» или читает книги и предпочитает общаться с людьми вживую.

Язык программирования тут вторичен.

Enthusiast ★★★
()
Ответ на: комментарий от alysnix

Хм, ладно, просто я знаю как можно задать сектор для таблицы векторов в асме, но ни разу не видел как задают сектор для переменных в C и C++, поэтому не знал что там так можно

@James_Holden

snake266 ★★★
() автор топика
Ответ на: комментарий от Enthusiast

Проще говоря, старпёры, выросшие на книгах, мыслят стратегически и пишут свой код в стремлении к минимализму, а «цифровая» молодёжь изначально рыщет в поиске нужной библиотеки и втаскивает в код кучи стороннего кода.

В крайности впадать тоже не нужно, но в целом люто плюсую.

Такая штука как ардуино и соответствующая культура ваяния г из г библиотек на г платформе в г IDE - лично мне вообще не понятна. Потому что профессионалы это не используют, а самодельщики - им же должно быть интересно сделать самому, по определению. А не воткнуть непонятное нечто.

James_Holden ★★★★
()
Ответ на: комментарий от snake266
uint32_t vectors[] __attribute__((section(".isr_vector"))) = {
    STACK_START,
    (uint32_t)Reset_Handler,
    (uint32_t)NMI_Handler,
    (uint32_t)HardFault_Handler,
    (uint32_t)MemManage_Handler,
    (uint32_t)BusFault_Handler,
    (uint32_t)UsageFault_Handler,
    0, // reserved
    .
    .
    .
};

Всего-то, магическое attribute

James_Holden ★★★★
()