17 de maio de 2021

Do bit Ao Byte

Embarcados, Linux e programação

Como transformar um BluePill em debugger

comandos GDB | transformar um BluePill em debugger

Quer saber como transformar um BluePill em debugger? O STM32F103 é uma placa com processador ARM Cortex-M3, com baixíssimo custo e cheia de recursos. Já escrevi uma série de artigos com ela:

RTOS – Nuttx no BluePill

Nuttx – Configurar porta USB

STM32 BluePill

Como habilitar GPIO no Nuttx

Deve ter mais um ou dois, mas não procurei muito. Enfim, essa placa é multipropósito, e nesse artigo vamos ver como transformá-la em uma ferramenta de baixo custo, com alguns recursos diferenciados.

O tema é man-ja-do. A Internet está repleta de artigos sobre o tema, principalmente em inglês, mas não poderia deixar de escrever porque é complementar a outros temas recém abordados.

STM32F103 para Black Magic Probe (BMP)

Já falei do baixo custo, mas não citei onde adquiri-la. A CurtoCircuito é a principal referência, não apenas por vendê-la por um preço justo, mas também pela qualidade do atendimento pré e pós-venda. Além disso, a CurtoCircuito é uma das poucas lojas que têm coragem de inovar, trazendo novidades sempre, indo além do padrão que a maioria mantém.

O modelo exato que usei para esse artigo é essa placa.

Entendendo o processo

Essa placa tem apenas o bootloader USART por padrão. A porta USB não serve para programá-la por não ter um bootloader relevante.

O processo adotado aqui para essa lagarta virar borboleta utiliza um FTDI padrão, não precisa ser o gravador ST-LINK V2 ou outro. No primeiro passo vamos gravar um bootloader que use a USB, então programá-la diretamente pela USB.

Primeiro, conecte o FTDI desse modo:

Wiring 1 – para programação

BluePill - transformar um BluePill em debugger

Quando usando seu próprio bootloader, os jumpers da STM32 ficam em 0 para boot0 e boot1. O que precisamos fazer agora é colocar o boot0 em 1.

STM32Loader

Precisamos também de um carregador para a placa, que é escrito em Python. Atualmente o Python2 já não é mais mantido e quase nada mais funciona ou está disponível. Baixe o STM32Loader desse link. Para instalá-lo (após baixá-lo), use o comando:

pip install stm32loader-0.5.1-py2.py3-none-any.whl 

Instale também o python3-serial, seja pelo pip ou pelo apt.

Tendo o carregador instalado, precisamos de algo para ele carregar para a placa, certo?

Compilar para ARM

No caso, o compilador que precisaremos utilizar é o arm-none-eabi. Instale os seguintes pacotes:

sudo apt-get install binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi

Repositório BlackMagic

Clone o repositório BlackMagic deste link. Se não tiver o programa git instalado em seu Linux, use sudo apt-get install git. Depois, clone o repositório:

git clone https://github.com/blacksphere/blackmagic.git

Entre no diretório criado pela clonagem e execute o comando make:

cd blackmagic
make

Ao término, entre no diretório src e execute essa série de comandos (aqui incluo a entrada no diretório src):

cd src
make clean
make PROBE_HOST=stlink

A compilação deve resultar em dois arquivos principais dentro do diretório src, sendo o blackmagic_dfu.bin e blackmagic.bin.

Supondo que esteja no mesmo nível de diretório do binário resultante da compilação, agora execute o seguinte comando para gravar o bootloader:

stm32loader -p /dev/ttyUSB0 -e -w -v blackmagic_dfu.bin

Pode ser necessário apertar o botão de reset da placa antes executar o comando acima. No meu caso, sim, foi necessário.

No final do processo será retornado um “ok” para a comparação do binário gravado, garantido que tudo ocorreu bem. Fique de olho nisso.

Volte o jumper do boot0 para a posição 0.

Black Magic Probe firmware

Hora da finalização. Desconecte todas as coisas e agora conecte a BluePill ao computador usando a porta USB. Usando o comando sudo dmesg, deverá ser possível o novo dispositivo USB conectado.

Instale o programa dfu-util:

sudo apt-get install dfu-util

Então execute o seguinte comando:

sudo dfu-util -d 1d50:6018,:6017 -s 0x08002000:leave -D blackmagic/src/blackmagic.bin

Esse será o padrão, mas para saber de que se trata, em dmesg encontramos a informação de idVendor e idProduct. Da mesma forma, com dfu-util -l vemos essas informações. Uma referência do comando pode ser vista aqui.

Após, desconecte e reconecte seu novo Black Magic Probe. Deverão aparecer duas portas no sistema. A ttyACM0, que é o servidor GDB, e a segunda porta, que é a UART serial, para debug serial. Já fizemos o necessário para transformar um BluePill em debugger!

transformar um BluePill em debugger

Wiring do Black Magic Probe

Esse wiring é definitivo para o dispositivo que agora é uma ferramenta.

ALVODEBUGGER
GNDGND
SWDIOPB14
SWCLKPA5
VCC3V3

O dispositivo agora suporta JTAG/SWD e Serial UART simultaneamente! Os pinos para conexão serial são:

ALVODEBUGGER
RXPA3
TXPA2

Não se esqueça que TX vai ao RX e RX ao TX. Se ligar TX com TX e RX com RX, não haverá dados no barramento.

Instale o pacote de depuração GDB:

sudo apt-get install gdb-multiarch

Agora é só usar! Experimentei em outro STM32F103C8, conectando o BMP aos pinos frontais da placa, como descrito na tabela mais acima.

No Laboratório Maker 08 vimos como adicionar suporte ao STM32 na IDE do Arduino. Siga o procedimento, então compile esse código de exemplo:

uint16_t i = 0;
 void setup() {
   // initialize digital pin PC13 as an output.
   pinMode(PB12, OUTPUT);
   pinMode(PC13, OUTPUT);
 }
 // the loop function runs over and over again forever
 void loop() {
   digitalWrite(PB12, HIGH);   // turn the LED on (HIGH is the voltage level)
   digitalWrite(PC13, HIGH);
   delay(500);              // wait for a second
   digitalWrite(PB12, LOW);    // turn the LED off by making the voltage LOW
   digitalWrite(PC13, LOW);
   delay(500);              // wait for a second
   teste();
 }
 void teste(){
   for (uint8_t j=0; j<20;j++){
      digitalWrite(PB12, HIGH);   // turn the LED on (HIGH is the voltage level)
      digitalWrite(PC13, HIGH);
      delay(300);              // wait for a second
      digitalWrite(PB12, LOW); 
      digitalWrite(PC13, LOW);
      // turn the LED off by making the voltage LOW
      delay(100); 
      i++;
   }
 }

Apesar de parecer meio sem nexo, o propósito é justamente enxergar a depuração por linha de comando. Claro que podemos utilizar uma IDE como o VSCode para depurar código, mas é perfeitamente possível fazê-lo por linha de comando, apesar de não ser tão confortável. Mas é divertido, veja o procedimento:

Compile o código acima. O diretório de compilação no Linux será algo como /tmp/arduino_build_xxxxxx, onde x é uma sequência de números a verificar após a compilação. Não feche a IDE do Arduino, senão a compilação será apagada. Agora deixe a IDE de lado e abra um terminal.

Uma sequência simples para assistirmos o LED onboard piscar e ler o valor de mudança da variável i:

gdb-multiarch -tui
target extended-remote /dev/ttyACM0
monitor swdp_scan
attach N (N é o número do dispositivo)
set mem inaccessible-by-default off
load /tmp/arduino_build_637618/led.ino.elf
file /tmp/arduino_build_637618/led.ino.elf
(confirme com y)
watch i
list loop
break loop
break teste
print j
n

Depois de n pode ir apertando só enter para entrar na próxima interação. Fica mais ou menos assim:

transformar um BluePill em debugger

Onde comprar JTAG JLink para RP Pico?

Se não quer ter trabalho, o  J-Link que estou usando é da Werneck Eletronics, que você pode adquirir por um excelente preço na Shopee. Se não conhece a Shopee, vale a pena. Como não tem o achaque do MercadoLivre, os preços são melhores. A MASUGUX também adotou e acredito que seja uma tendência.

Eles têm também um outro modelo que presumo ser a mesma coisa, mas não posso confirmar. Confira nesse link.

Vídeo

No Vídeo “Debug com SWD” faço essa demonstração do uso, após transformar um BluePill em debugger. Posteriormente veremos como utilizar o debugger em outras condições, mas por enquanto é isso. Tem outras operações importantes para fazer, mas fica para outro artigo.

Até a próxima!

Revisão: Ricardo Amaral de Andrade