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


Laboratório Prático Completo de Depuração com STM32 + GDB (Do Zero ao HardFault)

Agora vamos consolidar tudo em um laboratório prático realista. A ideia aqui é simular um projeto STM32 baremetal com um erro proposital, e usar o GDB como ferramenta de engenharia — não como ferramenta de curiosidade.

O cenário será o seguinte:

  • STM32 (qualquer Cortex-M3/M4/M7 serve)
  • Código baremetal simples
  • Um ponteiro inválido causando HardFault
  • Uso sistemático do GDB para descobrir a causa

Esse tipo de exercício é extremamente formador.


6.1 Código com erro proposital

Considere o seguinte trecho em C:

#include <stdint.h>

volatile uint32_t *ptr;

void faulty_function(void)
{
    *ptr = 0x12345678;  // ERRO: ptr nunca foi inicializado
}

int main(void)
{
    faulty_function();

    while(1);
}

Esse código compila perfeitamente. Mas ao executar, vai gerar HardFault porque ptr aponta para endereço indefinido.

Compile com:

-g -Og

Gere o ELF.

Suba o OpenOCD e conecte com:

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

6.2 Executando passo a passo

Quando parar em main:

next

Agora estamos prestes a entrar em faulty_function.

Use:

step

Estamos dentro da função.

Antes de executar a linha problemática:

p ptr

Você verá algo como:

$1 = (volatile uint32_t *) 0x00000000

Ou algum lixo.

Agora execute:

next

O sistema vai cair em HardFault_Handler.


6.3 Investigando o HardFault profissionalmente

Primeiro:

bt

Pode não mostrar corretamente a origem.

Agora vamos aplicar técnica de engenharia.

Veja registradores:

info registers

Observe $sp.

Agora:

x/8xw $sp

Extraia o PC salvo:

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

Suponha que retorne:

0x0800012C

Agora:

list *0x0800012C

Você verá a linha:

*ptr = 0x12345678;

Diagnóstico concluído: acesso inválido por ponteiro não inicializado.

Isso é engenharia de depuração.


6.4 Corrigindo e validando

Corrija código:

volatile uint32_t safe_variable;
volatile uint32_t *ptr = &safe_variable;

Recompile.

Repita processo:

monitor reset halt
load
continue

Agora não ocorre HardFault.


6.5 Segundo laboratório: Stack Overflow real

Agora vamos criar um erro diferente:

void recursive_function(void)
{
    uint8_t buffer[1024];
    recursive_function();
}

Isso gera overflow rapidamente.

Repita o processo.

Quando cair em HardFault:

info registers

Observe $sp.

Se estiver abaixo do limite de RAM → overflow confirmado.


6.6 Terceiro laboratório: Corrupção silenciosa

Código:

uint32_t array[4];

void corrupt(void)
{
    for(int i = 0; i < 10; i++)
        array[i] = i;
}

Erro clássico: escreve além do limite.

Coloque watchpoint:

watch array[4]
continue

Quando escrever fora do limite, o GDB interrompe.

Você verá exatamente onde ocorre a corrupção.

Isso é extremamente poderoso para sistemas com DMA ou múltiplas tasks.


6.7 Analisando registradores de fault (SCB)

Quando ocorre HardFault, registre:

x/4xw 0xE000ED28

Esse endereço contém CFSR.

Decodificação:

  • Bit 0–7: Memory Management Fault
  • Bit 8–15: Bus Fault
  • Bit 16–31: Usage Fault

Se for UsageFault por divisão por zero, você verá bit correspondente ativo.

Isso permite classificar tipo exato da falha.


6.8 Laboratório com periférico: GPIO que não responde

Simule erro: esqueça de habilitar clock do GPIO.

Quando LED não acender:

No GDB:

x/1xw RCC_AHB1ENR_ADDRESS

Verifique se bit do GPIO está habilitado.

Se não:

set {uint32_t}RCC_AHB1ENR_ADDRESS |= (1<<0)

Se LED acender → erro confirmado no firmware.

Isso economiza ciclos enormes de debug.


6.9 Método Profissional de Debug (Modelo Mental)

Sempre siga esta ordem:

  1. Sistema travou?
  2. Onde está o PC?
  3. Stack está íntegra?
  4. Registradores de fault indicam o quê?
  5. Periférico realmente está habilitado?
  6. Clock realmente está ativo?
  7. DMA realmente está escrevendo?
  8. Interrupção realmente está limpando flag?

Nunca comece alterando código aleatoriamente.

Comece medindo estado.


6.10 Consolidação: Checklist de Depuração STM32

Quando algo falhar:

  • monitor reset halt
  • bt
  • info registers
  • x/8xw $sp
  • list *PC
  • Verificar SCB fault status
  • Verificar clock RCC
  • Verificar registrador do periférico
  • Verificar stack pointer
  • Verificar limites de array

Se você seguir esse protocolo, praticamente todo problema embarcado vira resolvível.

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

0
Adoraria saber sua opinião, comente.x