STM32 Blue Pill na bancada: gcc-arm-none-eabi e stlink-tools

O repositório arm é o mais enxuto desta série — e isso já é informação de engenharia. O README cabe em poucas linhas: pasta /stm32_blue_pill, peça stm32f103c8t6, e o apt de Debian/Ubuntu stlink-tools + gcc-arm-none-eabi. Não há blink publicado, não há linker script no tree que o GitHub lista, não há CubeMX. Trato o repo como caderno de toolchain Cortex-M, não como firmware pronto.

Quem vem de PIC18 ou de AVR sente o salto: ARM Cortex-M3, barramento AHB/APB, SWD em vez de ICSP/ISP, 3,3 V em vez de 5 V “na raça”. Quem vem de CLP sente outra coisa: o STM32 é o tipo de MCU que mora dentro de I/O remoto, drive e IHM moderna. Entender a ferramenta de gravar e o compilador bare-metal é o mínimo para não tratar essa caixa preta como magia.

O que o repositório afirma — e só isso

Fatos do README e da árvore:

  • Alvo: placa Blue Pill com STM32F103C8T6.
  • Toolchain: gcc-arm-none-eabi (GCC cross para bare-metal, newlib, sem SO).
  • Gravador/debug: stlink-tools (pacote que traz st-flash, st-info, st-util para ST-LINK).
  • Há um arquivo-marcador stm32_blue_pill/stm32f103c8t6.

Não descrevo RTOS, HAL da ST, USB CDC, CAN ou DMA neste artigo porque não estão no repo. O estudo é: como se apoia uma bancada ARM de 32 bits com ferramentas GNU, no mesmo espírito do avr_mcu (apt + make + dongle) e no contraste com o pic_mcu (MPLAB X + XC8).

Por que a Blue Pill ainda merece tempo de bancada

A Blue Pill é uma placa chinesa clássica: LQFP48, cristal de 8 MHz na maioria dos lotes, LED em PC13, USB device no silício (FS), SWD nos pinos de cabeçalho. O F103C8 é Cortex-M3 @ 72 MHz no papel, com Flash nominal de 64 KB — e clones / “C8 com Flash de CBxx” são lenda de fórum. Eu não afirmo capacidade de Flash de um lote específico que não medi. Afirmo o princípio: leia o ID com st-info --probe antes de confiar no silkscreen.

Por que essa placa, e não um Nucleo oficial? Porque ela é o “Arduino Nano” do STM32: barata, abundante, suficiente para aprender SWD, tensão e reset. O Nucleo traz ST-LINK onboard e regulador decente. A Blue Pill cobra o preço da gambiarra — e a gambiarra ensina.

Nota de bancada, tensão. O F103 é 3,3 V. 5 V no pino de I/O é o jeito mais rápido de matar o chip. O pino 5V da placa alimenta o regulador (quando o lote traz um AMS1117 de verdade). USB e ST-LINK ao mesmo tempo pedem cuidado com referência de terra e com o jumper de 3V3. No painel industrial o análogo é óbvio: 24 V no bornes de 3,3 V de um CLP compacto também não perdoa.

Nota de bancada, clone. Muita Blue Pill viaja com ST-LINK clone de R$ 15 (STM32F103 “amarelinho”). O stlink-tools costuma falar com eles. Firmware do dongle desatualizado, cabo SWD invertido (SWDIO/SWCLK) e NRST flutuando são as falhas chatas. st-info --probe é o avrdude -vvv deste mundo.

gcc-arm-none-eabi: o que essa toolchain é

gcc-arm-none-eabi é GCC + binutils + newlib para alvo arm-none-eabi — “none” = sem sistema operacional, “eabi” = Embedded ABI. Você gera .elf e .hex/.bin como no AVR, só que o alvo é thumb Cortex-M, com startup em assembly, tabela de vetores em Flash e um linker script que diz onde param .text, .data e .bss.

O salto conceitual a partir do PIC/AVR:

  1. Memória mapeada em 32 bits. Periférico não é só um registrador de 8 bits em banco; é um bloco em 0x4000… com bus bridge. O datasheet vira RM0008 (reference manual) + DS (datasheet de pinos). Sem essa distinção, o iniciante se perde.
  2. Startup e reset. Antes do main existem: cópia de .data da Flash para RAM, zero em .bss, eventualmente FPU (não é o caso do M3) e SystemInit de clock. No PIC18 o XC8 esconde boa parte; no ARM bare-metal o script mente e o chip hardfault.
  3. HardFault. O LED não pisca e o debugger para num vetor. No AVR você “não roda”. No PIC você “não sai do reset”. No Cortex-M você tem um nome. Aprender a ler HFSR/CFSR no gdb/st-util é o equivalente ARM de olhar WDT e oscilador no PIC.

Nada disso está implementado neste repositório. Está implicado pela escolha da toolchain. Eu deixo a fronteira clara: o README instala o serrote; a tábua ainda não foi cortada no Git.

stlink-tools e o SWD

SWD (Serial Wire Debug) usa dois fios + GND (+ 3V3 de referência, + NRST se quiser reset controlado): SWDIO e SWCLK. É o parente ARM do ICSP. O ST-LINK v2 (ou clone) fala esse protocolo; o pacote stlink-tools é a ponta de usuário no Linux.

Fluxo mental de bancada, alinhado ao que o README instala:

  • st-info --probe — vê o chip?
  • st-flash write firmware.bin 0x08000000 — grava a Flash no endereço base do F103.
  • st-util — GDB stub na porta 4242, para arm-none-eabi-gdb.

Não publico aqui um hello.bin que o repo não tem. O hábito, porém, é o mesmo do make upload do AVR e do “Make and Program” do MPLAB: uma ferramenta de host, um dongle, um endereço de Flash.

Ponte industrial. IHM weintek, CLP compacto e inversor moderno escondem um Cortex-M atrás da etiqueta. Quando o técnico de painel encontra um conector SWD de 4 pinos numa placa de I/O, não é “coisa de maker”: é o mesmo pino de fábrica que o time de firmware usou para carregar o runtime. Saber que st-flash existe evita tratar o dongle como brinquedo e o conector como “não mexer”.

Blue Pill versus PIC18 e AVR — o mapa que eu uso

Tema PIC18F4550 (pic_mcu) ATmega328P (avr_mcu) STM32F103C8 (este repo)
Ferramenta no estudo MPLAB X + XC8 avr-gcc + avrdude gcc-arm-none-eabi + stlink-tools
Debug físico ICSP / PGD-PGC ISP (USBasp) SWD (ST-LINK)
Tensão típica de I/O 5 V 5 V 3,3 V
Palavra 8 bits (+ acesso 16) 8 bits 32 bits
Relógio no estudo PLL / EC 48 MHz (projetos irmãos) 16 MHz no blink 8 MHz cristal → PLL 72 MHz (típico; não medido neste repo)
Primeiro risco de bancada Config bit / MCLR Fusebit / assinatura 5 V no pino / HardFault

O F103 tem CAN, USB, timers avançados, ADC de 12 bits, mais de um USART. Isso é silício. Não é feature deste repositório. Eu já usei PIC18 com a intenção de CAN via MCP2515 marcada como “coming soon” no outro README: a lição se repete. Datasheet não é commit.

Armadilhas da toolchain GNU-ARM na bancada Linux

A instalação via apt parece trivial (gcc-arm-none-eabi, stlink-tools, às vezes gdb-multiarch). O diabo mora nos detalhes que o README de três linhas não cabe.

Versão do GCC no apt versus CMSIS/HAL. Pacotes Debian/Ubuntu envelhecem. Um tutorial de 2024 pode assumir -mcpu=cortex-m3 -mthumb com um startup gerado pelo CubeMX 6.x; o binário do apt pode ser mais antigo ou mais novo que o que o autor do tutorial usou. Sintoma clássico: linka, grava, HardFault no reset — e a causa é startup/linker desalinhado com o ABI, não “Blue Pill ruim”. Mitigação: pinar a versão do cross-compiler no README do estudo e guardar o arm-none-eabi-gcc -v no diário de bancada.

newlib, semihosting e printf. Quem vem do host cola printf e espera milagre. Em bare-metal, printf exige _write (ou semihosting via debugger). Semihosting sem st-util/OpenOCD conectado trava o MCU num breakpoint eterno — parece “placa morta”. Na indústria o análogo é o firmware de I/O que só “anda” com o cabo de debug plugado porque alguém deixou assert de semihosting no build de fábrica.

OpenOCD versus stlink-tools. Os dois falam ST-LINK. Misturar receitas sem saber qual daemon está na porta 4242/3333 gera “Connection refused” e culpa falsa no cabo. Escolha um caminho por sessão de estudo. Este repo aponta stlink-tools; eu não invento script OpenOCD que não existe no tree.

udev e permissão. Sem regra udev, st-flash pede sudo. Sudo em gravador vira hábito tóxico (e mascara problema de grupo plugdev). O mesmo vale para USBasp no AVR: permissão correta é parte da bancada, não “detalhe de Linux”.

Endianness e endereços. st-flash write quer .bin no endereço base 0x08000000. Gravar .elf com a ferramenta errada, ou .hex interpretado como binário cru, apaga a tabela de vetores. Sintoma: probe ok, LED morto, PC em lixo. Conferir o formato antes do segundo write é o equivalente ARM de não mandar o hex do XC8 pelo avrdude.

Clock e cristal errado no lote. Algumas Blue Pill trazem cristal de 8 MHz; receitas assumem 8 e configuram PLL para 72. Se o lote tiver outro cristal (raro, mas documentado em fóruns) e você não medir, UART fica “torto” e o iniciante culpa o USB-serial. Osciloscópio no OSC_IN/OUT ou leitura do RCC depois do SystemInit fecha a dúvida. Eu não afirmo a frequência do cristal da placa que está na minha gaveta sem medir — o princípio é medir.

Analogias industriais: onde o Cortex-M já mora no quadro

Não preciso inventar “case de fábrica” para o F103. O padrão se repete em produtos que o painelista já toca:

  • Módulo de I/O remoto. Muitos slices EtherNet/IP ou Modbus TCP carregam um MCU ARM que faz a ponte entre o ASIC de rede e os optoacopladores. O técnico troca o módulo; o firmware do módulo foi gravado por SWD na linha.
  • Driver de motor / inversor compacto. A malha rápida pode morar em DSP ou em Cortex-M4/M7; o M3 ainda aparece em supervisão, HMI local e protocolo. Entender mapa de memória e vetor de IRQ ajuda a ler um manual de “fault code” sem misturar causa de hardware com bug de ponteiro.
  • IHM embarcada. Painéis com Linux + Qt são óbvios; há também IHMs menores com MCU + framebuffer. O SWD atrás da tampa não é serviço de campo rotineiro — é canal de manufatura e de RMA. Saber que ele existe evita o mito de que “só a porta USB de usuário reprograma”.
  • Instrumentação de processo. Transmissor com display local muitas vezes é Cortex-M + ADC + stack HART/Modbus. A Blue Pill não é esse produto; a disciplina de gravar, ler ID e respeitar 3,3 V é a mesma família de hábito.

A ponte com CLP é pedagógica, não de substituição: ladder e ciclo de scan continuam no controlador certificado. O STM32 de estudo explica o silício atrás de muitos blocos QM do quadro. Função de segurança (STO, relé de segurança, CLP-S) permanece noutro dossiê.

Roteiro de estudo para popular o repo sem mentir no README

O estado atual (marcador + apt) é honesto. O caminho para deixar de ser só toolchain, em ondas que cabem em noites de bancada:

  1. Semana de probe. st-info --probe estável, foto do terminal no diário (sem IA), anotar ID do chip e se o clone ST-LINK respondeu. Se não responder: cabo, NRST, 3V3, udev — nessa ordem.
  2. Blink mínimo versionado. Startup + linker script + main que togglesh PC13. Sem HAL se a meta for entender registrador; com SPL/HAL se a meta for produtividade — mas declare a escolha no README. O commit precisa incluir o .ld e o startup, senão o clone do GitHub não builda.
  3. Make, não só IDE. Alvo all gera .elf/.bin; alvo flash chama st-flash. Espelho do avr_mcu. Quem só clica no STM32CubeIDE não treina o contrato que o CI e a fábrica usam.
  4. USART de log. 115200 8N1 num USB-TTL 3,3 V. Primeiro “printf” honesto (com _write ou lib leve). Sem isso, HardFault vira adivinhação.
  5. GDB via st-util. Break no reset, inspect de SCB->HFSR. Uma sessão em que você o fault vale mais que três tutoriais de CubeMX.
  6. Só então periférico de aplicação. Timer PWM, ADC pot, ou CAN transceiver em 3,3 V — um por vez. CAN sem terminador e sem common-mode é a próxima armadilha; não misture com o primeiro blink.

Critério de “repo não vazio”: README com versões (gcc -v, st-flash --version), um firmware que builda do zero, e uma seção Limites que diga o que não foi medido (Flash real do lote, EMI, temperatura).

O que isto ensina versus ASIL e chão de fábrica

A Blue Pill não é um MCU automotivo de item de segurança. Não tem a documentação, o processo de PPAP, o conjunto de diagnósticos e o suporte de longa duração que um SPC56, um TC3xx ou um STM32 da linha Safety carregam. O Cortex-M3 em si aparece em muitos produtos industriais QM. ASIL é processo + hardware com evidência, não “32 bits”.

O que a bancada GNU-ARM ensina de verdade:

  • cross-compiler e convenção none-eabi;
  • SWD como canal de fábrica;
  • respeito a 3,3 V e a terra comum com o notebook;
  • a ideia de mapa de memória e vetor de interrupção em Flash;
  • o hábito de probe antes de confiar no silkscreen;
  • a diferença entre “compila” e “sobrevive ao reset sem HardFault”.

O que ela não ensina:

  • ISO 26262 (HARA, FMEDA, decomposição ASIL, ferramentas classificadas);
  • ISO 13849 / IEC 62061 no quadro (isso continua no relé de segurança, no CLP-S e no STO do inversor);
  • HAL certificado, MPU configurada, dual-bank com bootloader assinado;
  • EMC de veículo, transceptor CAN com common-mode, load dump;
  • qualificação de compilador, cobertura MC/DC, traceabilidade de requisito até o objeto.

No quadro elétrico, um STM32 pode ser o cérebro de um I/O ou de um instrumento. A função de segurança, se existir, mora noutro bloco — ou neste bloco só depois de um dossiê que este repositório nem começa.

Limites honestos deste artigo e do repositório

  • Não há hex/binário publicado; qualquer “blink” descrito acima é plano, não artefato atual do Git.
  • Não medi consumo, temperatura de junção nem margem de Flash do chip que está na bancada.
  • Não comparo desempenho com Nucleo, Black Pill ou ESP32 — são famílias e objetivos diferentes.
  • Não endosso clone de ST-LINK para linha de produção; para estudo de hobby/lab ele costuma bastar, com as ressalvas de firmware do dongle.
  • CubeMX, Zephyr, FreeRTOS e TinyUSB ficam de fora até existir commit correspondente.
  • Nenhuma métrica de “tempo até first blink” ou “bug encontrado” foi inventada para embelezar o texto.

Fechamento

arm é um bilhete de ferramenta: Blue Pill, F103C8T6, gcc-arm-none-eabi, stlink-tools. Eu recuso transformar isso em tutorial de CubeMX ou em “ECU ARM”. O próximo commit honesto seria um blink com startup e linker script versionados — o equivalente ao src/blink do AVR. Até lá, o valor do repo é alinhar a bancada Linux ao mesmo hábito dos outros MCUs: compilador no PATH, dongle no USB, endereço de Flash na cabeça, e nenhuma promessa ASIL no silkscreen de uma placa de dez reais.