Depuração de Periféricos, Barramentos e Técnicas Profissionais com GDB no STM32
Agora vamos elevar o nível. Aqui entramos no território onde você não está mais apenas “seguindo código”, mas analisando o estado real do hardware através da memória mapeada do STM32. Essa é a diferença entre depuração de software comum e depuração embarcada profissional.
Em STM32, praticamente tudo é memória mapeada: GPIO, USART, ADC, TIM, RCC, DMA, etc. O GDB permite inspecionar esses registradores diretamente.
4.1 Depuração de GPIO via registradores
Suponha que um LED não esteja acendendo.
Você suspeita do registrador ODR (Output Data Register).
Exemplo genérico (endereço ilustrativo):
x/1xw 0x48000014
Isso lê um word de 32 bits.
Se quiser verificar um bit específico:
p/x (*(uint32_t*)0x48000014) & (1 << 5)
Se for zero, o pino está baixo.
Você pode forçar manualmente:
set {uint32_t}0x48000014 |= (1 << 5)
Se o LED acender, o problema é lógico no firmware, não elétrico.
Isso evita recompilar código apenas para testar hipótese.
4.2 Depuração de USART (UART)
Caso típico: nada aparece na serial.
Você pode inspecionar:
- SR (status register)
- DR (data register)
- CR1, CR2, CR3
Exemplo:
x/4xw 0x40011000
Verifique se:
- TXE (Transmit Empty) está ativo
- RXNE (Receive Not Empty) está ativo
Se TXE nunca fica 1, pode haver problema de clock no RCC.
Então inspecione RCC:
x/1xw 0x40023840
Se o clock do periférico não estiver habilitado, o erro está no RCC, não na UART.
4.3 Depuração de ADC + DMA
Você configurou ADC com DMA circular, mas os valores parecem errados.
Primeiro: confirme que o ADC está realmente convertendo.
Verifique status:
x/1xw ADC_SR_ADDRESS
Verifique buffer DMA:
x/16xw adcBuffer
Se os valores não mudam, verifique:
- DMA NDTR (contador restante)
- Endereço de memória configurado
Você pode verificar registradores DMA diretamente.
Isso permite descobrir se o problema está:
- No ADC
- No DMA
- No ponteiro do buffer
- No alinhamento de memória
4.4 Depuração de Timer (TIM)
Se interrupção do timer não dispara:
- Verifique se contador está incrementando:
x/1xw TIMx_CNT_ADDRESS
Execute várias vezes.
Se não mudar → clock do timer não habilitado.
- Verifique PSC e ARR:
x/2xw TIMx_PSC_ADDRESS
Se PSC for muito alto, timer pode parecer parado.
4.5 Inspeção de mapa de memória completo
Você pode inspecionar regiões inteiras:
x/128xw 0x20000000
Para analisar RAM inteira.
Ou Flash:
x/64xw 0x08000000
Isso é útil para:
- Verificar se firmware foi gravado corretamente
- Verificar bootloader
- Conferir vetor de interrupção
Para ver vetor de reset:
x/2xw 0x08000000
Primeira palavra → stack inicial
Segunda palavra → Reset_Handler
4.6 Debug de barramento e alinhamento
Cortex-M gera HardFault se houver acesso desalinhado (dependendo da configuração).
Se você suspeita de acesso inválido:
disassemble
Verifique se está acessando endereço não múltiplo de 4 para word.
Você também pode inspecionar SCB (System Control Block):
x/4xw 0xE000ED28
Esse endereço contém registradores de fault status.
Particularmente:
- CFSR
- HFSR
Eles indicam tipo exato da falha.
4.7 Profiling simples com GDB
Embora GDB não seja profiler dedicado, você pode medir tempo entre breakpoints.
Exemplo:
- Coloque breakpoint antes da função crítica.
- Leia valor de um timer livre:
p TIM2->CNT
- Continue até final.
- Leia novamente.
Diferença → tempo de execução.
Alternativamente, você pode ler DWT_CYCCNT (contador de ciclos):
p/x *(uint32_t*)0xE0001004
Se estiver habilitado.
Isso permite análise de performance sem instrumentação invasiva.
4.8 Macros e automação avançada no GDB
Você pode criar comandos customizados:
define reset_run
monitor reset halt
load
break main
continue
end
Agora basta digitar:
reset_run
Você também pode automatizar dump de registradores de fault:
define fault_info
x/4xw 0xE000ED28
end
Isso é extremamente útil em times de desenvolvimento.
4.9 Integração com VSCode (modo profissional)
Embora você esteja usando GDB puro aqui, no ambiente profissional normalmente usa-se:
- VSCode + Cortex-Debug extension
- OpenOCD
- arm-none-eabi-gdb
O VSCode apenas gera os comandos GDB automaticamente.
O que realmente importa é dominar os comandos, porque quando algo dá errado no IDE, você cai para CLI.
4.10 Técnicas Profissionais de Depuração
Aqui está o que engenheiros experientes fazem:
- Sempre compilar debug com -Og
- Usar asserts em firmware
- Verificar stack watermark
- Inspecionar registradores de fault antes de reiniciar
- Nunca confiar apenas em printf
- Confirmar estado real do hardware via memória mapeada
- Usar watchpoints para corrupção silenciosa
- Isolar problemas em nível de registrador antes de culpar HAL
Depuração embarcada é análise de estado, não tentativa e erro.
Até agora cobrimos:
- Uso completo do GDB
- Debug de HardFault
- Debug de ISR
- Debug com FreeRTOS
- Debug de periféricos
- Inspeção de memória mapeada
- Profiling básico
- Automação com macros