MCU & FPGA geral GDB para STM32: Cheat Sheet Profissional de Depuração com OpenOCD, HardFault e FreeRTOS

GDB para STM32: Cheat Sheet Profissional de Depuração com OpenOCD, HardFault e FreeRTOS


Casos Reais de Depuração em STM32 com GDB

Agora vamos sair do nível “comando isolado” e entrar no que realmente acontece no campo: firmware travando, HardFault misterioso, interrupção que nunca retorna, stack corrompida, task do FreeRTOS que some. Aqui eu vou mostrar o raciocínio técnico e como o GDB entra como ferramenta cirúrgica.


3.1 Debug de HardFault no Cortex-M (passo a passo real)

HardFault é o clássico pesadelo em STM32. Pode ser causado por:

  • Ponteiro inválido
  • Acesso a região proibida
  • Execução de instrução inválida
  • Stack overflow
  • Divisão por zero (se habilitada)

Quando o firmware cai em HardFault_Handler, a primeira coisa que você faz no GDB é:

break HardFault_Handler
continue

Assim que ele parar:

bt

Se o stack ainda estiver íntegro, o backtrace já pode mostrar a função que causou o problema. Mas muitas vezes ele para direto no handler e o backtrace não ajuda.

Estratégia avançada: inspecionar stack frame salvo

No Cortex-M, quando ocorre exceção, o hardware empilha automaticamente:

  • r0
  • r1
  • r2
  • r3
  • r12
  • lr
  • pc
  • xPSR

O sp naquele momento aponta para esse frame.

Então:

info registers

Observe $sp. Agora:

x/8xw $sp

O valor na posição correspondente ao PC salvo normalmente é o 7º item (offset 6 * 4 bytes).

Exemplo:

p/x *((uint32_t*)$sp + 6)

Isso revela o endereço onde a falha ocorreu.

Depois:

list *0x08001234

Agora você sabe exatamente a linha que causou o HardFault.

Esse procedimento separa um depurador amador de um engenheiro embarcado sério.


3.2 Detectando Stack Overflow

Sintomas típicos:

  • Firmware trava aleatoriamente
  • Variáveis globais mudam sem explicação
  • HardFault intermitente

Primeiro, verifique o stack pointer:

p/x $sp

Compare com o mapa de memória do STM32 (por exemplo, RAM começa em 0x20000000).

Se o SP estiver fora da faixa esperada → corrupção.

Você pode inspecionar a área da stack:

x/32xw 0x20000000

Se estiver usando FreeRTOS, cada task tem sua própria stack. Você pode:

info threads
thread 2
bt

Se estiver usando OpenOCD com suporte RTOS, ele já mostra tasks como threads.


3.3 Debug de Interrupção que trava o sistema

Um erro clássico é ISR muito longa ou com erro lógico.

Coloque breakpoint na ISR:

break EXTI0_IRQHandler

Continue.

Quando parar, faça:

bt

Verifique se ela está sendo chamada em loop.

Se você suspeita que a flag não está sendo limpa, pode verificar registradores do periférico diretamente:

x/1xw 0x40010410

Se necessário, force limpeza manual:

set {uint32_t}0x40010410 = 0

Isso permite validar hipóteses sem recompilar.


3.4 Debug de variáveis sendo alteradas por DMA

Cenário clássico: buffer de ADC + DMA e dados aparecem corrompidos.

Você pode colocar watchpoint:

watch adcBuffer[10]

Quando o DMA escrever, o core para.

Isso é extremamente útil para descobrir se:

  • DMA está configurado errado
  • Overrun está ocorrendo
  • Ponteiro está errado

Limitação: watchpoints são limitados por hardware.


3.5 Depuração com FreeRTOS

Se estiver usando FreeRTOS no STM32, o GDB pode enxergar tasks como threads (dependendo da configuração do OpenOCD).

Comandos úteis:

info threads

Selecionar task:

thread 3

Ver backtrace da task:

bt

Isso é fundamental para:

  • Task bloqueada em semáforo
  • Deadlock
  • Stack overflow por task

Você também pode inspecionar TCB manualmente:

p *pxCurrentTCB

Se estiver com símbolos.


3.6 Debug de código otimizado (-O2 / -O3)

Aqui está um ponto crítico.

Quando o firmware está compilado com -O2, você pode observar:

  • Variáveis “sumindo”
  • Linhas puladas
  • Breakpoint não sendo atingido

Por quê?

Porque o compilador:

  • Reordena instruções
  • Remove variáveis temporárias
  • Inline functions

Solução prática durante debug:

Use -Og.

Se for obrigado a usar -O2, utilize:

disassemble

E:

layout asm

Ou:

stepi

Você passa a depurar em nível de assembly.


3.7 Arquivo .gdbinit para automatizar sessão

Você pode criar um .gdbinit no diretório do projeto:

Exemplo:

target extended-remote :3333
monitor reset halt
load
break main

Assim, toda vez que abrir:

arm-none-eabi-gdb firmware.elf

Ele já conecta automaticamente.

Isso economiza tempo e padroniza processo.


3.8 Diagnóstico de travamento por clock ou PLL

Se o firmware altera clock cedo (SystemInit), pode perder comunicação com debugger.

Solução:

  1. Conectar
  2. Dar reset halt
  3. Colocar breakpoint antes da configuração de PLL
break SystemClock_Config
continue

Assim você intercepta antes do clock mudar.


3.9 Quando o STM32 não conecta mais

Cenário: firmware configura pinos SWD como GPIO.

Solução:

Use reset sob controle:

monitor reset halt

Ou inicie OpenOCD com:

reset_config srst_only srst_nogate

Ou conecte segurando reset físico.


Até aqui cobrimos debug real de:

  • HardFault
  • Stack corruption
  • ISR problemáticas
  • DMA
  • FreeRTOS
  • Código otimizado
  • Clock misconfiguration
  • Perda de debug
  • Debug de periféricos específicos (GPIO, USART, ADC, TIM) via registradores
  • Uso de GDB para profiling simples
  • Script avançado com macros GDB
  • Integração com VSCode e CLI
  • Técnicas profissionais de depuração em produção
0 0 votos
Classificação do artigo
Inscrever-se
Notificar de
guest
0 Comentários
mais antigos
mais recentes Mais votado
Feedbacks embutidos
Ver todos os comentários

Related Post

Lançamento do site Basicão dos Microcontroladores: um novo espaço para aprender sobre microcontroladoresLançamento do site Basicão dos Microcontroladores: um novo espaço para aprender sobre microcontroladores

Lançamento do site Basicão dos Microcontroladores: um novo espaço para aprender sobre microcontroladores Com grande entusiasmo, anunciamos o lançamento do Basicão dos Microcontroladores, acessível pelo endereço https://mcu.tec.br. Este novo site

0
Adoraria saber sua opinião, comente.x