Como imprimo mensagens de depuração no console gdb com a placa de descoberta STM32 usando GDB, OpenOCD e arm-none-eabi-gcc?

15

Estou programando uma placa de descoberta STM32 Cortex M0 (32F0308DISCOVERY) usando OpenOCD, arm-none-eabi-gcc e gdb. Eu queria saber se existe alguma maneira simples de registrar mensagens de depuração por SWD. Eu li sobre a opção de semi-hospedagem, mas isso parece exigir a inclusão de newlib ou outras grandes bibliotecas. (Existe apenas um flash de 64k disponível.) Existe alguma maneira mais leve de registrar texto por SWD ou usar o UART como única opção prática?

foldl
fonte
1
Eu sugiro que você tente a opção semi-hospedagem. A título indicativo, as bibliotecas oferecidas pelo CooCox (um ambiente Windows Cortex-M gratuito) para M3 / 4 são bastante minimalistas, sua transferência de byte único é 17 instruções de montagem. A reconstrução de um projeto antigo (STM32F4) com sua semi-hospedagem e -O0 adicionou 48 bytes ao tamanho do código.
Markt
Você pode não ter o vinculador removendo o código não utilizado. Quanto às alternativas, o repositório do github do texane para conduzir ferramentas stlink tem um esquema simples de caixa de correio, embora eu ainda não o tenha experimentado.
Chris Stratton

Respostas:

15

Obrigado pelas indicações, markt e chris-stratton. A opção de semi-hospedagem acabou sendo bastante direta. Consegui encontrar a fonte para algumas rotinas simples de log que podem enviar mensagens para o console do OpenOCD. Vou publicá-los aqui, pois (i) eles precisaram de alguma modificação para funcionar e (ii) acho que essa informação não é super fácil de encontrar para pessoas que estão apenas começando.

Primeiro, o código D aqui é facilmente adaptado para fornecer a seguinte função 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");
}

Exemplo de chamada do send_command para gravar uma sequência no console do 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);

Segundo, a função putChar dada nos comentários aqui funciona bem, exceto que eu tive que adicionar um '#' antes de 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"
    );
}

Para observar a saída dessas funções, inicio o OpenOCD e, em seguida, conecto usando arm-none-eabi-gdb da seguinte maneira:

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

Observe que as mensagens aparecem no stdout do processo OpenOCD, não no console do GDB.

foldl
fonte
1
Há um erro, o sizeof () deve ser strlen ().
1
Obrigado user107642. De fato, é possível usar sizeof aqui se 's' for uma matriz e não um ponteiro, então eu a modifiquei dessa maneira.
foldl
Ótima resposta! Você também pode escrever putchartão simples quantovoid putchar(char c) { send_command(3,&c); }
mvds
1
O "sizeof" contará o \ 0 à direita da string, enquanto strlen não. Se o openocd apenas imprimir no stdout e em uma janela do terminal xterm, isso provavelmente não fará uma diferença perceptível, pois o terminal provavelmente o ignorará. Mas se você acabar colocando as coisas em um arquivo, acho que ficará surpreso ao encontrar esses zeros lá. Ou o protocolo especifica que você precisa enviar seqüências de caracteres com o terminador à direita?
User242579
Ah, bom ponto user242579. Adicionei um '-1' para levar em consideração o final \ 0.
usar o seguinte