Выход OpenOCD по точке останова
Я разрабатываю приложение на STM32F042. Я прогоняю все из make-файла, включая свои модульные тесты. Я использую OpenOCD и ST-LINK для прошивки цели. Мои модульные тесты выполняются на хосте и на целевом компьютере. Драйвер модульного тестирования хоста возвращает 0 из main() в случае успеха и ненулевое значение в случае неудачи, поэтому make-файл знает, прошли ли тесты. Makefile мигает и запускает тесты на целевом объекте, но не знает, успешны они или нет. Встроенное тестовое приложение включает красный светодиод при сбое и зеленый при успешном выполнении, поэтому я знаю - теперь я хочу автоматизировать этот шаг.
Я хочу установить две точки останова в коде, одну в обработчике сбоя и одну в конце main, и сказать OpenOCD выйти с нулевым или ненулевым статусом, если он попадет в одну или другую точку останова.
Итак, мой вопрос сводится к двум конкретным:
Чтобы установить точку останова, мне нужно знать значение ПК в определенной строке кода. Как мне получить это значение из набора инструментов arm-gcc?
Могу ли я настроить OpenOCD для выхода по определенным точкам останова и с определенным статусом?
1 ответ
Вот что у меня получилось. Для каждого целевого модульного теста я запускаю сервер OpenOCD и подключаюсь к нему с помощью gdb. Gdb запускает сценарий, который устанавливает две точки останова, одну для успеха, одну для отказа. Если он достигает любой точки останова, он завершает работу сервера OCD и завершает работу с кодом, который сообщает об успехе или неудаче в оболочку. Чтобы запустить те же тесты на хосте, я просто компилирую их как обычные исполняемые файлы.
Makefile:
# target unit test binaries
foo_tests.elf bar_tests.elf baz_tests.elf bop_tests.elf: unit_test_runner.ao
# disable optimization for target unit test driver to avoid optimizing
# away functions that serve as breakpoint labels
unit_test_runner.ao: CFLAGS += -O0 -g
# link target unit test binaries for semihosting
%_tests.elf: ARM_LDLIBS += -specs=rdimon.specs -lrdimon
# host unit test binaries
foo_tests bar_time_tests baz_tests bop_tests: unit_test_runner.o
# run target unit test binaries through gdb and OpenOCD; redirecting stderr
# leaves printf output from `assert()' clearly visible on the console
%.tut: %.elf
openocd -f interface/stlink-v2-1.cfg -f target/stm32f0x.cfg 2> $@.log &
gdb-multiarc -batch-silent -x tut.gdb $< 2> $@-gdb.log
# run host binary
%.run: %
./$*
tests: foo_tests.run bar_time_tests.run baz_tests.run bop_tests.run \
foo_tests.tut bar_time_tests.tut baz_tests.tut bop_tests.tut
tut.gdb:
target remote localhost:3333
monitor arm semihosting enable # let assert()'s printf() through
monitor reset halt
load
monitor reset init
break success # set breakpoint on function `sucess()'
commands # on hitting this bp, execute the following:
monitor shutdown # shutdown OpenOCD server
quit 0 # exit GDB with success code
end
break failure # set breakpoint on function `sucess()'
commands
monitor shutdown
quit 1 # exit GDB with failure code
end
continue
unit_test_runner.c:
#include <stdlib.h>
/* These two functions serve as labels where gdb can place
breakpoints. */
void success() {}
void failure() {}
/* Implementation detail for `assert()' macro */
void assertion_failure(const char *file,
int line,
const char *function,
const char *expression)
{
printf("assertion failure in %s:%d (%s): `%s'\n",
file, line, function, expression);
failure();
exit(1);
}
/* This function is necessary for ARM semihosting */
extern void initialise_monitor_handles(void);
int main(int argc, char* argv[])
{
#ifdef __arm__
initialise_monitor_handles();
#endif
tests(); /* client code implements this function */
success();
return 0;
}