Мы уже 10 лет проектируем электронику и по опыту знаем, что разработка встроенного ПО не менее важна, чем аппаратной части. И здесь команда постоянно сталкивается с серьезными ограничениями. Представьте: мощность чипов в сотни раз меньше, чем у смартфона, память измеряется килобайтами, функционал даже у портативных устройств становится все сложнее, а энергопотребление должно быть максимально экономным.
Под встроенным программным обеспечением в нашей индустрии понимают программы, разработанные для конкретных (встроенных) устройств. Например, к электронике, работающей на встроенном ПО, относятся:
- калькуляторы;
- фитнес-трекеры;
- стиральные машины;
- промышленное и медицинское оборудование.
Встроенное ПО также иногда называют прошивкой. Это не совсем корректно, но для простоты мы также будем использовать этот термин.
Далее поговорим о трудностях разработки встроенного ПО, с которыми мы сталкиваемся регулярно.
Обеспечение безопасности
Из всех уровней программного обеспечения (встроенное ПО, операционная система, приложение) именно встроенная программа запускается первой. Если получить доступ к этому коду, можно взломать устройство без особых сложностей. По этой причине требуется особое внимание к обеспечению безопасности. Кроме того, разрабатывая электронику, мы также должны позаботиться о защите интеллектуальных прав заказчика и не допустить, чтобы кто-то смог украсть код программы. Для этих целей мы чаще всего применяем шифрование.
Наглядный пример. В нашем проекте по разработке музыкальной педали для перелистывания нот реализовано обновление прошивки по беспроводной сети: новый файл передается по BLE (Bluetooth с низким энергопотреблением), и в этот момент его можно перехватить.
Педаль управляет разными приложениями для чтения нот. Наступаешь на кнопку – страница перелистывается вперед или назад.
Чтобы этого не произошло, наши разработчики использовали специальный инструмент, который шифрует пакеты обновления перед отправкой. Код в файле превращаются в непонятный набор символов. Без криптографического ключа (инструкции по дешифровки) его невозможно прочитать или восстановить в исходный вид.
Когда педаль принимает защищенный файл, он расшифровывается с помощью заранее “запакованного” в устройство ключа. Если ключ неверный, устройство не примет обновление. То есть ему нельзя подсунуть фальшивку. Кстати, случалось ли вам сталкиваться с попытками взлома встроенных систем или ваших личных (носимых) устройств? Поделитесь в комментариях.
В другом проекте по разработке системы управления аккумуляторами мы обеспечили два уровня защиты.
- На первом уровне сам образ встроенного ПО команда решила шифровать с помощью алгоритма AES-256. Если файл, который предполагалось передавать по электронной почте, попадет не в те руки, это будет набор бессмысленных символов.
- На втором, мы использовали цифровые подписи. Это криптографический механизм, который служит для подтверждения подлинности данных. При получении обновления устройство сравнивает подпись в файле и у себя. Если подпись не совпадает или вообще отсутствует, обновление не устанавливается. Таким образом, даже если кто-то взломает код шифрования, система все равно проигнорирует фальшивый файл прошивки.
Малый объем памяти
Многие встроенные устройства довольно малы, что накладывает ограничения на доступные разработчикам ресурсы – в частности на размер памяти. При этом требования к электронике с каждым годом все выше. Получается, нужно умещать в небольшом объеме памяти все более сложные функции.
Обычно мы стараемся оценить, сколько понадобится памяти и какие компоненты можно использовать, еще на этапе проработки архитектуры. Но зачастую уже в середине проекта требуется оптимизировать программу.
К примеру, в проекте по разработке графического калькулятора мы применили два способа для сокращения размер кода.
- Во встроенном ПО устройства использовались внутренний язык и интерпретатор ввода (он обрабатывает математические формулы). При этом в обоих компонентах применялся практически идентичный синтаксис. По сути, два фрагмента кода во многом повторяли друг друга. Так что мы перенесли уникальные функции из интерпретатора во встроенный язык и удалили интерпретатор. Сэкономили около 100 КБ на флеш-памяти микроконтроллера. Поверьте, в нашей работе это существенная экономия!
- Мы также решили заменить исходный тип данных на более “легкий”. Разные типы данных требуют разного объема памяти для хранения одних и тех же значений. Изначально у нас использовался double. Это 64-разрядное число двойной точности с плавающей точкой, которое позволяет точно хранить числа, содержащие до 15 цифр. Double обеспечивает большую точность, чем другие типы данных, но требует 8 байт. К тому времени стало ясно, что такая точность калькулятору не нужна, поэтому его заменили на float. Это 32-разрядное число одинарной точности с плавающей точкой, которое может точно хранить числа, содержащие только до шести цифр. Float требует всего 4 байта.
Энергоэффективность
Это особенно актуально при разработке портативных устройств, работающих от батарей. Чтобы микроконтроллер потреблял меньше энергии, приходится оптимизировать работу его ядра (главного вычислительного модуля) и периферии (аналого-цифровых преобразователей, таймеров, последовательных интерфейсов и тому подобного).
Чтобы снизить энергопотребление ядра, нужно сократить число выполняемых им операций. В проекте с графическим калькулятором мы применили два очевидных способа.
- Во-первых, снизили число операций за счет банальной оптимизации кода. Для этого обычно оптимизируют использование регистров, применяют алгоритмы с меньшей вычислительной сложностью и так далее.
- Во-вторых, применили деактивацию ядра в периоды бездействия. Ядро находится в спящем режиме и “просыпается” только 30 раз в секунду, чтобы опросить кнопки калькулятора. Если нажатий не обнаруживается, то ядро снова “засыпает”, не тратя энергию. И только если будет обнаружено нажатие, оно начнет выполнять инструкции.
В результате в режиме активного ожидания микроконтроллер калькулятора потребляет около 80 мА, а в спящем режиме – всего порядка 5 мА.
Тот же подход применяется и к периферии. Так, работая над устройством отслеживания персонала и имущества в шахтах, мы столкнулись с проблемой. Устройство должно было каждые 7,5 секунд передавать данные по BLE и потребляло слишком много энергии. Нужно было умерить “аппетиты” устройства, не снижая пропускную способность канала.
Мы запрограммировали устройство на буферизацию данных: перед установлением соединения данные собираются в пакеты и хранятся во временной памяти. В результате получилось увеличить интервалы соединения втрое. Соединение устанавливается реже – потребление энергии ниже.
Трудности, связанные с отладкой
При первом запуске любая программа будет вести себя не совсем так, как рассчитывают разработчики. Разнообразные баги могут появляться из-за того, что в сложных проектах трудно отслеживать все возможные взаимодействия. Непредвиденные ошибки могут возникать из-за обновления операционной системы, библиотек или аппаратного обеспечения. Поэтому отладка – это неотъемлемая часть разработки встроенного ПО.
Выявить баги можно с помощью отладчиков. Такие инструменты прогоняют код шаг за шагом и обнаруживают места, где программа зависает.
Однако отладчики не всегда доступны. Когда программа загружается на устройство, ради оптимизации размера из ее кода удаляется отладочная информация. Конечно, к этому этапу мы проверяем и перепроверяем код на несколько раз, поэтому после установки проблем быть не должно. Однако ошибки могут проявиться при обновлении прошивки.
Кроме того, некоторые китайские производители микроконтроллеров не имеют совместимых инструментов отладки. Мы столкнулись с такой ситуацией в одном из своих проектов. Из-за этого команде приходилось отслеживать поведение программы другими способами.
С помощью консоли мы вводили в части кода строки со специальными данными. Эти данные выводились через отладочный UART-порт (специальный разъем для обмена данными). Можно также использовать светодиод. Если введенные значение, строка кода или текст не выводятся, когда должны, значит, что-то пошло не так на предыдущем шаге.
Поскольку ошибки приходится выявлять, можно сказать, вручную, этот процесс очень утомительный и отнимает больше времени, чем при использовании инструмента отладки. Но оно стоит того.
Обновления и обновления по воздуху
Встроенное ПО устройств часто требуется обновлять – например, в программу добавляется новый функционал, и нужно передать новую версию прошивки уже активным пользователям. Когда дело касается обновлений по воздуху (через беспроводную сеть, например, Wi-Fi), то мы чаще всего сталкиваемся с такой проблемой, как прерывание сигнала.
Так, мы работали над проектом умного дома. Обсудили с заказчиком варианты и решили, что пользователям будет удобнее получать обновления встроенного ПО по воздуху. В этом случае нельзя, чтобы новый образ прошивки перезаписывал предыдущий напрямую. Если по каким-то причинам сигнал прервется, в памяти останется сломанный код и устройство “закирпичится”.
Поэтому мы добавили в систему резервную память. Образ прошивки сначала загружался туда, затем устройство проверяло целостность файлов, и лишь после этого образ переписывал исходную версию прошивки.
Точность генерации импульсов
Другая сложность в разработке встроенного ПО – достичь нужной точности таймингов. В одном из проектов от системы требовалось высокое быстродействие при большом количестве задач. Изначально мы решили писать встроенное ПО под операционную систему реального времени. Это сократило бы время разработки и сэкономило бы заказчику средства.
Однако на испытаниях программа генерировала сигналы с нестабильной задержкой. Вот как они выглядели на осциллографе:
Пришлось отказаться от изначального плана и переписать прошивку без применения операционной системы. Это сложнее и потребовало больше времени, но проблему удалось решить. Вот как стали выглядеть сигналы:
Какая из описанных трудностей кажется вам самой актуальной для вашего бизнеса и почему? Было бы интересно почитать.
Заключение
Заказывая проектирование электроники, важно выбрать опытную команду, которая знает, как справляться с типовыми трудностями разработки встроенного ПО. Это актуально по нескольким причинам:
- Качественная прошивка обеспечивает высокую надежность и безопасность устройства. Снижаются риски потери данных, взломов и сбоев, что особенно важно для потенциально опасного оборудования, например, промышленных устройств.
- Грамотные механизмы безопасности помогают защитить вашу интеллектуальную собственность и предотвратить подделку или несанкционированное использование продукции.
- Оптимизированное встроенное ПО эффективно использует ограниченные ресурсы устройства. Это позволяет ставить более дешевые компоненты и таким образом снижать себестоимость продукта.
- Устройства с качественным встроенным ПО работают стабильно. Это улучшает пользовательский опыт, повышает доверие к продукту, а с ним и конкурентоспособность решения.
а