Jak wydrukować komunikaty debugowania na konsoli gdb za pomocą płyty wykrywającej STM32 przy użyciu GDB, OpenOCD i arm-none-eabi-gcc?

15

Programuję płytę wykrywającą STM32 Cortex M0 (32F0308DISCOVERY) przy użyciu OpenOCD, arm-none-eabi-gcc i gdb. Zastanawiałem się, czy jest jakiś prosty sposób na rejestrowanie komunikatów debugowania przez SWD. Czytałem o opcji semihosting, ale wydaje się, że wymaga to wciągnięcia newlib lub innych dużych bibliotek. (Dostępna jest tylko pamięć flash 64k.) Czy istnieje bardziej lekki sposób na rejestrowanie tekstu przez SWD, czy też używanie UART jest jedyną praktyczną opcją?

złożyć
źródło
1
Sugeruję wypróbowanie opcji semihostingu. Tytułem informacji, biblioteki oferowane przez CooCox (darmowe środowisko Windows Cortex-M) dla M3 / 4 są dość minimalistyczne, ich transfer jednobajtowy to 17 instrukcji montażu. Przebudowa starego projektu (STM32F4) z ich półhostingiem i -O0 dodała 48 bajtów do rozmiaru kodu.
markt
Twój linker może nie usuwać nieużywanego kodu. Jeśli chodzi o alternatywy, repo github texane do napędzania narzędzi stlink ma prosty schemat skrzynki pocztowej, chociaż jeszcze tego nie wypróbowałem.
Chris Stratton

Odpowiedzi:

15

Dzięki za wskazówki, markt i chris-stratton. Opcja półhostingu okazała się dość prosta. Udało mi się znaleźć źródło kilku prostych procedur rejestrowania, które mogą wysyłać wiadomości do konsoli OpenOCD. Zamieszczę je tutaj, ponieważ (i) wymagały one modyfikacji, aby działały oraz (ii) Myślę, że te informacje nie są bardzo łatwe do znalezienia dla osób, które dopiero zaczynają.

Pierwszy kod D tutaj łatwo dostosowany, aby zapewnić następującą funkcję: 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");
}

Przykład wywołania polecenia send_command w celu napisania ciągu znaków do konsoli 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);

Po drugie, funkcja putChar podana w komentarzach tutaj działa dobrze, z tym wyjątkiem, że musiałem dodać „#” przed 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"
    );
}

Aby zobaczyć wyniki tych funkcji, najpierw uruchamiam OpenOCD, a następnie łączę się za pomocą arm-none-eabi-gdb w następujący sposób:

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

Zauważ, że komunikaty pojawiają się na standardowym etapie procesu OpenOCD, a nie na konsoli GDB.

złożyć
źródło
1
Wystąpił błąd, sizeof () powinien być strlen ().
1
Dzięki użytkownik107642. W rzeczywistości można tutaj użyć sizeof, jeśli „s” jest tablicą, a nie wskaźnikiem, więc zmodyfikowałem go w ten sposób.
foldl
Świetna odpowiedź! Możesz także napisać putchartak proste, jakvoid putchar(char c) { send_command(3,&c); }
mvds
1
„Sizeof” policzy końcowe \ 0 ciągu, a strlen nie. Jeśli openocd po prostu wypisze na standardowe wyjście i okno terminala xterm, prawdopodobnie nie zrobi to zauważalnej różnicy, ponieważ terminal prawdopodobnie go zignoruje. Ale jeśli w końcu umieścisz różne rzeczy w pliku, myślę, że będziesz zaskoczony, gdy znajdziesz tam te zera. Czy protokół określa, że ​​należy wysyłać ciągi z końcowym terminatorem?
user242579,
Ach, dobry punkt użytkownik 242579. Dodałem „-1”, aby uwzględnić końcowe \ 0.
foldl