Pull to refresh

Автоматизация тестирования при разработке прошивок радиоэлектронных устройств

Reading time11 min
Views9.6K

Update: Видео версия материала https://youtu.be/9ITrzCq-YKI

Занимательный факт. Исходный код программы бортового управляющего компьютера лунного модуля Аполлон 11 содержит 64830 строк. Исходные коды прошивок навигационного приемника, которые мы в МЭИ разрабатываем последние десять лет, содержат 217510 строчек на C++ и 181236 строчек на SystemVerilog. И я всё жду, когда это количество перейдет в качество.

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

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

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

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

Традиционные испытания радиоаппаратуры

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

Наш приемник в баньке - камера тепла-холода-влажности
Наш приемник в баньке - камера тепла-холода-влажности

Проводить испытания по полной программе значительно чаще - нереально. Типичная программа испытаний рассчитана на 1-2 недели ручного труда, нужно подключать/отключать разные приборы, использовать испытательные камеры и т.д. и т.п. Проверяется длинный список требований из следующих групп:

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

Какие требования покрывать автотестами?

Так ли много требований могут сломаться при изменениях в прошивке? Пожалуй, в основном это требования назначения и, иногда, требования радиоэлектронной защиты. Их, а ещё ряд проверок выполнения требований к ПО, мы и автоматизировали:

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

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

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

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

  • самая частая ошибка при разработке ПО - код не компилируется или не синтезируется (забыли файл, не те ключи у разработчика, битстрим собирается с критическим ворнингом, прошивка перестала вмещаться в небольшую ПЛИС и т.д. и т.п.);

  • требования назначения доминируют в программе и методике испытаний радиоустройств (например, это 73% ПМИ в нашей последней разработке);

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

Какие компоненты тестировать?

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

В качестве устройства мы выделили изделие с максимумом функций и интерфейсов - навигационный приемопередатчик. Он не только принимает сигналы GPS, ГЛОНАСС и т.д., но может и формировать навигационные сигналы для разных нужд. Например, для испытания другой аппаратуры или построения локальных навигационных систем.

Навигационный приемопередатчик Adicus, испытываемое изделие
Навигационный приемопередатчик Adicus, испытываемое изделие

В комплекс его ПО входит множество компонентов:

Но наиболее критичными являются прошивка процессорной системы (Firmware в виде демона для запуска на ОС), прошивка программируемой логики (Logic Modules, из которых генерируется прошивка ПЛИС) и хостовые программы для взаимодействия с устройством.

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

Как часто тестировать?

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

Замечательно было бы реагировать на каждое изменение, вносимое разработчиками в код, в том числе в ветках. Тогда разработчики быстрее узнают о проблемах и быстрее их исправят. Но, к сожалению, пуши от разработчиков поступают чаще, чем длительность исполнения некоторых тестов. Так прошивка для ПЛИС может разводиться несколько часов, а тест на живом приемнике может потребовать сбора данных на нескольких десятках минут и т.д. Можно было бы размножать ресурсы для выполнения тестов, но вместо этого мы дополнительно сократили программу испытаний для отдельных пушей.

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

Третий тип событий - ночные тесты. Тут оборудование свободно. Можно занять несколько часов машинного времени, решить задачи оптимизации, подготовить прошивки ПЛИС с полным заполнением кристалла и т.д. и т.п. Подготовить прошивки для использования конечным пользователем.

Испытания в отдельной ветке 1028-fix-snr, ночной тест в develop и процесс ревью #479 через Merge request
Испытания в отдельной ветке 1028-fix-snr, ночной тест в develop и процесс ревью #479 через Merge request

Три разных типа событий, три разных программы, отличающиеся объемом и временем исполнения. Но все они - автоматические. Вместе они позволяют реализовать систему непрерывного применения изменений (Continuous Integration, CI) и непрерывной поставки изменений пользователю (Continuous Deploy, CD)

Использование Gitlab CI/CD для организации автотестов

Первые три попытки

Немного истории. Как опытные разработчики велосипедов, мы начали с собственного решения. Написали библиотечку для общения с лабораторными приборами в матлабе, скрипты тестирования под разные требования. Разложили по папочкам. Написали описание к каждому тесту в Word'е. И запускали эти скрипты по cron'у через Makefile. Отчет приходил ночью на почту.

Артефакты неизвестной цивилизации, примерно 2016 год нашей эры
Артефакты неизвестной цивилизации, примерно 2016 год нашей эры

Эта система ушла в забвение в 2014 после обновления сервера, проработав пару месяцев. Затем авторазложение повторилось в 2016 году, после того, как кто-то утащил имитатор сигналов для выполнения другой работы. Она не преодолела порог полезности - слишком много сил на поддержание, результат приходит с задержкой, не изящно и не красиво.

Письмо с результатами теста
Письмо с результатами теста

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

В четвертый раз инструмент соответствовал задаче. В качестве системы контроля версий - git, ведение проекта в Gitlab, а система автотестирования в Gitlab CI/CD. Ну и ряд организационных мер: ответственный человек и выделенные исключительно под тестирование лабораторные приборы и серверы.

Взаимодействие компонентов системы автоматического тестирования
Взаимодействие компонентов системы автоматического тестирования

Ядром системы выступает локальный Gitlab-сервер. На нем хранятся репозитории, с ним взаимодействуют разработчики и раннеры. Раннеры - специальные программы, запущенные на отдельных серверах. Они периодически обращаются на сервер с вопросом: а есть что потестировать? Если есть, они получают задачу и начинают её выполнять. Сейчас мы используем три раннера: один для сборки прошивок ПЛИС, один для взаимодействия с изделием и лабораторными приборами, и один для остальных нужд.

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

Этапы испытаний

Сущности и понятия, используемые в Gitlab, хорошо ложатся на термины отечественных ГОСТов. Что ГОСТу этап, то Gitlab'у stage, что ГОСТу программа испытаний, то Gitlab'у pipeline (конвейер). Мы разбили программу испытаний на три этапа:

  • Build - Сборка - на этом этапе компилируются программы, генерируются прошивки ПЛИС, выполняются юнит-тесты

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

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

Здоровый конвейер - зеленый конвейер
Здоровый конвейер - зеленый конвейер

Есть ещё чисто технический четвертый этап, Conclusion, на нем мы собираем итоговые документы о проведенном тестировании.

Проверки

По ГОСТу этап содержит проверки или испытания, а в Gitlab'е этап содержит job'ы. Один job - одна проверка.

Каждая проверка - это скрипт, запускаемый на одном из раннеров в нужном docker-окружении. Ему могут быть предоставлены результаты выполнения других проверок (например, собранные прошивки). А ещё ему доступна локальная копия всего репозитория, все исходные коды проекта.

Правила запуска скрипта описываются в gitlab-ci.yaml файле, располагаемом в корне репозитория. Скрипты теста также лежат в репозитории. Таким образом, вы всегда можете вернуться к нужному коммиту и перезапустить проверки, если это потребуется.

Пример описания одной из проверок в gitlab-ci.yaml

Разделы с описанием проверок в gitlab-ci.yaml формируются отдельным генератором под составленную программу испытаний, выглядит они примерно так:

adicusSolveslnTTFFforGPS:
  extends: 
    - .testbed
    - .artifacts_settings
  allow_failure: true
  rules:  
    - if: '$CI_PIPELINE_SOURCE == "push"'
      when: always  
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
      when: always  
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: always
    - when: never
  variables:
    PREFIX: '016'
  needs:
    - testBedlsPowered 
    - trcvdlsCompilableForPetaLinux 
    - simlsCompilableForHostLinux 
    
  script: >
    python3 ./qa/tests/is_testbed_ttff_low.py    --param '{"system": ["GPS"], "ttff": 300, "IP": ["192.168.0.117"], "DEV": ["CLONICUS"], "accumulation_time":150, "PLTYPEFINDBIT" : "CI" }'            --obj "Прошивка процессорной системы" --prefix $PREFIX --stage $CI_JOB_STAGE --CI_JOB_NAME $CI_JOB_NAME --GITLAB_TOKEN $GITLAB_TOKEN

.artifacts_settings:
  artifacts:
    when: always
    paths: 
      - qa/reports/$CI_JOB_NAME
      - qa/reports/log
      - built
      - built/petalinux
      - built/qnx
      - qa/built
      - qa/built/petalinux
      - qa/built/qnx
      - qa/log
    expire_in: 2 week


.testbed:
  image: navsyslab/sim:v3.3
  stage: testbed
  cache:
    key: $CI_COMMIT_SHORT_SHA
    paths:
        - qa/cache
        - qa/log
        - built
        - built/petalinux
        - built/qnx
  tags:
    - testbed
  resource_group: testbed
  before_script:
    - mkdir -p ./qa/cache
  after_script:
    - ls -l qa/cache

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

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

  • запись описания предстоящих на этом шаге действий в файл методики испытаний method.tex

  • непосредственно выполнение действия и получение результата

  • запись результата в файл протокола protocol.tex

Псевдокод функции, осуществляющей непосредственно проверки, подготовку методики и протоколов
Псевдокод функции, осуществляющей непосредственно проверки, подготовку методики и протоколов

Благодаря такой простой организации тестового скрипта описание методики, действия и протокол не расходятся и не содержат воду.

Приложения

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

В системе автоматического тестирования мы Приложения выделили в отдельные скрипты - apps. Они нужны для того, чтобы:

  • не дублировать код в скриптах проверок

  • не дублировать действие, если его результат известен из другой проверки

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

Кэширование результатов работы Приложений
Кэширование результатов работы Приложений

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

Стенд и взаимодействие с лабораторными приборами

В составе стенда мы собрали лабораторные приборы одного производителя - немецкого Rohde&Schwarz:

  • векторный генератор сигналов с функциями имитации навигационных сигналов SMBV100A,

  • осциллограф RTM1054,

  • анализатор спектра FSV3.

Испытательный стенд (FSV остался за скобками; экраны обычно выключены)
Испытательный стенд (FSV остался за скобками; экраны обычно выключены)

Векторный генератор используется для имитации выхода ГНСС антенны: навигационных сигналов различных спутников, теплового шума усилителя, помех.

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

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

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

Например, так генератор настраивается на имитацию шума ГНСС антенны
    def setawgn(self):
        self.sendcommand('SOUR:AWGN:STAT OFF')
        self.sendcommand('SOUR:AWGN:MODE ADD')
        self.sendcommand('SOUR:AWGN:BWID 75e6')
        self.sendcommand('SOUR:AWGN:BWID:RAT 1.0')
        self.sendcommand('SOUR:AWGN:DISP:MODE RF')
        self.sendcommand('SOUR:AWGN:POW:MODE CN')
        self.sendcommand('SOUR:AWGN:POW:RMOD NOISE')
        self.sendcommand('SOUR:AWGN:CNR -26')
        self.sendcommand('SOUR:AWGN:POW:NOISE -44')
        self.sendcommand('SOUR:AWGN:BRAT 1023000')
        self.opc()
        self.sendcommand('SOUR:AWGN:STAT ON')
        self.opc()
        print(f'SMBV:AWGN set to ADD mode')

Что-то даже есть в сети.

Функции библиотеки вызываются либо непосредственно из Проверок, либо из Приложений.

Оформление отчета по ЕСКД

На этапе Conclusion отдельные методики и протоколы собираются в два документа:

  • Программа и методика испытаний

  • Книга протоколов испытаний

Сборка отчетных документов
Сборка отчетных документов

Благодаря LaTeX и нашему шаблону они выглядят на радость нормоконтролеру:

Картинка, доказывающая, что всё по ГОСТу!
Картинка, доказывающая, что всё по ГОСТу!

Для этого на этапе проверок и приложений готовятся уникальные tex-файлы и изображения. На последнем этапе они конвертируются в pdf.

Непрерывная интеграция изменений

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

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

Процесс рассмотрения Merge Request'а
Процесс рассмотрения Merge Request'а

Когда разработчик выполнил поставленную задачу, он заводит Merge Request для передачи изменений в основную ветку проекта. Успешно выполненные тесты - это необходимое условие для принятия Merge Request'а. Если код и изделие не прошли испытания, изменения не попадут в основную ветку проекта.

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

Заключение

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

Tags:
Hubs:
Total votes 30: ↑29 and ↓1+35
Comments29

Articles