Як надрукувати повідомлення про налагодження на консолі gdb за допомогою плати виявлення STM32 за допомогою GDB, OpenOCD та arm-none-eabi-gcc?


15

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


1
Пропоную спробувати варіант напівгості. За ознакою, бібліотеки, пропоновані CooCox (вільне середовище Windows Cortex-M) для M3 / 4, є досить мінімалістичними, їх однобайтовий переказ становить 17 інструкцій по збірці. Перебудова старого (STM32F4) проекту з їх напівгостунгом та -O0 додала 48 байт до розміру коду.
маркт

У вас може не бути, щоб ваш лінкер знімав невикористаний код. Щодо альтернативних варіантів, github repo 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

Зауважте, що повідомлення відображаються в макеті процесу OpenOCD, а не на консолі GDB.


1
Там помилка, розмір () повинен бути strlen ().

1
Дякую користувачу107642. Насправді тут можна використовувати sizeof, якщо 's' - це масив, а не покажчик, тому я змінив його таким чином.
скласти

Чудова відповідь! Ви також можете написати putcharтак просто, якvoid putchar(char c) { send_command(3,&c); }
mvds

1
"Sizeof" буде рахувати тривалість \ 0 рядка, тоді як strlen не буде. Якщо openocd просто друкує до stdout та вікно терміналу xterm, це, ймовірно, не помітить різниці, оскільки термінал, ймовірно, проігнорує це. Але якщо ви в кінцевому підсумку помістите речі у файл, я думаю, ви здивуєтеся, що знайдете там ці нулі. Або в протоколі вказується, що вам потрібно надіслати рядки з кінцевим термінатором?
користувач242579

Ах, добрий користувач242579. Я додав '-1', щоб врахувати відстань \ 0.
скласти
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.