Наихудшие практики встроенных систем?

Что вы считаете «наихудшим» подходом при разработке встраиваемой системы?

Вот некоторые из моих представлений о том, чего не следует делать:

  • Избегайте абстрагирования аппаратного уровня, вместо этого распределяйте доступ к аппаратным средствам по всему коду.
  • Отсутствие какой-либо среды эмуляции, наличие только фактического оборудования для exe / cute.
  • Избегайте модульных тестов, возможно, из-за двух вышеупомянутых моментов
  • Не разрабатывать систему в многоуровневой структуре, так что более высокие уровни могут зависеть от отлаженной и работающей функциональности нижних уровней.
  • Выбор оборудования без учета программного обеспечения и инструментов, которые будут его использовать
  • Использование оборудования, предназначенного для легкой отладки, например нет контрольных точек, нет индикаторов отладки, нет JTAG и т. д.

    Я уверен, что есть много хороших идей о том, чего не следует делать, давайте их послушаем!

  • Стоит ли изучать PHP в 2026-2027 годах?
    Стоит ли изучать PHP в 2026-2027 годах?
    Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
    Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
    Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
    В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
    Приемы CSS-макетирования - floats и Flexbox
    Приемы CSS-макетирования - floats и Flexbox
    Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
    Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
    В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
    Концепция локализации и ее применение в приложениях React ⚡️
    Концепция локализации и ее применение в приложениях React ⚡️
    Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
    Пользовательский скаляр GraphQL
    Пользовательский скаляр GraphQL
    Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
    41
    0
    4 444
    21

    Ответы 21

    Распределение динамической памяти после инициализации. После запуска системы пул памяти должен оставаться статическим.

    Хороший ответ, а как насчет случаев, когда система должна обрабатывать входные данные переменной длины, например У меня была система, которая принимала конфигурацию XML. из браузера результирующая структура данных может быть маленькой или довольно большой. Как лучше всего справиться с таким делом?

    Fred Basset 30.10.2008 22:41

    Зависит от размера и временных ограничений системы. На более высоком уровне встроенного мира разумно динамическое распределение.

    Steve Fallows 30.10.2008 23:02

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

    jholl 03.11.2008 21:06

    Хорошим подходом может быть создание распределителя LIFO или двойного LIFO (один LIFO выделяет снизу вверх, а независимый - сверху вниз). Если время жизни выделяемых объектов соответствует шаблону двойного LIFO, это может быть намного чище, чем использование malloc / free.

    supercat 08.01.2013 04:41

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

    Эй, Билл Гейтс основал свою империю на разработке базового интерпретатора для машины, к которой у него никогда не было доступа (по легенде, он сработал в первый раз, когда был фактически загружен в цель, Altair 8800). Вот для чего нужны эмуляторы!

    Tim Ring 31.10.2008 12:40

    @ Тим: Моим личным фаворитом был друг, который разрабатывал систему для клиента, не имея доступа к системе, кроме отправки кода клиента по электронной почте и получения результатов. Он сказал, что многому научился, но больше не будет этого делать.

    tloach 31.10.2008 21:51

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

    Craig McQueen 23.07.2009 06:25

    @Craig McQueen: Независимая от платформы эмуляция может позволить проделать долгий путь без оборудования. К сожалению, затем можно обнаружить, что временное поведение реального оборудования в значительной степени отличается от эмулятора, что потребует серьезной доработки.

    supercat 02.02.2011 08:36

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

    Предположим, что порядок байтов всегда будет неизменным.

    (Расширьте его до размера регистров и всего, что касается технических характеристик оборудования)

    (Пояснение кейса в комментариях).

    Однажды мне пришлось перенести приложение с Verifone POS, в котором использовался прямой порядок байтов, на более новую версию с прямым порядком байтов. Это была не единственная ошибка в предыдущем коде, но она была наименее очевидной.

    Null303 30.10.2008 22:47
    • Экономия на лесозаготовительной установке. Встроенные системы сложно отлаживать, и вам нужно много журналов.
    • Отсутствие возможности разрешать уровни ведения журнала. Одна из многих систем будет демонстрировать странное поведение, и вам необходимо установить более подробный уровень отладки журналирования этой системы.
    • Запрещение какого-либо выходного порта для входа в систему, например. приставка.
    • Отсутствие возможности «пройтись по коду».
    • Отсутствие возможности профилировать код, чтобы вы могли видеть, какие биты необходимо оптимизировать, например. на ассемблере.
    • Не разрабатывает какой-то «тест на работоспособность», чтобы вы могли быстро проверить работоспособность устройства после загрузки и перед отправкой.
    • Основа дизайна на какой-то "самодельной" ОС

    Без более подробного определения «встроенного программирования» невозможно сказать, какая практика является хорошей, а что плохой.

    Многие из техник, которые вы можете использовать для программирования 8-битного микроконтроллера на изворотливом нестандартном диалекте «C», были бы совершенно неуместными, например, на платформе CE или XPe.

    Абстракция - это (чрезмерно) дорогая роскошь во многих случаях, поэтому «избегать ее» может быть лучше, чем плохо.

    Хороший замечание, но иногда мне интересно, действительно ли CE «встроен» по сравнению с некоторыми из устройств, которые я использовал? Это действительно «Роллс-Ройс» среди встраиваемых систем.

    rbrayb 30.10.2008 23:01

    Вот несколько:

    • Не создавайте легко объяснимую архитектуру, понятную как разработчикам, так и менеджерам и клиентам.

    • Встроенная система почти всегда чувствительна к затратам. Не планируйте, что HW станет медленнее (дешевле), и не планируйте новые функции на критическом пути к данным.

    • Большинство встраиваемых систем являются «безголовыми» (без клавиатуры, мыши или других HID). Не планируйте в своем расписании написание средств отладки. И не привлекайте хотя бы одного разработчика для их обслуживания.

    • Обязательно недооценивайте, сколько времени потребуется, чтобы получить подсказку. Вот сколько времени нужно, чтобы довести основной процессор до точки, в которой он сможет разговаривать с вами, а вы с ним.

    • Всегда предполагайте, что подсистемы HW работают «из коробки», такие как память, часы и питание.

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

    Quibblesome 26.01.2010 21:42
    • Неинициализированные векторы исключений (вы знаете, для тех, которые "никогда не будут достигнуты")
    • Скажите это вместе со мной: глобальные переменные. Особенно те, которые используются ISR и задачами (или циклами переднего плана) без защиты.
    • Отказ от использования «летучих» там, где это необходимо.
    • Имея подпрограммы, которые DisableInterrupts () и затем EnableInterrupts () объединены в пару. Понял? Не RestoreInterrupts (), а ВКЛЮЧИТЬ. Ага, вложение.
    • Нет GPIO для переключения при тестировании.
    • На борту нет контрольных точек.
    • Нет светодиодов или последовательного порта для просмотра состояния системы во время выполнения.
    • Нет измерения того, насколько занят / простаивает ЦП.
    • Использование встроенной сборки для всех, кроме самых ужасных случаев. Напишите быстрое уточнение.
    • Использование for (i = 0; i <1000; i ++) {} для "немного задержки". Да, это не укусит тебя сотнями разных способов ....
    • Не использовать const везде, где можно сохранить оперативную память и сократить время загрузки (без копирования / инициализации переменных)

    У меня есть еще тонна, но это должно помочь нам начать ....

    Хороший список. Я бы поставил тебе +2, если бы мог.

    Robert 31.10.2008 17:24

    Я бы поставил этому +100, если бы мог. Передаю это другим коллегам.

    Renan 21.02.2013 18:03

    ОК, раунд 2 .... еще несколько:

    • Не используйте сторожевой таймер (особенно встроенный!)

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

    • Используйте RTOS, когда это не требуется

    • Не используйте RTOS, если В самом деле имеет смысл

    • Никогда не смотрите на сгенерированный код сборки, чтобы понять, что происходит под капотом.

    • Напишите прошивку, чтобы ее нельзя было обновить в полевых условиях

    • Не документируйте свои предположения

    • Если вы видите что-то странное во время тестирования / отладки, просто игнорируйте это, пока это не повторится снова; вероятно, это не было чем-то важным, например, отключением питания, пропущенным прерыванием, признаком повреждения стека или какой-либо другой мимолетной и периодической проблемой

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

    • Не пользуйтесь инструментами профилирования во время выполнения, такими как Micrium uC / Probe (я уверен, что есть и другие).

    • Не включайте самотестирование оборудования при включении питания перед запуском основного приложения - эй, загрузочный код запущен, что может не работать?

    • Определенно не включайте тест RAM в POST (см. Выше), который вы не собираетесь реализовывать.

    • Если у целевого процессора есть MMU, при всей святости, не используйте этот страшный MMU !!! Особенно не позволяйте ему защищать вас от записи в пространство кода, выполнения из пространства данных и т. д.

    • Если вы проводили тестирование, отладку и интеграцию с определенным набором параметров компилятора (например, без оптимизации / с низкой оптимизацией), ОБЯЗАТЕЛЬНО ВКЛЮЧИТЕ ПОЛНУЮ ОПТИМИЗАЦИЮ перед сборкой финального релиза !!! Но включайте оптимизацию только в том случае, если вы не собираетесь тестировать. Я имею в виду, что вы уже тестировали несколько месяцев - что может пойти не так?! ??!

    Кто-нибудь остановит меня, пока я не поранился.

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

    • При составлении графика исходите из предположения, что с первого раза все получится.

    • Подводка к доске без осциллоскопа и / или логического анализатора. Esp. прицел, это бесполезно.

    • Не учитывайте источник питания при проектировании. Такие вопросы, как нагрев, эффективность, влияние пульсаций на показания АЦП и поведение системы, электромагнитное излучение, время запуска и т. д. Не важны.

    • Что бы вы ни делали, не используйте контроллер сброса (тип 5-центового IC), просто используйте RC-цепь (надеюсь, с большим количеством высокочастотных шумов переменного тока, связанных с ней)

    • ПРИСОЕДИНЯЙТЕСЬ К БОЛЬШОМУ взрыву !!! Не создавай маленькие кусочки постепенно и часто интегрируй, глупый дурак !!! Просто пишите код в течение нескольких месяцев вместе с коллегами по работе, а затем сложите все вместе в ночь перед большой демонстрацией выставки!

    • Не используйте в коде инструкции отладки / трассировки. Видимость плохая.

    • Делайте много вещей в ваших ISR. Сортировка пузырей, запросы к базе данных и т. д. Эй, скорее всего, никто тебя не прервет, тебе слово, наслаждайся, приятель !!!

    • Игнорируйте макет платы в дизайне. Пусть автотрассировщик отправится в город по этим согласованным кривым импеданса и этому сильноточному высокочастотному источнику питания. Эй, у тебя есть дела поважнее, партнер !!!

    • Используйте новые, бета-версии, неизданные кремниевые компоненты, которые раньше начали применять, особенно если они критичны с точки зрения безопасности (авиация, медицина) или используются в больших объемах (интересно отозвать 1 миллион единиц). зачем ехать в Лас-Вегас, когда есть новые образцы кремния на этом 4-ядерном 7-ступенчатом конвейерном чипе с частотой 300 МГц?

    Я уверен, что найду это забавным, как только воспоминания, которые я подавлял, утихнут и я перестану дергаться. +1 за дни "психического здоровья" надо взять .... :-)

    Adam Liss 12.11.2008 06:49
    • Напишите свой модуль FW так, чтобы он был полностью универсальным, принимающим все возможные параметры в качестве переменных, даже если уровень выше вас вызовет всегда с теми же параметрами.

    • Используйте memcpy везде в коде, даже если у вас есть движок DMA в системе (зачем беспокоить HW).

    • Разработайте сложную многоуровневую архитектуру FW, а затем получите доступ модуля непосредственно к глобальным переменным, принадлежащим модулям более высокого уровня.

    • Выберите ОСРВ, но не пытайтесь проверить ее реальную производительность (разве мы не можем доверять цифрам, предоставленным поставщиком?)

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

    Да, я программировал эту архитектуру раньше.

    Если я правильно помню, OMAP5912 от TI объединил в одном устройстве процессор ARM с прямым порядком байтов и DSP с прямым порядком байтов c55, взаимодействуя через общую память. Как и во всем инженерном деле, сложность, которую это внесло, была частью компромисса с преимуществами использования этих проверенных технологий.

    Jeremy 04.08.2017 11:47

    Printf.

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

    Записать в буфер памяти (бонусные баллы для перечислений memcpy'ing вместо s (n) printf) и прочитать его в другой раз.

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

    Не делайте этого:

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

    • Будьте незнакомы со спецификой используемого вами процессора, особенно если вы пишете какие-либо низкоуровневые драйверы.

    • Выберите версию семейства процессоров с наименьшим объемом флэш-памяти на том основании, что вы всегда можете «обновить позже», если только затраты не сделают это неизбежным.

    Это не только для встроенных систем, но и тратить все это время на поиск ошибок (отладку) вместо того, чтобы избегать ошибок с помощью таких интересных вещей, как, например, Проверка кода - определенно одна из наиболее часто применяемых худших практик.

    Другой - позволить одному огромному процессору делать всю работу вместо того, чтобы разбивать проблему на мелкие, например. с большим количеством процессоров. Помните КОКОМО?

    Это во многом зависит от типа контроллера, для которого вы программируете. Иногда стоимость является самым важным, и вы пытаетесь обойтись как можно меньше. Я обычно в такой лодке. Вот несколько худших приемов, которые я использовал:

    • Не сосредотачивайтесь на улучшении своих процессов. В следующий раз постарайся немного усерднее. Позже, когда мы не будем спешно выпускать новые продукты и поддерживать все эти ошибки в полевых условиях, мы можем беспокоиться об этом.
    • Избегайте разработки инженерного инструмента, который упростит вашу жизнь, и если вы его создадите, не позволяйте ему отправлять недопустимые входные данные на устройство.
    • Не сомневайтесь в оптимизации. Это магия. Компилятор знает, что делает. Ошибка компилятора никогда не возникнет, особенно для 7-битного субмикроконтроллера PIC вашего клиента. Слишком много людей заметят, верно?
    • Делите и умножайте, как будто вы запускаете физический движок, не беспокойтесь о переполнении, потере точности или округлении до нуля.
    • Если кажется, что ваше время работает, не проверяйте, отстаетесь ли вы на 1 или дрейфуете ли вы со временем. Вы играли на ударных в старшей школе, вы бы заметили разницу между 7200000 тактов и 7200001.
    • Положитесь на тестирование на уровне системы от группы, которая ничего не знает о вашей прошивке.
    • Работайте на как можно большем количестве различных устройств. Проведите несколько сеансов отладчика в разных средах разработки. Работайте над разработкой одного продукта, одновременно тестируя другой продукт и пытаясь воспроизвести проблему в полевых условиях на третьем.
    • Выпустите новую версию кода в спешке, потому что вы изменили только одну вещь и, вероятно, не сломали ее. Производственная линия остановлена, мы не можем терять время!
    • Не нужно никаких тестов, чтобы предупредить вас, если оптимизация отключена. Наверное, не так? Новая версия IDE, которую вы только что установили, не могла нарушить этот параметр.
    • Напишите код достаточно хорошо, чтобы он работал. Потратьте 75% времени на то, чтобы сделать это на полпути.
    • Не принимайте участия в разработке функций. Разрешите любой функции собирать информацию о состоянии за несколько дней. Нет возможности ввести эту информацию о состоянии для теста. Это даст вам свободное время, когда вы попытаетесь воспроизвести ошибки, которые люди видели в полевых условиях, а производственные специалисты тоже оценят свое свободное время.

    С точки зрения программного обеспечения, не тратить время на изучение оборудования.

    Несколько дополнительных запретов:

    • Оставьте разработку и тестирование компонентов, зависящих от оборудования, до самого конца, только чтобы обнаружить, что оборудование не работает, работает не так, как ожидалось или имеет некоторые недостатки, которые нельзя исправить с помощью программного обеспечения (например, нежелательные нелинейные искажения, которые прерываем всю дальнейшую обработку сигнала).
    • Простое проектирование аналогово-цифровых схем, не задумываясь о том, как события, происходящие в цифровой части, могут и могут повлиять на аналоговую часть (например, перекрестные помехи, приводящие к неверному считыванию данных с АЦП).
    • Предположим, что микроконтроллер делает то, что указано в листе данных, что он делает / не делает то, что обещано в листе данных.
    • Поместите служебную программу сторожевого таймера в высокоприоритетное синхронизированное прерывание, чтобы, что бы ни случилось, сторожевой таймер никогда не отказал.
    • Используйте любой код, который есть в Интернете, особенно если он взят с сайта Arduino / Pic.
    • Предположим, что существует какое-либо стандартное определение чего-либо, от одного компонента к другому, например Tx / Rx (у нас есть устройство Sony с 2 портами связи на нем, у одного Tx / Rx перевернуты относительно другого).
    • Подумайте, что покупатель потрудится проверить / протестировать что-либо, пока не продаст как минимум 100 единиц.
    • Предположим, что любые другие игроки в этой области действительно знают, что они делают (у нас есть стандарт, в котором говорится: «мы думаем, что это то, что делал наш старый протокол, но на самом деле никто об этом не помнит»)

    Некоторые из наихудших практик из моего опыта работы со встроенными системами более 8 лет и обучения встроенным системам:

    1. Выбор типа данных - Встроенные системы ограничены в ресурсах. Если данные будут находиться в диапазоне от 5 до 200, нет смысла объявлять их как int. Требуется только 8 бит, тогда как используется 32 бита. Пустая трата 24 бита.

    Неправильные типы данных также могут иметь катастрофические последствия.

    1. Много работы в ISR - ISR должны быть как можно короче. Некоторые люди, которых я видел, реализуют всю логику в ISR, что очень-очень плохо. Настолько плохо, что это должно быть квалифицировано как преступление. Вместо этого используйте флаги

    2. Использование целых чисел в качестве флагов - это больше похоже на расширение пункта 1. Вам нужен только один бит. Не используйте для этого 16 или 32 бита.

    3. Но худшее из всего, что я видел, - это обдумывание алгоритма снова и снова, чтобы получить лучший и самый совершенный подход. Стоп!! Помните о передовых методах и в первую очередь заставьте систему работать.

    Есть еще много всего. Можно Прочтите некоторые из них здесь

    Другие вопросы по теме