Тестирование кода для встроенного приложения

Фон:

Я разрабатываю большой проект с использованием Atmel AVR atmega2560. Этот проект содержит множество аппаратных функций (7 устройств SPI, 2 порта I2C, 2 порта RS485 MODBUS, множество аналоговых и цифровых входов / выходов). Я разработал "драйверы" для всех этих устройств, которые обеспечивают основной цикл приложения интерфейсом для доступа к необходимым данным.

Вопрос:

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

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

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

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

--Стив

5 ответов

Решение

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

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

Сначала разделите ваш код на слои. Один уровень должен быть "аппаратно-независимым" - то есть вызовы функций. Не просите пользователя писать напрямую в регистры HW. Другой (нижний) уровень имеет дело с HW. Этот слой можно "высмеять", чтобы протестировать более высокий уровень. Нижний уровень не может быть действительно протестирован без HW, но он не будет часто меняться и нуждается в глубокой интеграции HW, так что это не проблема.

"Жгутом тестирования" будет весь ваш высокоуровневый HW-независимый код с "поддельным" нижним уровнем специально для тестирования. Это может моделировать устройства HW для корректной и неправильной функциональности и, таким образом, позволяет запускать автоматические тесты на ПК.

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

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

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

Vectorcast - это коммерческий инструмент для запуска модульных тестов на оборудовании с покрытием кода.

У вас есть разъем JTAG? Вы можете использовать JTAG для симуляции ошибок на чипе.

Мне нравится разделять задачи. Например, когда я сделал кольцевой буфер для своего Atmel AVR, я написал все это в Code::Blocks и скомпилировал его с помощью обычного компилятора GCC вместо компилятора AVR GCC, а затем я создал для него модульный тест. Я использовал специальный заголовочный файл для обеспечения правильных типов данных, с которыми я хотел работать (например, uint8_t). Я нашел ошибки в модульных тестах, исправил их, затем перенес исправленный код в AVR Studio и интегрировал его. После этого я использовал функции поддержки записи и ISR, чтобы поместить буфер в полезный код (т. Е. Извлечь один буфер из буфера, вставить его в регистр вывода данных UART, добавить строковую константу в буфер для функции printf и т. Д.). Затем я использовал симулятор AVR, чтобы убедиться, что мои ISR и функции вызывались и что правильные данные отображались в регистрах. После этого я запрограммировал его на чип, и он работал отлично.

Я очень предпочитаю возможности отладки Code::Blocks по сравнению с AVR Studio, поэтому я использую описанный выше подход, когда могу. Когда я не могу, я обычно имею дело только с оборудованием. Например, у меня есть таймер, который автоматически производит прямоугольную волну. Лучшее, что я мог сделать, - это увидеть, как в симуляторе вертится бит. После этого мне просто нужно было прицелиться и убедиться.

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

Попробуйте заранее продумать четыре шага, когда планируете отладку. Здесь должно быть +5В, но что, если нет? Запишите в интерфейс отладки способ переключения пина и посмотрите, изменит ли это его. Что если это не сработает? Делайте что-нибудь еще, и так далее, и так далее. Вы попадаете в точку, когда вы сталкиваетесь с тем, что "У меня нет идеи, почему эта опасность не работает!!!!" но, надеюсь, вы заранее выясните причину.

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