Как распечатать сообщения отладки на консоли gdb с платой обнаружения STM32, используя GDB, OpenOCD и arm-none-eabi-gcc?

15

Я программирую плату обнаружения STM32 Cortex M0 (32F0308DISCOVERY), используя OpenOCD, arm-none-eabi-gcc и gdb. Мне было интересно, есть ли какой-нибудь простой способ записи отладочных сообщений через SWD. Я читал об опции полухостинга, но, похоже, для этого нужно добавить newlib или другие большие библиотеки. (Доступно только 64 КБ флэш-памяти.) Есть ли более легкий способ записи текста через SWD или использование UART - единственный практичный вариант?

foldl
источник
1
Я предлагаю вам попробовать вариант полухостинга. Для примера, библиотеки, предлагаемые CooCox (бесплатная среда Windows Cortex-M) для M3 / 4, довольно минималистичны, их однобайтовая передача - 17 инструкций по сборке. Перестройка старого проекта (STM32F4) с их полустоингом и -O0 добавила 48 байтов к размеру кода.
Markt
Возможно, ваш компоновщик не удаляет неиспользуемый код. Что касается альтернатив, в gtub-репозитории texane для управления инструментами stlink есть простая схема почтового ящика, хотя я еще не пробовал ее.
Крис Страттон

Ответы:

15

Спасибо за указатели, Маркт и Крис-Страттон. Вариант полухостинга оказался довольно простым. Мне удалось найти источник для пары простых процедур регистрации, которые могут отправлять сообщения на консоль OpenOCD. Я опубликую их здесь, так как (i) они требуют некоторой модификации для работы и (ii) я думаю, что эту информацию не так просто найти людям, которые только начинают работать.

Во- первых, D - код здесь легко приспосабливается предоставить следующую функцию C:

void send_command(int command, void *message)
{
   asm("mov r0, %[cmd];"
       "mov r1, %[msg];"
       "bkpt #0xAB"
         :
         : [cmd] "r" (command), [msg] "r" (message)
         : "r0", "r1", "memory");
}

Пример вызова send_command для записи строки в консоль OpenOCD:

const char s[] = "Hello world\n";
uint32_t m[] = { 2/*stderr*/, (uint32_t)s, sizeof(s)/sizeof(char) - 1 };
send_command(0x05/* some interrupt ID */, m);

Во- вторых, функция putChar дается в комментариях здесь работает отлично, за исключением того, что мне пришлось добавить «#» перед тем 0x03:

void put_char(char c)
{
    asm (
    "mov r0, #0x03\n"   /* SYS_WRITEC */
    "mov r1, %[msg]\n"
    "bkpt #0xAB\n"
    :
    : [msg] "r" (&c)
    : "r0", "r1"
    );
}

Чтобы посмотреть на вывод этих функций, я сначала запускаю OpenOCD, затем подключаюсь с помощью arm-none-eabi-gdb следующим образом:

target remote localhost:3333
monitor arm semihosting enable
monitor reset halt
load code.elf
continue

Обратите внимание, что сообщения появляются в stdout процесса OpenOCD, а не в консоли GDB.

foldl
источник
1
Есть ошибка, sizeof () должен быть strlen ().
1
Спасибо user107642. На самом деле здесь можно использовать sizeof, если 's' - это массив, а не указатель, поэтому я изменил его таким образом.
foldl
Отличный ответ! Вы также можете написать putcharтак просто, какvoid putchar(char c) { send_command(3,&c); }
mvds
1
"Sizeof" будет считать завершающий \ 0 строки, в то время как strlen не будет. Если openocd просто печатает на стандартный вывод и окно терминала xterm, это, вероятно, не будет иметь заметного значения, поскольку терминал, вероятно, проигнорирует его. Но если вы в конечном итоге поместите вещи в файл, я думаю, вы будете удивлены, обнаружив эти нули там. Или протокол указывает, что вам нужно отправлять строки с завершающим терминатором?
user242579
Ах, хорошая точка user242579. Я добавил '-1', чтобы учесть завершающий \ 0.
сложить