GNU ARM Cross-toolchain – OpenOCD + GDB

gdb

Os artigos anteriores da série indicaram os passos a serem seguidos para compilação de um projeto, configuração das regiões de dados na memória e gravação do binário executável gerado na memória do microcontrolador. Ao longo da etapa de desenvolvimento de um projeto, é necessário que haja algum meio de depuração do código, mesmo que este seja um simples envio de dados seriais por um periférico do microcontrolador. Isso acaba não sendo prático pois esse método, para cada adição de um ponto de depuração, deve ser executado o seguinte ciclo: alteração de código, compilação e execução. A fim de reduzir esse ciclo, neste artigo é introduzido o depurador GDB, que permite o controle de execução da aplicação, podendo inserir breakpoints ao longo do seu código.

 

Antes de entrarmos em maiores detalhes, é necessário possuir uma cópia local do projeto disponível no GitHub. Caso não tenham sido realizados os passos listados nos artigos anteriores, é interessante que esses sejam executados de forma a tirar maior proveito dos conceitos apresentados a seguir.

 

Uma vez que o ambiente esteja criado corretamente, basta atualizar o projeto, tendo em vista que ele vem sofrendo alterações/modificações com o tempo. Execute os seguintes comandos:

 

$ cd ~/work/projects/stm32f4-discovery-bare-metal
$ git pull

 

 

 Por que depurar?

 

Uma vez que o binário executável seja gerado no dispositivo host, um PC, é necessário gravá-lo no dispositivo target e executá-lo. Isso foi feito no primeiro artigo desta série, e é o que ocorre na fase de produção de um produto. O microprocessador busca e executa as instruções da memória do sistema, interna ou externa, sem permitir que o estado interno do programa seja monitorado, o que atrapalha a etapa de desenvolvimento. Para isso foi criado um método de depuração do código de uma aplicação que é executada num ambiente target diferente do ambiente host, conhecido como depuração remota.

 

 

Depuração remota

 

Para a execução da depuração remota, são necessários dois ambientes: o host e o target. No primeiro deve ser executado um aplicativo front-end, depurador, o qual oferece a interface com o usuário. Já no sistema target, precisa existir um aplicativo back-end, também conhecido como debug monitor, que se comunique com o aplicativo front-end que é executado no sistema host. Esse meio de comunicação pode ser tanto uma conexão ethernet ou serial, isolando o controle de baixo nível com o microprocessador realizado pelo back-end.

 

Em sistemas bare-metal, ao invés de ser implementado um debug monitor no próprio dispositivo target, é comum executar esse aplicativo no próprio ambiente host, capaz de se comunicar com o dispositivo target de alguma forma, tal como USB. Como o host não possui suporte nativo à sinalização elétrica necessária para o acesso ao hardware a ser depurado, faz-se necessário que o ambiente target possua um hardware especial, chamado debug adapter. Esse dispositivo é capaz de receber comandos de baixo nível e realizar a depuração do microprocessador por meio de algumas interfaces, tal como JTAG e SWD.

 

Neste artigo é utilizado o depurador GDB, que é fornecido pelo pacote de instalação do cross-toolchain utilizado. Já o back-end servidor deve ser um aplicativo com suporte ao microprocessador utilizado (STM32F4), ao debug adapter do kit de desenvolvimento (ST-LINK/V2) e, principalmente, ao protocolo serial remoto (RSP) do GDB. O OpenOCD possui todas essas características, e já foi utilizado no artigo anterior. A configuração utilizada é exibida na figura abaixo.

 

remote_debug

 

 

OpenOCD

 

O aplicativo OpenOCD (Open On-Chip Debugger) tem como objetivo oferecer, para dispositivos embarcados, depuração, in-system programming e boundary-scan. Também oferece suporte a adaptadores que implementam os padrões JTAG e SWD. Deve-se levar em consideração que a interface SWD não oferece suporte à boundary-scan e, portanto, o foco deste artigo, usando o kit STM32F4Discovery, é somente depuração.

 

OpenOCD implementa dois servidores: um Telnet e outro GDB. Uma vez que esse aplicativo é executado, são aguardadas conexões de clientes a partir desses dois canais de comunicação e processados os comandos recebidos.

 

Para iniciar a depuração do projeto disponibilizado no GitHub, vamos precisar dos mesmos componentes que vínhamos utilizando até o momento. Ou seja, um PC host Linux, o kit STM32F4Discovery e um cabo USB.

 

O primeiro passo é iniciar o servidor GDB, o OpenOCD.

  

$ openocd -s ~/work/tools/openocd/share/openocd/scripts -f board/stm32f4discovery.cfg

 

As mensagens abaixo devem ser exibidas. Neste momento o OpenOCD já iniciou o seu servidor GDB e está aguardando comandos do aplicativo cliente.

 

Open On-Chip Debugger 0.8.0 (2014-08-23-18:03)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.sourceforge.net/doc/doxygen/bugs.html
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : This adapter doesn't support configurable speed
Info : STLINK v2 JTAG v14 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 2.905263
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints

 

O passo seguinte é, em outro prompt do shell, inicializar o cliente GDB e indicar a aplicação a ser depurada.

 

$ cd ~/work/projects/stm32f4-discovery-bare-metal/hello_world
$ arm-none-eabi-gdb build/hello-world.elf

 

As mensagens abaixo são exibidas. Os símbolos de debug e as seções de código e dados, contidos no arquivo executável no formato ELF, são lidos pelo depurador e, no final, é disponibilizado um prompt de comando do GDB.

 

GNU gdb (Sourcery CodeBench Lite 2014.05-28) 7.7.50.20140217-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://sourcery.mentor.com/GNUToolchain/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from build/hello-world.elf...done.
(gdb)

 

Agora deve ser indicado que a aplicação a ser depurada não é nativa e encontra-se gravada em outro ambiente. Para isso, deve ser informado o meio de acesso remoto ao servidor GDB, o qual realiza a interface com o dispositivo target. Pelo fato desse aplicativo ser executado no ambiente host também, como ilustrado na figura anterior, é implementada a conexão com o cliente GDB por meio de socket localhost, usando a porta 3333. Portanto, execute o seguinte comando:

 

(gdb) target remote localhost:3333

 

Caso exista algum programa gravado na memória do microprocessador, é dado início à sua execução. Mas neste momento é interessante que o dispositivo esteja no estado halt, em modo debug. Para isso, execute o próximo comando:

 

(gdb) monitor reset init

 

O resultado do comando acima deve ser o seguinte: 

 

target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000504 msp: 0x20020000
(gdb) 

 

Obs.: O comando monitor do GDB faz com que o restante do comando escrito seja executado pelo dispositivo servidor, que no caso é o OpenOCD.

 

Agora vamos apagar a memória interna do microprocessador.

 

(gdb) monitor flash erase_sector 0 0 last

 

Uma mensagem parecida como a seguinte é exibida.

 

erased sectors 0 through 11 on flash bank 0 in 15.635715s

 

Memória limpa! Falta a gravação do binário da aplicação.

 

(gdb) load

 

Caso o comando tenha sido executado com sucesso, a saída a seguir é exibida:

 

Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x1d1c lma 0x8000188
Loading section .data, size 0x24 lma 0x8001ea4
Start address 0x8000504, load size 7880
Transfer rate: 12 KB/sec, 2626 bytes/write.
(gdb) 

 

Com o binário gravado na memória interna do microprocessador, executamos o comando reset.

 

(gdb) monitor soft_reset_halt

 

Pronto para a depuração? Vamos criar um breakpoint na função main, a qual é chamada após a inicialização da biblioteca de runtime.

 

(gdb) break main

 

Se a seguinte mensagem aparecer, estamos indo bem!

 

Breakpoint 1 at 0x8000690: file /home/henrique/work/projects/stm32f4-discovery-bare-metal/hello_world/src/hello_world.c, line 114.

 

Se for executado o comando continue, a execução da aplicação é retomada e, em seguida, paralizada assim que a função main for chamada.

 

(gdb) continue

 

Como esperado, o breakpoint parou a execução momentaneamente da aplicação.

 

Continuing.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, main () at /home/henrique/work/projects/stm32f4-discovery-bare-metal/hello_world/src/hello_world.c:114
114	  SystemCoreClockUpdate();
(gdb)

 

Caso deseje depurar o código dentro da função SystemCoreClockUpdate, pode ser executado o comando step do GDB, o qual executa a próxima linha de código da aplicação depurada, que por sua vez está dentro dessa função. No entanto, caso queira executar essa chamada de função com um único comando, deve ser usado o comando next. Segue uma sequência de comandos next e step como exemplo:

 

(gdb) next
116	  if (SysTick_Config(SystemCoreClock / 1000)) {
(gdb) step
SysTick_Config (ticks=168000) at /home/henrique/work/projects/stm32f4-discovery-bare-metal/hello_world/cmsis/core/core_cm4.h:1283
1283	  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
(gdb) next
1285	  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
(gdb) 

 

Caso seja executado novamente o comando continue, a aplicação volta a ser executada, sem paradas desta vez.

 

(gdb) continue

 

A execução do programa é retomada. Como parar? Pode usar o comando Ctrl+C, o qual gera um signal SIGINT para o aplicativo GDB e, com isso, a aplicação é pausada.

 

Existem muito mais comandos para serem utilizados. A documentação do projeto GDB é um bom começo! Seguem alguns comandos bem bacanas para começar a se divertir com o GDB:

 

  • info locals: exibe o conteúdo das variáveis locais da função sendo executada;
  • disassemble: exibe o código Assembly gerado para a função sendo executada;
  • bt: exibe o backtrace da pilha, detalhando todas as chamadas às funções.

 

Dá trabalho depurar dessa forma, em linha de comando, certo? Num próximo artigo montaremos um ambiente com uma IDE open-source que realiza todo esse trabalho para a gente!

 

Bibliografia

 

GDB - GNU Project debugger

 

Outros artigos da série

<< GNU ARM Cross-toolchain – Configurando stack e heapGNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery - Parte 1 >>
NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Henrique Rossi
Engenheiro eletricista com ênfase em eletrônica e pós-graduado em Engenharia de Software. Comecei um mestrado, mas o interrompi. Especialista na área de sistemas embarcados, com mais de 12 anos de experiência em desenvolvimento de firmware (sistemas baremetal e baseados em RTOS) e Linux Embarcado. Atualmente sou administrador do site Embarcados, trabalho num fabricante de Set-Top Box e atuo como consultor/desenvolvedor na área de sistemas embarcados.

9
Deixe um comentário

avatar
 
8 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Henrique RossiEduardo ScherrerAlgoritmos DSP com a placa STM32F4Discovery - Parte IGNU ARM Cross-toolchain – Eclipse + FreeRTOS + GCC - Parte 2Embarcados – Sua fonte de informações sobre Sistemas Embarcados GNU Cross-toolchain - Processo de build Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
trackback

[…] GNU ARM Cross-toolchain – OpenOCD + GDB » 23-01-2014 […]

trackback

[…] GNU ARM Cross-toolchain – OpenOCD + GDB […]

trackback

[…] GNU ARM Cross-toolchain – OpenOCD + GDB […]

trackback

[...] GNU ARM Cross-toolchain – OpenOCD + GDB [...]

trackback

[...] Pronto! Agora a aplicação bare-metal está migrada para uma versão com o FreeRTOS. Vamos compilá-la e depurá-la com o que aprendemos até aqui? Conecte a sua placa STM32F4Discovery no seu PC com o cabo USB e execute os seguintes comandos para compilar a aplicação e iniciar o servidor GDB, o OpenOCD: [...]

trackback

[...] GNU ARM Cross-toolchain – OpenOCD + GDB [...]

Eduardo Scherrer
Visitante
Eduardo C. Scherrer

Olá Henrique,

Acompanho o site dos embarcados e está muito bom, cada dia uma informação valiosa. Parabéns pelo trabalho.

Estou muito interessado na continuidade deste post, por se tratar de usar um microcontrolador com tanto poder, e claro, utilizando uma ferramenta fácil acesso (pelo menos financeiramente falando).

Eu já li em alguns lugares, se não me engano no blog do Sergio Prado. Sobre utilizar uma IDE para fazer todo este processo de codificação, depuração e gravação do microcontrolador. Você abordará este assunto como continuidade?
Teria algum lugar para indicar onde posso continuar estes passos.

Obrigado.
E mais uma vez parabéns pelo trabalho de todos.

Eduardo Scherrer

Henrique Rossi
Visitante

Olá Eduardo!

Muito obrigado pelo comentário! Esta série vai ter continuação sim, e muita!! 🙂

Um dos seguintes posts será sobre a criação do ambiente gráfico, usando uma IDE (Eclipse), mas estamos escrevendo um artigo sobre o uso do FreeRTOS 8.0 nesta placa.

Pode continuar acompanhando a série, que ela vai evoluir.

Grande abraço,
Henrique

trackback

[...] GNU ARM Cross-toolchain – OpenOCD + GDB [...]