30 de julho de 2021

Do bit Ao Byte

Embarcados, Linux e programação

Primeiros passos com OpenOCD

primeiros passos com OpenOCD

Particularmente estou dando os primeiros passos com openOCD, do qual pretendo escrever alguns artigos. Ainda assim, é tanta coisa que não dará pra abordar tudo, mas vamos ver o suficiente para usá-lo satisfatoriamente.

O propósito é utilizá-lo como interface para o JLink e então usar o GDB para fazer debug. O GDB é o que já usamos para debug no Linux tradicionalmente, a diferença está no modo de utilizá-lo, mas nem é tanta diferença também.

O que é o OpenOCD?

Os detalhes que podem ser úteis para um trabalho universitário podem ser vistos no about. Basicamente, o OpenOCD (Open On-Chip Debugger) é uma ferramenta que faz interface de depuração, programação in-system e testes boundary-scan em dispositivos embarcados.

Vou enfatizar mais vezes: São os primeiros passos com OpenOCD porque são “meus” primeiros passos. Se você já conhece a ferramenta e quiser auxiliar com dicas, comente no artigo em nossa página lá no Facebook e em um novo artigo cito seu nome como autor da dica.

A escolha de um dispositivo de interface

O OpenOCD não faz tudo sozinho. Ele é uma interface intermediária a um dispositivo, e a escolha desse dispositivo deve levar em consideração alguns parâmetros.

Transporte

O foco do OpenOCD é JTAG. Se precisa interfacear com um dispositivo JTAG, está no caminho certo. Outros meios de transporte são o SPI e o SWD, por exemplo.

O Raspberry Pi Pico tem uma interface SWD, assim como a BluePill, que serão as MCUs mais utilizadas em artigos posteriores.

Tensão

O dispositivo pode ter diferentes tensões, sendo 1.8V, 2.8V, 3.3V ou 5V. O JTAG JLink é o que utilizaremos em nossos primeiros passos com OpenOCD nos artigos, sendo que ele suporta uma boa série da familia ARM, entre eles, o Cortex-M0 (RP Pico) e o Cortex-M3 (BluePill). Seu nível lógico é 3v3.

Pinout, conexão, RTCK

O JLink tem um conector de 20 pinos. Existem outros tipos de comunicação, mas confesso só ter visto ethernet e USB. No caso do JLink, a conexão é USB.

O JLink é um JTAG para a família ARM, por isso ele tem o chamado “clock adaptativo” – o RTCK.

USB FT2232

Diversos dongles USB são baseados no FTDI (“Future Technology Devices International”), conhecido como FT2232. Em meados de 2012, uma nova variante surgiu – o FT2232H. Os dispositivos JTAG que usam FT2232H ou FT232H podem suportar clock adaptativo.

O FT2232H possui dois canais de comunicação, e um deles pode ser usado como interface UART, ao mesmo tempo que a outra é usada para fazer depuração. Algumas placas de desenvolvimento integram o FT2232 como uma solução de depuração de baixo custo usando USB-Serial.

Jim-Tcl

O OpenOCD usa um interpretador Tcl conhecido como Jim-Tcl. Essa linguagem de programação oferece um interpretador de comandos simples e extensível.

Podemos usar Tcl como comandos simples sem precisar aprender muito sobre Tcl, ou então podemos escrever programas para automatizar as tarefas.

Se tem interesse em se aprofundar no assunto, o site do Jim-Tcl é a melhor opção para aprender Tcl. O site não tem SSL, mas também não há importância nisso.

As configurações do OpenOCD são scripts Jim-Tcl. O interpretador de comandos do OpenOCD é hoje uma mistura de Jim-Tcl e do interpretador de comandos original do projeto OpenOCD.

Podemos digitar diversos comandos por linha de comando através de telnet ou via monitor do GDB.

Execução do OpenOCD

Se não forem passados parâmetros através das flags -f (para indicar arquivos de configuração) ou -c (para indicar comando por linha), o OpenOCD tentará ler o arquivo openocd.cfg. Podemos passar mais de um arquivo de configuração, como veremos ao executar o OpenOCD com a RP Pico.

Mais uma vez: são os primeiros passos com OpenOCD, e posso cometer alguns erros (como penso que o fiz), mas coloquei a coisa pra funcionar e já me motivou um bocado.

Arquivo de configuração

Por padrão o arquivo é procurado no diretório corrente (se não indicado), então no diretório de scripts e o último lugar importante, no home do usuário, no diretório oculto do programa (~/.openocd).

Execução simples

No melhor dos casos, teremos dois scripts para fazer a interação com um dispositivo através de um JTAG. A linha de comando para iniciar o OpenOCD para depurar uma Raspberry Pi Pico deve ser algo como:

openocd -f interface/blackmagic.cfg -f target/rp2040.cfg

No caso, passamos os dois arquivos de configuração necessários: o primeiro é o adaptador e o segundo é a placa alvo. Repare que a diferença está não apenas no nome do arquivo, mas também no diretório base. Se compilou o OpenOCD conforme o artigo “Como programar a Raspberry Pi Pico no Linux“, deverá existir em seu home o diretório pico/openocd. Dentro dele temos o diretório tcl e dentro deste último diretório, temos os diretórios interface e board.

openOCD - interface e target

Se quiser saber quais são os JTAGs suportados, basta listar o diretório interface e para as placas, liste o diretório boards.

Para fazer o primeiro teste, optei por algo mais simples ainda, que foi utilizar o JLink no STM32F103, como feito com o firmware Black Magic Probe em um BluePill. A linha de comando é parecida, mas tive que fazer algumas modificações em ambos os arquivos. O processo está descrito mais adiante.

O que acontece ao executar o OpenOCD

Já vimos que podemos executá-lo com linha de comando ou passando arquivos de configuração. Quando iniciado, ele inicia como um servidor, mas ele pode executar algumas ações sem iniciar como um servidor também.

A conexão ao OpenOCD quando está sendo executado como um servidor pode se ser feita através de Telnet, GDB ou RPC. Podemos criar programas que façam interface com esses canais, mas vamos focar primeiramente no padrão, para que saibamos como agir em caso de alguma anomalia.

primeiros passos com OpenOCD - conexão funcional

Debug do debugger

Se a configuração padrão não for suficiente, se algo der errado, como detectar um problema? Bem, ao tentar interfacear com um dispositivo, sendo uma anomalia simples (por exemplo, ausência de comandos no arquivo de configuração ou typo), podemos utilizar a flag -d para ter uma saída detalhada da execução do comando e assim facilitar a identificação de um problema na tentativa de conexão.

Se o dispositivo alvo não estiver configurado corretamente, o JTAG poderá ficar irresponsivo até que o alvo esteja devidamente configurado, por exemplo, através dos comandos do monitor, no GDB, em um arquivo ~/.gdbinit.

Arquivo de configuração do OpenOCD

Não é exatamente “do” OpenOCD, mas “para” o OpenOCD. O arquivo de configurações do usuário engloba todas as partes do projeto em um só lugar. Idealmente, o arquivo de configuração já deve vir pronto, como por exemplo, os do próprio OpenOCD, ou de algum vendedor de placas ou JTAGs.

Existem 3 outros tipos de configuração que não são parte do usuário:

  • Interface – usado para especificar o adaptador.
  • board – um para cada placa.
  • target – os chips que integram as CPUs e outros JTAG TAPs.

O melhor caso é quando incluímos apenas 2 arquivos: interface e board. Nesse caso, eles manipulam todas as coisas necessárias.

No arquivo de interface temos a indicação do adaptador JTAG que, no meu caso, será o JLINK. O segundo arquivo será a especificação da placa, que se encarregará de ajustar o TAP e alvos GDB. Se fôssemos incluí-los em um script, usaríamos a palavra reservada source dessa maneira:

source [find interface/olimex-jtag-tiny.cfg]
source [find board/csb337.cfg]

Modificando um arquivo existente

Vou exemplificar a configuração que fiz no arquivo interface/jlink.cfg nesses primeiros passos com OpenOCD, e continuar com informações técnicas que considero importantes em outro artigo.

Ao conectar o JTAG no computador, consultei os eventos do sistema com o comando dmesg. A partir dele vi que o JLink havia sido reconhecido adequadamente:

dmesg jtag jlink

Então comecei a testar a inicialização do dispositivo. Primeiramente, com o comando openocd -f interface/jlink.cfg:

jtag

Repare que houve “1” erro, apesar de 3 linhas informando. A mensagem claramente mostra o parâmetro que deve ser adicionado ao arquivo jlink.cfg para resolver o problema. Adicionei então o valor adapter speed 4000 ao arquivo e executei novamente o mesmo comando:

swd

Agora faltou o quê? Repare na mensagem: passamos por vários pontos e o erro informa que faltou indicar o transport. Ainda deu as opções possíveis. Como poderia ser mais fácil?

Adicionei então o parâmetro tranport select swd, já que SWD é o que utilizaremos tanto no Raspberry Pi Pico como no BluePill (STM32F103).

O arquivo ficou assim:

adapter driver jlink 
adapter speed 4000 
transport select swd

E a execução sucedeu sem problemas. Mas ainda faltam algumas coisinhas.

primeiros passos com OpenOCD - inicio

Antes de seguir, fiz um teste de conexão com telnet:

primeiros passos com OpenOCD - telnet

Ok, conectou sem problemas!

Agora quero me conectar ao BluePill, como fizemos no artigo de “Comandos GDB para usar com BluePill“. Dentro de boards temos a stm32f1x.cfg para esse propósito, mas também precisará de uma pequena modificação. O comando ficou assim:

sudo openocd -f interface/jlink.cfg -f target/stm32f1x.cfg \ -c "telnet_port 4444"

Haverá um erro relacionado aos argumentos. O que fiz para esse debug foi usar -disable no lugar dos argumentos, mas não é a melhor opção. O ideal é executar o debug no OpenOCD (com a flag -d) e verificar onde exatamente está o erro. Mas o que queria era comprovar que o JLink funcionaria.

Faltou alguma coisa no parâmetro porque o comportamento ficou “esquisito”. Não consegui carregar os símbolos, mas consegui executar com breaks. Para usar watch, precisei fazer um cast no tipo:

primeiros passos com OpenOCD - GDB

Isso já é o suficiente para os primeiros passos com OpenOCD, mas há muito pela frente.

Na documentação oficial do OpenOCD você encontrará mais de 170 páginas de configurações e instruções. É realmente esclarecedor, recomendo a leitura (em inglês). Como fico ansioso com coisas divertidas como essa, até o momento li só 30 páginas. Tem muita coisa ainda e talvez ainda aborde de outra maneira o OpenOCD!

Qual JTAG usar?

Estou aprendendo sobre JTAG agora, gatinhando ainda. Foi bastante fácil utilizar o firmware do Black Magic Probe no BluePill para programar outro STM32F103. Já para fazer o debug com o JLink é um pouco mais difícil, tem coisas que ainda não tenho o conceito, mas devagar chegamos lá. Esse JTAG Jlink você encontra na Shopee.

Revisão: Ricardo Amaral de Andrade