Manual
do
Maker
.
com
No artigo "Como transformar um BluePill em JTAG" vimos alguns comandos GDB que já são suficientes para um debug mínimo. Dá pra fazer muito mais, não só por linha de comando, mas não é uma má ideia aprender fazer algumas coisas por linha de comando, então vamos montar nossa lista de referências dos comandos mais aplicáveis.
No artigo supracitado vimos como instalar o gdb-multiarch e como executá-lo. Basta chamar o comando gdb-multiarch. O resultado será um shell com um prompt (gdb), onde podemos digitar os demais comandos.
Estando no prompt do GDB, simplesmente digite target extended-remote /dev/ttyACM0. Se a porta for outra, se o sistema operacional for outro, adapte a porta para corresponder ao seu sistema. Se precisa saber como identificar a porta, mais uma vez, o artigo citado no primeiro parágrafo o auxiliará com isso tudo.
Digite monitor help no prompt do GDB para ver os comandos disponíveis.
A lista de comandos é context sensitive, isto é, muda conforme o alvo. O comando para o alvo STM32: monitor erase_mass, não estará disponível até que o alvo seja escaneado.
Há dois comandos para varrer por dispositivos que estejam usando a interface JTAG ou SWD; monitor jtag_scan e monitor swdp_scan.
Para desconectá-lo, use monitor tpwr enable. Para conectar-se a ele, use attach N, onde N é o número do dispositivo que aparece.
Esse comando instrui o GDB a permitir acesso à memória fora do dispositivo, conhecida como memory map. Use: set mem inaccessible-by-default off.
Para carregar o firmware para o dispositivo alvo, usamos load /tmp/arduino_build_123456/firmware.elf para debug. Esse caminho e nome de arquivo são parcialmente fictícios, uma vez que o path se refere ao mesmo caminho que encontramos a compilação da IDE do Arduino no Linux, mudando basicamente os números e o nome do firmware, para o correspondente ao programa compilado na IDE do Arduino.
Para fazer o debug do artigo anterior, usei seguidamente o comando file /tmp/arduino_build_123456/firmware.elf, com os mesmos princípios descritos acima. A diferença é que aqui deveremos confirmar com um y e depois disso poderemos fazer o debug de um modo mais fluido.
Podemos executar o firwamre de teste com run até que seja interrompido por outro evento, enquanto start rodará da inicialização até a entrada de main. Usando a API do Arduino fica um pouco estranho, porque invés da inicialização de variáveis, declarações de função e outras coisas que acontecem fora de main, com a API do Arduino temos setup e loop dentro de main, então não tem muito proveito nesse momento.
Podemos interromper a aplicação com Ctrl+C também, quando em execução.
Essa é a parte mais gostosa da depuração. Podemos adicionar pontos de parada no código e assim analisar o funcionamento de uma função, o retorno de uma variável, encontrar um ponto de exceção no código e outras coisas mais. Podemos também assistir diretamente a mudança de valor de uma variável, com watch <variável>.
Para adicionar um breakpoint podemos usar a forma break <função> ou break
Lembre-se: Breakpoints interrompem quando o ponto alvo entra em seu momento de execução. Os watchpoints interromperão quando a variável monitorada mudar seu valor.
Esse exemplo de comandos GDB acima é baseado nesse código:
uint16_t i = 0;
void setup() {
// initialize digital pin PC13 as an output.
pinMode(PB12, OUTPUT);
pinMode(PC13, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(PB12, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(PC13, HIGH);
delay(500); // wait for a second
digitalWrite(PB12, LOW); // turn the LED off by making the voltage LOW
digitalWrite(PC13, LOW);
delay(500); // wait for a second
teste();
}
void teste(){
for (uint8_t j=0; j<20;j++){
digitalWrite(PB12, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(PC13, HIGH);
delay(300); // wait for a second
digitalWrite(PB12, LOW);
digitalWrite(PC13, LOW);
// turn the LED off by making the voltage LOW
delay(100);
i++;
}
}
Podemos também avaliar variáveis, memória ou registradores, usando os comandos print
Um tanto mais avançado, podemos também fazer um dump da memória para um formato hexa Intel usando dump ihex memory
Se quiser desconectar do dispositivo, use detach. Usando kill, o alvo será reiniciado ao desconectar.
O GDB tem vários outros recursos, mas utilizá-lo através de uma IDE é bastante cômodo, e leva o desenvolvimento para microcontroladores a outro nível. Veremos isso em breve, acompanhe!
Se quiser saber mais sobre o GDB, visite o site oficial do projeto.
Uma referência espetacular pode ser encontrada nesse outro link.
Se não pretende fazer seu próprio JTAG, o J-Link que estou usando é da Werneck Eletronics, que você pode adquirir por um excelente preço na Shopee. Se não conhece a Shopee, vale a pena. Como não tem o achaque do MercadoLivre, os preços são melhores. A MASUGUX também adotou e acredito que seja uma tendência.
Eles têm também um outro modelo que presumo ser a mesma coisa, mas não posso confirmar. Confira nesse link.
Esse vídeo demonstra um processo completo o suficiente para servir de parâmetro. Olha só que delícia é usar um debugger!
Revisão: Ricardo Amaral de Andrade
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.