Дякую за покажчики, марк та крис-страттон. Варіант напівгості виявився досить простим. Мені вдалося знайти джерело для декількох простих процедур ведення журналу, які можуть надсилати повідомлення на консоль 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.