Код тестирования для встроенного приложения
Фон:
Я разрабатываю довольно большой проект, используя Atmel AVR atmega2560. Этот проект содержит множество аппаратных функций (7 устройств SPI, 2 I2C, 2 порта RS485 MODBUS, множество аналоговых и цифровых входов/выходов). Я разработал "драйверы" для всех этих устройств, которые обеспечивают основной цикл приложения с помощью интерфейса для доступа к требуемым данным.
Вопрос:
Проект, который я разрабатываю, в конечном итоге должен будет соответствовать стандартам SIL.
Я хотел бы иметь возможность протестировать код и обеспечить хороший уровень охвата кода. Однако я не могу найти какую-либо информацию, чтобы начать с того, как должна быть настроена такая структура тестирования.
Идея состоит в том, что я могу иметь набор автоматических тестов, которые позволят исправлять ошибки и дополнения к функциям, которые будут проверены, чтобы проверить, не нарушают ли они код. Дело в том, что я не понимаю, как код может быть протестирован на чипе.
Требуется ли мне оборудование для мониторинга ввода-вывода на устройстве и эмуляции внешних устройств? Любые указатели, которые могут быть предоставлены, будут высоко оценены.
- Стив
Ответы
Ответ 1
Это очень хороший вопрос - общая проблема для встроенных разработчиков. К сожалению, большинство встроенных разработчиков не так обеспокоены, как вы, и проверяйте только код на реальном оборудовании. Но, как отметил еще один ответ, это может в основном проверить только номинальную функциональность кода, а не ошибки угла/ошибки.
Нет единственного и простого решения этой проблемы. Однако некоторые руководящие принципы и методы выполняют относительно хорошую работу.
Сначала разделите свой код на слои. Один уровень должен быть "аппаратным агностиком", т.е. вызовы функций. Не просите пользователя напрямую записывать в регистры HW. Другой (нижний) слой относится к HW. Этот слой можно "высмеять", чтобы проверить более высокий уровень. Более низкий уровень не может быть действительно протестирован без HW, но он не будет часто меняться и нуждается в глубокой интеграции HW, поэтому это не проблема.
"Испытательный жгут" будет вашим высокоуровневым агностическим кодом HW с "поддельным" нижним уровнем, специально предназначенным для тестирования. Это может имитировать устройства HW для правильной и неправильной работы и, таким образом, позволить вам запускать автоматические тесты на ПК.
Ответ 2
Никогда не запускайте модульные тесты на или против реального оборудования. Всегда издевайтесь над интерфейсами ввода/вывода. В противном случае вы не сможете имитировать условия ошибки и, что более важно, вы не можете положиться на тест, чтобы добиться успеха.
Итак, вам нужно разделить ваше приложение на разные части, которые вы можете тестировать самостоятельно. Симулятор (или макет) все аппаратное обеспечение, которое вам нужно для этих тестов, и запускайте их на своем ПК разработки.
Это должно охватывать большую часть вашего кода и оставляет вас с драйверами. Постарайтесь сделать как можно больше кода драйвера без использования оборудования. В остальном вам нужно понять, как сделать код на аппаратном уровне. Это обычно означает, что вы должны создать тестовую кровать с внешними устройствами, которые реагируют на сигналы и т.д. Так как это хрупкое (так как в "ваши тесты не могут сделать эту работу автоматически" ), вы должны запускать эти тесты вручную после подготовки оборудования.
Ответ 3
Vectorcast - это коммерческий инструмент для запуска модульных тестов на оборудовании с охватом кода.
Ответ 4
У вас есть разъем JTAG? Вы можете использовать JTAG для имитации ошибок на чипе.
Ответ 5
Мне нравится отделять задачи. Например, когда я создал круговой буфер для своего Atmel AVR, я написал все это в Code:: Blocks и скомпилировал его с помощью обычного компилятора GCC вместо компилятора AVR GCC, затем создаю для него unit test. Я использовал специальный файл заголовка, чтобы обеспечить соответствующие типы данных, с которыми я хотел работать (например, uint8_t). Я обнаружил ошибки с модульными тестами, исправил их, затем перевел фиксированный код в AVR Studio и интегрировал его. После этого я использовал написанные функции поддержки и ISR, чтобы поместить буфер в полезный код (т.е. Вытащить один байт из буфера, вставить его в регистр вывода данных UART, добавить строчную константу в буфер для функции printf и т.д.). Затем я использовал симулятор AVR, чтобы убедиться, что мои ISR и функции вызываются и что правильные данные появляются в регистрах. После этого я запрограммировал его на чип, и он работал отлично.
Я очень предпочитаю возможности отладки Code:: Blocks по сравнению с AVR Studio, поэтому я использую вышеуказанный подход, когда могу. Когда я не могу, я обычно имею дело только с оборудованием. Например, у меня есть таймер, который автоматически создает прямоугольную волну. Лучшее, что я мог сделать, это увидеть, что в симуляторе сбивается штыревой бит. После этого мне просто нужно было поднять прицел и убедиться.
Мне нравится использовать многоуровневый подход при отладке проблем. Например, с часами первый слой: "Поместите зонд на булавку и посмотрите, есть ли там сигнал". Если нет, проконтролируйте штырь на uC и ищите сигнал. Затем я закодировал интерфейс отладки в одном из моих UART, где я могу посмотреть конкретные значения регистра и убедиться, что они такие, какими они должны быть. Поэтому, если он не работает, следующим шагом является "вызвать значение регистра и обеспечить его правильность".
Попытайтесь задуматься о четырех шагах, когда планируете свою отладку. Здесь должно быть + 5В, но что, если нет? Запишите в интерфейс отладки способ переключения булавки и посмотреть, не изменит ли она ее. Что делать, если это не сработает? Сделайте что-нибудь еще и т.д. И т.д. Вы дойдете до точки, в которой вы столкнетесь: "У меня нет ИДЕИ, ПОЧЕМУ ЭТОТ ОПАСНО, ЧТО НЕ РАБОТАЕТ!!!!" но, надеюсь, вы заранее узнаете причину.