---
title: "probe-rs 2026: Debug de Rust Embarcado | Rust Brasil"
url: "https://rustlang.com.br/blog/probe-rs-debug-rust-embarcado-2026/"
markdown_url: "https://rustlang.com.br/blog/probe-rs-debug-rust-embarcado-2026.MD"
description: "Aprenda a usar probe-rs em 2026 para gravar, executar e depurar firmware Rust em STM32, nRF, RP2040 e RISC-V, com RTT, defmt e VS Code."
date: "2026-07-24"
author: "Equipe Rust Brasil"
---

# probe-rs 2026: Debug de Rust Embarcado | Rust Brasil

Aprenda a usar probe-rs em 2026 para gravar, executar e depurar firmware Rust em STM32, nRF, RP2040 e RISC-V, com RTT, defmt e VS Code.


**O `probe-rs` é a opção mais direta para gravar, executar e depurar firmware Rust em muitos microcontroladores ARM e RISC-V.** Ele conversa com probes como ST-Link, J-Link e CMSIS-DAP, entende os metadados do binário Rust e reúne flash, controle de execução, RTT e integração com `defmt` em uma única stack. Para começar, instale as ferramentas, confirme que o probe USB aparece, selecione o chip correto e configure o `runner` do Cargo.

Este guia apresenta um fluxo reproduzível para **debug de Rust embarcado em 2026**, do primeiro `probe-rs list` até breakpoints no VS Code. O foco é entender as camadas para não cair no ciclo de reinstalar tudo quando o problema real está em permissões USB, alimentação da placa, target de compilação ou identificação incorreta do microcontrolador.

Se você ainda está montando a stack, leia primeiro o panorama de [Rust para sistemas embarcados](/artigos/rust-para-embarcados/) e o tutorial de [Embassy para IoT](/blog/rust-embedded-embassy-iot-2026/). Para instalar compilador, Cargo e componentes, use o [guia do rustup](/ecossistema/rustup/).

## O que o probe-rs faz

Em uma sessão de desenvolvimento embarcado existem quatro elementos diferentes:

1. **o computador**, onde Cargo compila o firmware;
2. **o probe de depuração**, conectado por USB ao computador;
3. **a interface física**, normalmente SWD ou JTAG;
4. **o microcontrolador**, onde o programa é gravado e executado.

O probe-rs é o software que coordena essa conversa. Ele pode:

- enumerar probes conectados;
- identificar e anexar-se a um target compatível;
- apagar e programar a memória flash;
- resetar, iniciar, pausar e continuar o processador;
- ler memória, registradores e estado dos cores;
- executar um ELF e exibir mensagens RTT;
- decodificar logs compactos gerados pelo `defmt`;
- servir como backend de debug para editores compatíveis com DAP;
- gerar um arquivo de diagnóstico quando uma sessão falha.

A vantagem para projetos Rust é a integração natural com Cargo e com o formato ELF produzido pelo toolchain. Você não precisa transformar toda execução em uma sequência manual de `objcopy`, servidor GDB, porta TCP e cliente separado. Essas peças continuam úteis em situações específicas, mas deixam de ser obrigatórias no caminho mais comum.

## probe-rs, OpenOCD, cargo-embed e cargo-flash

As ferramentas se sobrepõem, mas não são sinônimos:

| Ferramenta | Papel principal | Quando faz sentido |
|---|---|---|
| **probe-rs** | Comunicação, flash, execução e debug | Ponto de partida para projetos Rust modernos |
| **OpenOCD** | Servidor de debug tradicional e altamente configurável | Targets, scripts de placa ou fluxos legados já consolidados |
| **cargo-embed** | Execução configurada por `Embed.toml` sobre probe-rs | Projeto quer padronizar reset, RTT e opções de flash |
| **cargo-flash** | Gravação de firmware pela linha de comando | Automação que precisa somente programar a flash |
| **GDB** | Cliente de debug clássico | Equipe depende do fluxo GDB ou de integrações específicas |

Em um projeto novo, comece com `probe-rs run` e `probe-rs download`. Adicione `cargo-embed` quando um arquivo declarativo reduzir repetição para a equipe. Mantenha OpenOCD se a placa ou o processo de homologação depende de scripts já testados — trocar ferramenta sem resolver uma dor concreta só aumenta a superfície de configuração.

## Como instalar o probe-rs

Quem já usa Rust pode instalar a suíte pela própria toolchain:

```bash
cargo install probe-rs-tools --locked
probe-rs --version
```

A opção `--locked` pede ao Cargo que respeite o lockfile publicado pelo pacote, o que tende a tornar a instalação mais reproduzível. A compilação pode demorar porque inclui dependências de USB, protocolos de debug e suporte a vários targets.

O projeto também distribui binários para plataformas suportadas. Em uma equipe, escolha um método e documente a versão esperada. Evite deixar cada pessoa com uma versão desconhecida quando o firmware depende de um chip recém-adicionado ou de um comportamento específico do debugger.

Depois da instalação, conecte a placa e liste os probes:

```bash
probe-rs list
```

Se nenhum dispositivo aparecer, ainda não adianta investigar o código Rust. Primeiro resolva a camada USB.

### Linux: permissões e regras udev

No Linux, o dispositivo pode aparecer no `lsusb`, mas continuar inacessível ao usuário comum. Instale as regras `udev` recomendadas pelo projeto ou pela distribuição e recarregue-as. Dependendo do sistema, também será necessário reconectar o probe, reiniciar a sessão ou ajustar o grupo que possui acesso ao dispositivo.

Use este diagnóstico inicial:

```bash
lsusb
probe-rs list
```

Executar tudo com `sudo` pode mascarar a falta de permissões, além de criar artefatos do Cargo pertencentes ao usuário root. Corrija a regra do dispositivo em vez de transformar privilégio elevado em rotina.

### Windows e macOS

No Windows, confira se o probe está usando o driver esperado. Ferramentas do fabricante podem instalar um driver incompatível com acesso genérico via USB, dependendo do modelo e do modo. No macOS, confirme também cabos, hubs e permissões do ambiente de desenvolvimento.

Em qualquer sistema, teste um cabo USB conhecido por transportar **dados**. Cabos destinados somente a carga são uma causa surpreendentemente frequente de “probe não encontrado”.

## Descobrindo o chip correto

O probe e o target são coisas diferentes. Um ST-Link pode ser detectado corretamente, mas o probe-rs ainda precisa saber qual microcontrolador está conectado.

Pesquise a lista de chips suportados:

```bash
probe-rs chip list | grep -i stm32f411
probe-rs chip list | grep -i rp2040
```

Use o identificador exato retornado pela ferramenta. A marca impressa na placa nem sempre basta: placas da mesma família podem usar variantes com flash, RAM, encapsulamento ou revisão diferentes.

Para anexar explicitamente:

```bash
probe-rs attach --chip STM32F411CEUx
```

O nome acima é apenas um exemplo. Substitua-o pelo target real da sua placa. Se a conexão falhar, confira:

- alimentação e terra comum;
- fios SWDIO, SWCLK, GND e, quando necessário, RESET;
- tensão lógica compatível;
- firmware atualizado do probe;
- chip selecionado;
- velocidade de comunicação;
- estado de proteção da flash.

## Configurando o target de compilação

O probe-rs não corrige um firmware compilado para a arquitetura errada. Um STM32F411, por exemplo, usa Cortex-M4F e normalmente recebe código para `thumbv7em-none-eabihf`.

Instale o target:

```bash
rustup target add thumbv7em-none-eabihf
```

No projeto, crie `.cargo/config.toml`:

```toml
[build]
target = "thumbv7em-none-eabihf"

[target.thumbv7em-none-eabihf]
runner = "probe-rs run --chip STM32F411CEUx"

[env]
DEFMT_LOG = "info"
```

Com isso, `cargo run --release` compila o ELF e chama o probe-rs automaticamente:

```bash
cargo run --release
```

Não copie o target acima para ESP32, RP2040, nRF ou RISC-V sem verificar a arquitetura. O [rustup](/instalacao/rustup/) permite instalar vários targets lado a lado, mas o projeto deve escolher o correto.

## Gravar, executar e apagar

Para compilar e executar pelo runner:

```bash
cargo run --release
```

Para trabalhar diretamente com o binário:

```bash
cargo build --release
probe-rs run --chip STM32F411CEUx \
  target/thumbv7em-none-eabihf/release/meu-firmware
```

Quando você quer apenas programar a flash sem manter uma sessão de execução:

```bash
probe-rs download --chip STM32F411CEUx \
  target/thumbv7em-none-eabihf/release/meu-firmware
```

Também existe operação de apagamento. Use-a com intenção, especialmente em dispositivos que armazenam calibração, bootloader, credenciais provisionadas ou dados persistentes em regiões da flash. Em hardware de desenvolvimento, um erase completo pode resolver proteção ou conteúdo inconsistente; em produto provisionado, pode destruir informação importante.

## Logging eficiente com defmt e RTT

`println!` não está disponível da mesma maneira em um ambiente `#![no_std]`, e enviar strings formatadas por UART consome flash, RAM, CPU e largura de banda. O `defmt` reduz esse custo ao deixar boa parte da formatação no computador.

Dependências típicas:

```toml
[dependencies]
defmt = "0.3"
defmt-rtt = "0.4"
panic-probe = { version = "0.3", features = ["print-defmt"] }
```

No firmware:

```rust
#![no_std]
#![no_main]

use defmt::info;
use {defmt_rtt as _, panic_probe as _};

#[cortex_m_rt::entry]
fn main() -> ! {
    let versao = 1_u8;
    info!("firmware iniciado, versao={=u8}", versao);

    loop {
        cortex_m::asm::wfi();
    }
}
```

Ao executar o ELF com `probe-rs run`, a ferramenta encontra o canal RTT e usa os metadados do binário para reconstruir as mensagens no host. Preserve informações de debug no perfil release:

```toml
[profile.release]
debug = 2
lto = true
opt-level = "s"
codegen-units = 1
```

`debug = 2` aumenta o tamanho do arquivo ELF no computador, mas não significa que todas essas informações serão gravadas na flash. O arquivo usado pelo debugger precisa conter símbolos suficientes para backtraces, nomes de funções e decodificação correta.

## Quando usar cargo-embed

O `cargo-embed` é útil quando o time quer guardar opções de execução em um arquivo `Embed.toml`. Um exemplo conceitual:

```toml
[default.general]
chip = "STM32F411CEUx"

[default.reset]
enabled = true
halt_afterwards = false

[default.rtt]
enabled = true
```

A configuração aceita depende da versão instalada. Valide os campos na documentação correspondente à sua versão em vez de copiar um `Embed.toml` antigo sem revisão.

Depois, o fluxo costuma ser:

```bash
cargo embed --release
```

A vantagem não é “ser mais poderoso” que a base probe-rs, e sim transformar opções repetidas em configuração versionada. Para um exemplo rápido ou uma CI de flash, a CLI direta pode ser mais clara.

## Debug com breakpoints no VS Code

O probe-rs oferece integração com o **Debug Adapter Protocol (DAP)**, usado por editores como VS Code. Na prática, uma extensão compatível inicia uma sessão, carrega o ELF, conecta-se ao probe e traduz ações do editor — breakpoint, step over, step into, continue e inspeção — para o backend.

O fluxo geral é:

1. compile o firmware com símbolos de debug;
2. instale uma extensão de debug compatível com probe-rs;
3. informe o chip e o caminho do ELF;
4. selecione o core quando o dispositivo tiver mais de um;
5. inicie a sessão com a placa conectada;
6. coloque breakpoints em código executável, não em trecho otimizado para fora.

Um arquivo de configuração varia conforme a extensão e sua versão. Não trate um `launch.json` encontrado em tutorial antigo como API permanente. Os dados essenciais, porém, permanecem os mesmos: **chip**, **ELF**, **core**, comportamento de reset e modo de conexão.

O [rust-analyzer](/blog/rust-analyzer-guia-configuracao-2026/) continua responsável por autocompletar, navegação e diagnósticos do código. O adaptador do probe-rs cuida da execução no hardware. São ferramentas complementares.

## Por que o breakpoint não para

Em firmware otimizado, uma linha do arquivo-fonte pode não corresponder a uma instrução exclusiva. O compilador pode:

- remover código sem efeito observável;
- embutir uma função no chamador;
- fundir ou reordenar instruções;
- manter valores somente em registradores;
- transformar várias linhas em um único bloco.

Para investigar, compare um build de desenvolvimento com um release que preserve símbolos:

```bash
cargo build
cargo build --release
```

O build sem otimização costuma oferecer stepping mais previsível, mas pode mudar timing, consumo de flash e comportamento de concorrência. Bugs dependentes de tempo precisam ser analisados também em condições próximas da produção.

## Problemas comuns e como diagnosticar

### Nenhum probe encontrado

1. confirme o cabo de dados;
2. teste outra porta USB e evite hubs no primeiro diagnóstico;
3. rode `lsusb` ou o gerenciador de dispositivos;
4. instale regras udev ou driver adequado;
5. atualize o firmware do probe quando aplicável;
6. rode `probe-rs list` novamente.

### Probe aparece, mas não conecta ao chip

Confira pinagem SWD/JTAG, GND compartilhado, alimentação, reset e chip selecionado. Reduza a velocidade de debug se o sinal estiver ruim ou se o target estiver usando clock incomum. Algumas placas exigem conexão durante reset quando o firmware reconfigura rapidamente os pinos de debug ou entra em baixo consumo.

### Flash falha ou verificação não confere

Possíveis causas incluem proteção de leitura/escrita, região incorreta, target errado, queda de alimentação e bootloader ocupando a mesma área. Leia o mapa de memória e o linker script antes de apagar tudo.

### defmt não mostra mensagens

Confirme que:

- `defmt-rtt` foi vinculado ao firmware;
- existe um panic handler compatível;
- o ELF executado é exatamente o binário gravado;
- informações de debug não foram removidas;
- o código realmente alcança a chamada de log;
- o nível definido por `DEFMT_LOG` permite a mensagem.

### A sessão trava após um panic

Isso pode ser o comportamento esperado do panic handler. Use `panic-probe` com saída defmt, preserve símbolos e examine o backtrace. Em firmware, “travar” em um loop após panic é frequentemente preferível a continuar com estado inválido.

## Fluxo recomendado para equipes

Um projeto embarcado reproduzível deve versionar mais do que o `src/main.rs`:

- `rust-toolchain.toml` com canal e targets necessários;
- `.cargo/config.toml` com target e runner;
- linker script e arquivo de memória;
- identificação exata da placa e do chip;
- versão ou método de instalação do probe-rs;
- diagrama dos pinos de debug;
- comandos de build, flash, teste e recuperação;
- política para apagar flash e preservar dados provisionados.

Na CI, compile e execute testes que não dependem de hardware. Para validação real, uma bancada **hardware-in-the-loop** pode conectar placas a runners controlados, gravar o firmware, coletar RTT e validar periféricos. Esse tipo de experiência também é valorizado em [carreiras de Rust embarcado](/carreira/nicho-embedded/) e ajuda a construir um portfólio mais convincente do que somente um LED piscando.

## probe-rs por plataforma

### STM32 e nRF

São famílias muito comuns no ecossistema ARM Cortex-M. ST-Link, J-Link e probes CMSIS-DAP aparecem bastante em placas de desenvolvimento. Confirme o part number completo e o core correto.

### RP2040 e RP2350

A Raspberry Pi Debug Probe e outros dispositivos CMSIS-DAP oferecem um caminho acessível para SWD. O UF2 continua prático para o primeiro flash, mas uma conexão de debug permite breakpoints, inspeção e ciclos mais rápidos.

### ESP32 e RISC-V

A família ESP32 possui variantes Xtensa e RISC-V, com toolchains e mecanismos de flash diferentes. Não presuma que um comando válido para ESP32-C3 serve para um ESP32 clássico. Em vários projetos, `espflash` e ferramentas do ecossistema `esp-rs` complementam ou substituem partes do fluxo, conforme o chip e a interface.

Para uma comparação com outra linguagem voltada a sistemas e interoperabilidade com C, o <a href="https://ziglang.com.br/artigos/zig-para-embarcados/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'ziglang.com.br' })">guia de Zig para embarcados</a> mostra uma abordagem diferente para firmware e cross-compilation.

## Checklist rápido

Antes de abrir o debugger, confirme:

- o probe aparece em `probe-rs list`;
- o chip exato existe em `probe-rs chip list`;
- a placa está alimentada e compartilha GND com o probe;
- SWDIO/SWCLK ou JTAG estão ligados corretamente;
- o target do Rust corresponde à arquitetura do chip;
- o linker script corresponde à memória real;
- o runner aponta para o chip correto;
- o ELF preserva símbolos de debug;
- `defmt-rtt` e o panic handler estão vinculados;
- o firmware gravado é o mesmo ELF aberto no debugger.

## Conclusão

O **probe-rs** reduz bastante o atrito entre “o firmware compilou” e “eu entendo o que está acontecendo no microcontrolador”. Com uma única stack você pode detectar o probe, gravar a flash, executar o ELF, coletar logs compactos com `defmt` e iniciar uma sessão gráfica de debug.

A parte mais importante é diagnosticar por camadas. Primeiro USB e permissões; depois probe e fiação; em seguida chip, target e mapa de memória; somente então firmware, símbolos e breakpoints. Essa ordem evita perder horas alterando código quando o computador nem consegue conversar com a placa.

Para continuar, pratique com o [guia de Rust embarcado](/artigos/rust-para-embarcados/), experimente tarefas assíncronas no [Embassy](/blog/rust-embedded-embassy-iot-2026/) e conheça o cenário de [Linux embarcado e IoT industrial](/blog/rust-linux-embarcado-iot-industrial-2026/). Se o objetivo é carreira, veja também as [faixas salariais de firmware e sistemas embarcados](/blog/salario-engenheiro-firmware-embarcados-brasil-2026/).

## Perguntas frequentes

### O que é o probe-rs?

É uma suíte aberta para flash e debug de microcontroladores ARM e RISC-V. Ela conecta o computador a probes compatíveis, controla o target e integra o fluxo com binários e ferramentas do ecossistema Rust.

### Como instalar o probe-rs em 2026?

Uma opção é executar `cargo install probe-rs-tools --locked`. Depois confirme a instalação com `probe-rs --version` e a comunicação USB com `probe-rs list`. No Linux, instale também as regras udev necessárias.

### Qual é a diferença entre probe-rs, cargo-embed e cargo-flash?

probe-rs é a base de comunicação e debug. `cargo-embed` organiza flash, reset e RTT por meio de configuração versionada. `cargo-flash` é voltado principalmente à gravação. Para começar, a CLI `probe-rs` costuma ser suficiente.

### O probe-rs funciona com ST-Link, J-Link e Raspberry Pi Debug Probe?

Ele suporta várias versões de ST-Link, J-Link e CMSIS-DAP, categoria que inclui diversos probes acessíveis. Verifique o modelo local com `probe-rs list` e confirme também o suporte ao microcontrolador de destino.

### Como ver logs defmt com probe-rs?

Vincule `defmt`, `defmt-rtt` e um panic handler compatível, preserve símbolos no ELF e execute o firmware com `probe-rs run --chip ...`. A ferramenta lê o RTT e formata as mensagens no computador.
