• /
  • /

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

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

Что такое встроенные системы?

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

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

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

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

3. Разработчики встраиваемых систем – это инженеры-схемотехники и инженеры-программисты, отвечающие за непосредственное проектирование печатных плат и написание программного кода.

4. QA-специалисты отвечают за тестирование разрабатываемых решений.

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

Проектирование встроенных систем: разработка аппаратного обеспечения

1. Сбор требований и техническое задание

Поскольку КЕДР Solutions специализируется на контрактной разработке встраиваемой электроники, идеи новых продуктов обычно принадлежат нашим заказчикам. Когда команда присоединяется к проекту, наша первая задача – собрать требования к будущему устройству:

  • Функциональные требования (что должна делать система);

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

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

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

На основе этой информации команда КЕДР Solutions формирует техническое задание на разработку проекта – документ, описывающий назначение, функции, поведение и другие требования к будущему устройству.

2. Техническое предложение

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

Мы также подбираем компоненты для будущей печатной платы. Выбор здесь ограничен требованиями к продукту:

  • Технические характеристики: энергопотребление, объем памяти, производительность микроконтроллера, размер, вес и т.д.
  • Условия эксплуатации: экстремальные температуры, влажность, вибрационные нагрузки и т.п.
  • Стоимость и качество компонентов.
  • Доступность компонентов на рынке (если заказчик предполагает выпускать устройство серийно).

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

3. Дизайн и компоновка печатной платы

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

  • Работа должна вестись в полном соответствии с правилами проектирования печатных плат, чтобы устройство прослужило как можно дольше и без проблем.
  • Должное внимание необходимо уделять тепловому режиму платы – особенно при проектировании мощного устройства. Достаточного отведения тепла можно добиться за счет правильного размещения компонентов, увеличения площади меди, добавления переходных отверстий, использования радиаторов и других способов.
  • Работая с каким-либо компонентом впервые, сперва мы его тестируем, чтобы убедиться, что тот работает так, как указано в спецификациях.
  • Печатные платы должны быть защищены от электростатических разрядов, электромагнитных помех, неблагоприятных условий окружающей среды и других факторов.
  • Если заказчик планирует выпускать продукт серийно, разработка должна вестись с учетом требований производства (по принципам DFM).
  • Плата должна быть спроектирована с учетом требований сертификации (если клиент планирует сертифицировать продукт).

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

Прототипирование может потребовать создания не только печатных плат, но и других элементов системы. Так, в рамках одного из проектов мы разрабатывали алгоритм компьютерного зрения, который должен был управлять роботом-манипулятором. Заказанная нами модель не соответствовала размерам, которые предоставил заказчик: она оказалась слишком короткой. Поэтому команде пришлось удлинить руку с помощью металлической профильной трубы и деталей для соединения, напечатанных на 3D-принтере. Это позволило протестировать алгоритм.
Прототип робота-манипулятора, изготовленный из металлической профильной трубы и деталей для соединения, напечатанных на 3D-принтере.

4. Тестирование

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

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

Что такое встроенное программное обеспечение?

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

Такие программы встроены в устройства и предназначены для управления ими и/или выполнения ограниченного набора функций. Часто встроенное программное обеспечение не предполагается удалять с устройства, хотя в наши дни его можно обновлять через беспроводное соединение (OTA-обновления, или обновления по воздуху). Встраиваемое ПО хранится в энергонезависимой памяти – ПЗУ, EEPROM или флеш-памяти. Без него устройство не будет работать и превратится в кусок металла и пластика.

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

Задача встроенного ПО – управлять устройством за счет передачи данных между железом и высокоуровневыми программами.

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

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

Встроенное системы могут иметь до четырех уровней встроенного программного обеспечения:
Структура встроенного программного обеспечения.
Прошивка (firmware)

Прошивка – это тип компьютерной программы, которая запускает аппаратное обеспечение и предоставляет ему низкоуровневые инструкции. Операционные системы и приложения работают поверх прошивки. Такое ПО пишется на языках низкого уровня (обычно на C/C++). Чтобы устройство могло прочитать и выполнить такой код, он затем преобразуется в машинный код.

Встроенная операционная система

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

Связующее ПО (middleware)

В некоторых случаях проектирование встроенных систем предполагает создание связующего ПО, которое располагается по уровню между ОС и приложениями. Типичными примерами такого ПО являются виртуальные машины. Виртуальная машина эмулирует платформу и выполняет компьютерно-независимый код, благодаря чему тот становится совместимым с различными операционными системами. Например, программы, написанные на Kotlin, преобразуются в код Java (уровень приложения), который, в свою очередь, выполняется на виртуальной машине (уровень связующего ПО), работающей в операционной системе (уровень ОС).

Встроенное приложение

Как и приложения для компьютеров, этот тип ПО выполняет функции встроенной системы и напрямую взаимодействует с пользователями. Он обрабатывает данные, взаимодействует с другими устройствами и выполняет высокоуровневые функции. Встроенное прикладное ПО пишется на языках высокого уровня, таких как C++, Python и Java.

Встроенная система может иметь только прошивку или несколько уровней встраиваемого программного обеспечения. Кроме того, для правильной работы решения может потребоваться разработка настольного или мобильного приложения. Для вашего проекта мы можем создать любые типы программ. Напишите нам, чтобы подробно обсудить проект.

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

Инструменты разработки встраиваемого программного обеспечения

Разработчики используют следующие инструменты для создания программного обеспечения встраиваемых систем:

  • IDE (интегрированные среды разработки) – это наборы инструментов, которые содержат различные средства программирования: редакторы, компиляторы, отладчики и т.д.
  • Компиляторы и кросс-компиляторы переводят код, написанный на языке высокого уровня, в машинный код.
  • Отладчики помогают разработчикам находить и устранять баги.
  • Линкеры, или компоновщики, могут объединять различные фрагменты кода и модули в одну исполняемую программу. Современные компиляторы имеют встроенные линкеры.
  • Симуляторы и эмуляторы позволяют создавать виртуальные среды, приближенные к реальным условиям, для тестирования программ.
  • Средства конфигурации системы и генерации кода автоматически генерируют код для настройки аппаратных компонентов устройства. Они сводят к минимуму рутинную работу и, как следствие, сокращают вероятность ошибок.
  • Средства автозаполнения кода – это инструменты на основе искусственного интеллекта, которые анализируют написанный программистом код и автоматически дополняют его контекстуально релевантными фрагментами. Эти инструменты значительно ускоряют разработку программного обеспечения для встраиваемых систем.
  • Дизассемблеры используются для выявления ошибок, допущенных компиляторами. Иногда проще устранить ошибки на уровне ассемблера.

Сложности разработки встраиваемого программного обеспечения

1. Выбор аппаратных средств

Структуру и особенности будущего встроенного ПО команда может оценить на этапе подготовки технического предложения: опыт позволяет видеть, какие ресурсы могут предоставить выбранные аппаратные средства.

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

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

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

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

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

2. Выбор языка программирования и операционной системы

Выбор языка программирования определяется тем, какое аппаратное обеспечение мы собираемся использовать и какой тип ПО мы хотим создать. Например, программы для устройств на базе Android создаются на Java, а программное обеспечение для одноплатных компьютеров – на C или C++. Язык C подходит для низкоуровневого программирования, т.е. для программ, которые напрямую взаимодействуют с железом. C++, Python, Java, Rust и другие языки подходят для высокоуровневого программирования.

Специализация КЕДР Solutions – разработка на C/C++. Программист с опытом работы на C++ может с помощью фреймворка Qt создавать как встраиваемое программное обеспечение, так и прикладное ПО. Хотя существуют более безопасные альтернативы C/C++ (например, язык Rust), наша команда обладает достаточной квалификацией, чтобы не допускать ошибок при работе на C/C++. Таким образом, доверяя нам свой проект, вы экономите деньги, поскольку нам не нужно нанимать больше разработчиков, специализирующихся на разных языках.

Устройства с простыми функциями могут работать на так называемой bare-metal прошивке, которая не требует операционной системы. Однако при проектировании встроенных систем со сложными функциями необходимо использовать ОС.

Разработчикам доступны разные встроенные ОС: Embedded Linux, Android, Windows IoT, RTEMS и др. Выбор определяется несколькими факторами:

  • Целью проекта;
  • Доступными аппаратными ресурсами;
  • Стоимостью разработки.

Мощные аппаратные средства могут поддерживать требовательные к ресурсам операционные системы. Например, написание ПО для Ubuntu не займет много времени, но потребует мощного и дорогого железа, поскольку в Ubuntu множество сервисов, драйверов и пакетов. Разработка под слабое железо потребует больше времени на оптимизацию кода, а значит, обойдется дороже.
Схема, показывающая зависимость между стоимостью разработки встроенного ПО и доступными аппаратными ресурсами.
Мы предпочитаем свободно распространяемые операционные системы, потому что создавать ПО для них проще и дешевле. Но если проект того требует, можем создавать программы и для проприетарных ОС.

3. Архитектура встраиваемого программного обеспечения

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

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

Часто разрабатываемое встроенное решение является лишь частью более крупной системы. Проект также может потребовать разработки программного обеспечения прикладного уровня, которое будет каким-то образом взаимодействовать с устройством. Теоретически команда может сначала разработать встроенное ПО и лишь затем перейти к другим задачам. Но чтобы ускорить процесс, мы начинаем со спецификации внешних интерфейсов ПО, чтобы другие команды могли приступить к работе как можно скорее. Это обычная практика в embedded-разработке.

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

4. Написание кода

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

  • Недостаток информации

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

Так, в рамках одного из наших проектов разрабатываемое решение должно было отправлять команды на компьютеры MacBook через USB-порт. Команды представлены наборами битов, но в официальных документах Apple нет никакой информации по этому поводу. Так что команде пришлось искать сведения на разных форумах.
Наборы битов, представляющие собой команды «Перезагрузка» и «Переключение на DFU» для MacBook.
Эти наборы битов представляют собой команды «Перезагрузка» и «Переход в режим DFU».
  • Безопасность данных

Многие встроенные устройства имеют выход в Интернет. Если они передают конфиденциальные данные, соединение должно быть безопасным. Для этого используются стандартные методы шифрования. Например, сейчас команда КЕДР Solutions работает над медицинским устройством, передающим биометрические данные через Интернет. Такие данные должны быть защищены. Однако шифрование повышает требования к оборудованию, поэтому когда данные не содержат конфиденциальной информации, шифрование не применяется.

  • Ограниченность памяти и производительности

Встраиваемые устройства становятся все меньше, а требования к их производительности растут. Хотя в настоящее время нехватка памяти не так критична, как раньше, она остается одной из основных проблем при разработке встраиваемого ПО.

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

  • Стабильность

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

Вот типичный пример. Процесс 1 вычисляет переменную и помещает значение в ячейку памяти. Это значение требуется для Процесса 2. Поскольку два процесса выполняются параллельно, Процесс 2 может забрать значение из ячейки памяти до того, как Процесс 1 его вычислит, что приводит к сбою.

При написании кода разработчики должны предусмотреть такие ситуации и дать процессам соответствующие инструкции – например, поручить Процессу 2 сперва опрашивать Процесс 1 и забирать значение, только если оно рассчитано.

  • Новые требования

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

  • Оптимизация

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

5. Тестирование встроенного ПО и отладка

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

Например, при работе над системой безопасной буксировки самолетов команде нужно было как-то испытать модуль, измеряющий дистанцию до препятствий. Наш тестировщик спроектировал и изготовил на 3D-принтере специальный стенд. Модуль крепился к стойке, а сама стойка с помощью магнита крепилась к капоту автомобиля.
3D-модель испытательного стенда с прикрепленным к нему встроенным устройством.
Чтобы протестировать модуль, команда долгое время каталась по парковке.

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

В этом случае клиент может установить TeamViewer или аналогичное решение на компьютер, а затем подключить ПК к камере и тестируемому устройству. Таким образом, команда может, подключившись к ПК, передавать команды на устройство и видеть, что происходит через камеру.

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

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

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

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

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

Заключение

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

КЕДР Solutions – это сплоченная команда с богатым опытом embedded-разработки. Мы знаем, каких сложностей ожидать на каждом этапе и как с ними справляться. Обратитесь к нам, если вам нужна консультация по поводу идеи нового продукта.
Другие статьи