ÍNDICE DE CONTEÚDO
Saudações! Se você está aqui, é provável que já tenha se familiarizado com o universo dos microcontroladores da STMicroelectronics, especialmente com a renomada série STM32. Então pegue o seu café e se conforte na cadeira que hoje vou te apresentar uma poderosa ferramenta de programação de microcontroladores desenvolvida pela ST, o STM32CubeProgrammer.
Neste artigo, cobrirei o essencial para que você possa utilizar a CLI (Interface de Linha de Comando, do inglês, Command Line Interface) da ferramenta. Essa interface expande as possibilidades para a programação dos microcontroladores, abrindo espaço para a criatividade e automação dos processos de gravação dos dispositivos. Além disso, mostrarei como desenvolver scripts de gravação, uma integração com a linguagem Python e com o renomado Visual Studio Code.
Todo o conteúdo apresentado neste artigo foi elaborado com base na documentação da ferramenta, disponibilizada pela empresa desenvolvedora. Sendo assim, para informações ou detalhes adicionais, confira o seguinte manual do usuário: STM32CubeProgrammer software description – User manual
Esta é uma ferramenta gratuita que pode ser baixada diretamente do site do fabricante-desenvolvedor, por meio do seguinte link: STM32CubeProg – STM32CubeProgrammer software for all STM32 – STMicroelectronics
NOTA: Para utilizar a interface de linha de comando da ferramenta, é necessário ter instalado no seu computador o STM32CubeProgrammer ou o STM32CubeIDE (que inclui uma instância do STM32CubeProgrammer que pode ser utilizada).
O que é o ST32CubeProgrammer
Conforme mencionado anteriormente, o STM32CubeProgrammer é um conjunto de ferramentas desenvolvidas especificamente para a programação dos Microcontroladores da linha de 32 bits da ST, o STM32. Este software oferece um método simples e intuitivo para realizar a programação das memórias internas ao microcontrolador, tais como Flash, RAM e OTP, bem como das memórias externas, como EEPROM, Flash e RAM externas.
O acesso das memórias externas é efetuado por meio do uso dos external loaders, que são ferramentas poderosas que podem ser desenvolvidas para otimizar o processo de gravação. Sendo muito úteis nas etapas de programação e montage.
Para viabilizar todas essas funcionalidades, o microcontrolador pode ser acessado tanto pelas interfaces de depuração JTAG e SWD quanto pelas interfaces disponíveis no bootloader¹ (como UART, USB DFU, I²C, SPI e CAN).
As ferramentas são disponibilizadas em dois formatos: GUI, uma interface de usuário gráfica e intuitiva; e CLI, uma interface de linha de comandos que oferece ao usuário maior flexibilidade durante a utilização da ferramenta.
Fonte: Capturas de tela realizadas pelo autor.
¹ A programação e leitura de memórias externas estão restritas às interfaces de debug e bootloaders customizados ou proprietários. Portanto, não é viável acessá-las pelo bootloader interno de fábrica presente na memória do microcontrolador.
Primeiros passos com o CLI
Antes de darmos início a utilização da ferramenta, é importante mencionar que todos os comandos estão listados no manual de usuário (apresentado no início do artigo) e também podem ser acessados ao iniciar a ferramenta sem nenhum parâmetro, como demonstrado a seguir.
Para iniciar a utilização da interface de linha de comando (CLI) do STM32CubeProgrammer, comece abrindo o seu terminal preferido e navegue até a pasta “bin” no diretório onde o software foi instalado. No caso do Windows, o software é geralmente instalado na seguinte pasta por padrão:
1 |
“C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin” |
Se você possui apenas o STM32CubeIDE instalado em seu computador, é possível utilizar o STM32CubeProgrammer através do seguinte caminho:
1 |
“C:\ST\STM32CubeIDE_<em>\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win</em>\tools\bin” |
Tomando como base o terminal de comandos do Windows, para navegar até a pasta bin, é necessário aplicar o seguinte comando:
1 |
cd “C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin” |
Fonte: Captura de tela realizada pelo autor.
Ao entrar na pasta do programador, insira o comando STM32_Programmer_CLI para invocar a ferramenta. Isso permitirá que você verifique se está na pasta correta, bem como a versão do STM32CubeProgrammer, juntamente com os comandos disponíveis para uso com a ferramenta.
Fonte: Captura de tela realizada pelo autor.
O STM32_Programmer_CLI serve como a base para as chamadas do CLI. Acompanhando esse comando, você deve fornecer as instruções e parâmetros necessários, de acordo com o processo que deseja executar. Continue lendo este artigo, pois apresentaremos a seguir os comandos mais comuns, suas sintaxes e exemplos de aplicação.
Conexão com o Microcontrolador:
Para estabelecer a conexão com o microcontrolador, você utilizará o comando connect. Esse comando inclui vários parâmetros que variam conforme o tipo de conexão desejada (SWD, UART, SPI, etc.). Portanto, é importante consultar o manual do STM32CubeProgrammer para obter mais detalhes sobre esses parâmetros.
A sintaxe base deste comando é apresentada a seguir:
1 |
-c port= [options]--connect port= [options] |
O atributo do parâmetro port é selecionado de acordo com o tipo de comunicação, por exemplo, COMx (para VCOM no Windows), /dev/ttySx (para VCOM no Linux), USBx (interface usb), SWD, SPI, I2C e CAN. Veja o exemplo a seguir para abertura de uma comunicação via SWD:
1 |
STM32_Programmer_CLI -c port=swd mode=Normal reset=HWrst |
Fonte: Captura de tela realizada pelo autor.
Leitura de dados
A fim de ler os valores de endereços específicos de alguma memória do microcontrolador, utiliza-se o comando read. A sintaxe deste comando é apresentada a seguir:
1 |
-r32 <start_address> <size> |
O comando realizará a leitura em blocos de 32 bits, começando a partir de um endereço inicial (start_address) pelo tamanho especificado (size).
Aqui está um exemplo de como utilizar este comando. Lembre-se de que, antes de executar o comando de leitura, é necessário estabelecer a conexão com o microcontrolador usando o comando de conexão.
1 |
STM32_Programmer_CLI -c port=swd -r32 0x08001000 0x400 |
Fonte: Captura de tela realizada pelo autor.
Extração da memória para um arquivo
Utilizando o CLI, é possível extrair o conteúdo da memória do microcontrolador e exportar para um arquivo .bin. Para realizar este processo, o comando upload é utilizado. A sua sintaxe é dada da seguinte forma:
1 |
-u <start_address> <size> <file_path>--upload <start_address> <size> <file_path> |
Aqui está um exemplo de como usar este comando, juntamente com o resultado correspondente. Todos os exemplos apresentados a partir deste ponto serão executados na Placa Franzininho C0, utilizando conexões através da Virtual COM:
1 |
STM32_Programmer_CLI -c port=COM4 br=115200 -u 0x08001000 0x400 "C:\Users\botel\OneDrive\Área de Trabalho\myCode.bin" |
Fonte: Captura de tela realizada pelo autor.
Escrita na memória
Neste tópico é apresentado o comando write, ele pode ser utilizado para gravar dados no formato 32 ou 64 bits, conforme a sintaxe abaixo:
1 |
-w32 <start_address> <32_data_bits> <32_data_bits> …-w64 <start_address> <64_data_bits> … |
É fundamental lembrar que, antes de escrever na memória flash, o setor/página que você pretende escrever deve ser previamente apagado. Caso contrário, ao tentar executar o comando de escrita, ocorrerá um erro.
Quando você precisa gravar vários pacotes de dados sequenciais, basta inseri-los no comando, conforme o exemplo a seguir:
1 |
-w32 0x08000000 0x12345678 0xAABBCCFF 0x12AB34CD |
Executando o comando acima, serão escritos os valores 0x12345678 0xAABBCCFF 0x12AB34CD na memória FLASH a partir do endereço 0x08000000.
A seguir é apresentado um exemplo de utilização deste comando para a gravação de um pacote de 32 bits no endereço inicial da memória FLASH (0x08000000) do microcontrolador.
1 |
STM32_Programmer_CLI -c port=COM4 -w32 0x08000000 0x12345678 |
Fonte: Captura de tela realizada pelo autor.
Apagamento de setores da memória:
Para apagar setores da memória, o comando erase é utilizado. Sua sintaxe é apresentada a seguir:
1 |
-e [<sectorsCodes>]-e [<[start end]>]--erase [<sectorsCodes>]--erase [<[start end]>] |
Como mencionado anteriormente, este comando pode ser utilizado de duas maneiras. Na primeira, você especifica os setores de memória que deseja apagar. Veja o exemplo a seguir, que demonstra o apagamento dos setores 0, 2 e 7 da memória.
1 |
STM32_Programmer_CLI -c port=COM4 -e 0 2 7 |
A segunda forma de utilizar o comando, é especificando um intervalo de setores a serem apagados. No exemplo a seguir, os setores 0º ao 3º setor (setores 0, 1, 2 e 3) serão apagados.
1 |
STM32_Programmer_CLI -c port=COM4 -e [0 3] |
Fonte: Captura de tela realizada pelo autor.
Apagamento total da memória:
Para executar um apagamento completo da memória (mass erase), também é necessário usar o comando erase. No entanto, nesse caso, é feita uma alteração no parâmetro dos setores que serão apagados:
1 |
-e all |
Veja um exemplo a seguir da utilização deste comando:
1 |
STM32_Programmer_CLI -c port=COM4 -e all |
Fonte: Captura de tela realizada pelo autor.
Gravação um firmware na memória
Para gravar uma imagem (arquivo binário) na memória, utilize o comando download. Sua sintaxe é a seguinte:
1 |
-d <file_path> [start_address]--download <file_path> [start_address] |
O primeiro parâmetro deste comando deve indicar o diretório no qual o arquivo binário está armazenado em seu computador. O segundo parâmetro, por sua vez, deve fazer referência ao endereço inicial para a gravação da imagem, uma vez que os arquivos binários não contêm informações de endereço de gravação. Confira o exemplo a seguir:
1 |
STM32_Programmer_CLI -c port=COM4 -d C:\Users\botel\STM32CubeIDE\workspace_1.12.1\HelloWorld_FranzininhoC0\Debug\HelloWorld_FranzininhoC0.bin 0x08000000 |
Fonte: Captura de tela realizada pelo autor.
Leitura dos Option Bytes
Para realizar a leitura dos Option Bytes do microcontrolador o seguinte comando pode ser utilizado:
1 |
-ob displ |
Este comando efetua a leitura dos valores de todos os Option Bytes disponíveis no microcontrolador e os apresenta em forma de lista. Veja o exemplo a seguir para ver a execução deste comando:
1 |
STM32_Programmer_CLI -c port=COM4 -ob displ |
Fonte: Captura de tela realizada pelo autor.
Escrita dos Option Bytes
Além da leitura dos valores dos Option Bytes, também é possível alterá-los. Para isso o seguinte comando é utilizado:
1 |
-ob [OptByte=<value>] |
Veja a seguir um exemplo de utilização deste comando para a alteração do valor de RDP para 0x11:
1 |
STM32_Programmer_CLI -c port=COM4 -ob rdp=0x11 |
Fonte: Captura de tela realizada pelo autor.
Adicionando a CLI às variáveis de ambiente do windows
Conforme apresentado no tópico anterior, é necessário navegar até a pasta de instalação da ferramenta para utilizá-la. No entanto, podemos otimizar esse procedimento ao eliminando este passo do processo.
Uma abordagem para isso envolve adicionar o caminho do diretório onde o STM32_Programmer_CLI está localizado às variáveis de ambiente do Windows. Dessa maneira, a ferramenta pode ser chamada de qualquer local, pois o sistema operacional será capaz de localizá-la automaticamente
Para adicionar o caminho nas variáveis de ambiente, abra o menu iniciar e pesquise por “environment variables” (ou variáveis de ambiente, caso o seu sistema operacional esteja em português).
Na janela aberta, abra o menu “Environment Variables…”.
Fonte: Captura de tela realizada pelo autor.
No menu aberto, adicione o caminho da pasta “bin” no conjunto de variáveis “Path”:
Fonte: Captura de tela realizada pelo autor.
Após concluir esses passos, você poderá usar a CLI sem a necessidade de navegar até a pasta de instalação da ferramenta, conforme apresentado na Figura 15.
Fonte: Captura de tela realizada pelo autor.
Criação de scripts de gravação
Em muitos processos de gravação, frequentemente é necessário executar uma série de comandos de maneira repetitiva. Nessas situações, é possível construir um script contendo todas as instruções e comandos essenciais para o processo de gravação.
A grande vantagem de usar o script está na capacidade de empregar operações matemáticas (soma, subtração, e etc.), operações lógicas (lógica AND, lógica XOR, bitwise OR, e etc.), macros (Write(…), Read(…), Display(…) e Delay(…)), variáveis, estruturas de decisão e loops.
Nos tópicos a seguir, exploraremos esses recursos, juntamente com a sua sintaxe,e também fornecerei alguns exemplos de aplicação. Isso demonstrará como construir um arquivo com as instruções necessárias para implementar um processo de gravação mais complexo.
Macros
O STM32CubeProgrammer CLI inclui um conjunto de cinco grupos de macros que podem ser empregadas para a construção dos scripts. Cada macro deve ser precedida pelo símbolo ‘ # ’ seguido pelo nome da macro.
O primeiro grupo abrange as macros de escrita, as quais permitem gravar um valor específico de 8/16/32 bits em uma memória do dispositivo conectado. A sintaxe para utilização é a seguinte:
1 2 3 |
#Write32(Address, data) #Write16(Address, data) #Write8(Address, data) |
A segunda macro efetua a leitura das memórias do microcontrolador. Essa macro é restrita a ler um conteúdo de 32 bits e possui a seguinte sintaxe:
1 |
#Read(Address) |
A terceira macro é empregada para escrever mensagens, dados, mensagens de erro e o conteúdo de variáveis presentes no script. A sintaxe dessa macro é a seguinte:
1 |
#Display(“Hello World”) |
A quarta macro permite que o usuário coloque o sistema em standby por um período definido em milissegundos, com a seguinte sintaxe:
1 |
#Delay(Time) |
E finalmente, a quinta macro possibilita ao usuário desconectar da placa, permitindo posterior reconexão na mesma placa ou em outra, tudo dentro do mesmo script. A sintaxe para essa macro é a seguinte:
1 |
--scriptdisconnect |
É válido ressaltar que também é possível incluir comentários no script, utilizando a seguinte sintaxe:
1 |
//Meu Comentário |
Variáveis
A ferramenta permite a criação de variáveis para o armazenamento de dados durante a execução do script. Essas variáveis podem ser utilizadas em conjunto com as macros, em operações lógicas e matemáticas, em estruturas de decisão e em laços de repetição. A sintaxe para utilizar esse recurso é apresentada a seguir:
1 2 |
#variable=<value> #<macro>(#variable) |
Aqui vão alguns exemplos de utilização de variável com as macros:
1 2 3 4 5 6 7 |
#var0=0x20 #Delay(#var0) #var1=#Read(0x08000000) #var2=0x1234 #Display(#var2) |
Mais exemplos envolvendo variáveis serão fornecidos mais adiante, juntamente com a exploração dos demais recursos disponíveis.
Operações matemáticas
Como já apresentado anteriormente, é possível realizar algumas operações matemáticas nos scripts. As operações permitidas incluem adição (+), subtração (-), multiplicação (*) e divisão (/). E seguem a sintaxe abaixo:
1 |
#variable=[var1] op [var2] |
Um exemplo de operação matemática é apresentado a seguir:
1 2 3 4 5 6 |
#var1=0x0020000 #var2=#Read(0x08000010) #var3=([#var1] + [#var2]) #Display(#var1) #Display(#var2) #Display(#var3) |
Operações lógicas
Além das operações matemáticas, é possível efetuar operações lógicas. As operações aceitas incluem “e” lógico (AND), “ou” lógico (OR), bitwise “e” (&), bitwise “ou” (|) “ou exclusivo” (XOR) e deslocamento à direita e à esquerda (shift left e shift right, << >>). A sintaxe dessas operações é semelhante à das operações matemáticas:
1 |
#variable=[var1] op [var2] |
E seguem alguns exemplos:
1 2 3 4 5 6 7 8 |
-c port=COM4 #ADD = 0x08000000 #var0 = #Read(#ADD) #var1 = 0xFF00 #Display(#var0) #var2 = ([#var0] & [#var1]) #var2 = ([#var2] >> 8) #Display(#var2) |
Estruturas de decisão
Para complementar, é possível utilizar a estrutura if-else para a tomada de decisões dentro do script. A sintaxe dessa estrutura é exibida a seguir:
1 2 3 4 5 6 7 8 9 10 |
#Start if(condition) { } else { } #End |
Um exemplo de aplicação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
-c port=COM4 #ADD = 0x08000000 #var0 = #Read(#ADD) #Start if(#var0 < 0xFFFFFFFF) { #Display("Device already programmed") } else { #Display("Device not programmed") } #End |
Laços de repetição
Por fim, as últimas estruturas aceitas pelo script são os laços de repetição. Entre os laços disponíveis, você pode utilizar o while e o for, da seguinte maneira:
While:
1 2 3 4 5 6 7 |
#Start while(Condition) { Commands } #End |
For:
1 2 3 4 5 6 |
#Start for(Condition) { Commands } #End |
Exemplo de utilização do laço While:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
-c port=COM4 #ADD=0x08000000 #var0 = #Read(#ADD) #Start while(#var0 != 0xFFFFFFFF) { #Display(#var0) #ADD=([#ADD]+(4)) #var0=#Read(#ADD) } #End #Display(#ADD) |
Exemplo de utilização do laço for:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
-c port=COM4 -e all -r32 0x08000000 0x40 #ADD=0x08000000 #var0=0x000000 #Start #Display(#var0) for(#ADD=0x08000000;#ADD<0x08000078;#ADD=#ADD+8) { #Display(#ADD) #Write32(#ADD, #var0) #var0 = ([#var0] + 0x11111111) #Display(#var0) } #End -r32 0x08000000 0x80 |
Criação do arquivo e chamada no CLI
Agora que você está familiarizado com os principais comandos do CLI (conforme apresentado no tópico 3) e os recursos disponíveis para a criação de um script (conforme apresentado no tópico 4), já é possível criar o arquivo de script a ser executado pelo STM32CubeProgrammer.
Para isso, abra o seu editor de texto preferido, construa o script desejado e salve o arquivo com a extensão .PRG. Depois disso, você pode executá-lo a partir de um terminal com o seguinte comando:
1 |
STM32_Programmer_CLI -script myScript.prg |
Lembre-se de modificar o parâmetro “myScript.prg” para o caminho onde você salvou o seu script.
Para uma execução mais ágil, você pode criar um arquivo .bat, contendo o seguinte código:
1 2 |
STM32_Programmer_CLI -script myScript.prg pause |
Dessa forma, você estará criando um arquivo executável que permitirá a chamada do seu script, eliminando a necessidade de usar o terminal para sua execução. Essa abordagem possibilitará a execução de várias linhas de comando com apenas dois cliques no arquivo executável!
Fonte: Captura de tela realizada pelo autor.
Integração com VScode
Há várias maneiras de integrar o STM32CubeProgrammer CLI com o VSCode. Você pode usar os recursos apresentados até o momento de várias maneiras para executar uma rotina de programação diretamente do VSCode. No entanto, neste tópico, vamos focar em demonstrar como invocar os comandos por meio do Python no VSCode.
A partir deste ponto, pressupõe-se que você já esteja familiarizado com a importação de um projeto STM32 no VSCode, utilizando a extensão desenvolvida pela STMicroelectronics.
Na época em que este artigo foi escrito, a mencionada extensão possuía uma limitação quanto à gravação de microcontroladores. Essa limitação restringe a gravação do microcontrolador somente à abertura de uma sessão de depuração por meio da conexão SWD. No entanto, com o recurso a ser apresentado neste tópico, você será capaz de programar seu dispositivo por meio de qualquer interface de programação. Adicionalmente, será possível incorporar diversas outras etapas ao processo de programação, utilizando os recursos discutidos neste artigo.
Para começar, após ter importado um projeto no VSCode, crie um arquivo com a extensão .py na mesma pasta do seu projeto. Isso será utilizado para criar um script em Python.
Fonte: Captura de tela realizada pelo autor.
Você pode utilizar o seguinte script em Python para executar a gravação do seu código por meio do VSCode. Será necessário apenas ajustar os parâmetros dentro da seção USER SETTINGS, de acordo com as especificações do seu projeto. Sinta-se à vontade para personalizar o script conforme suas necessidades:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
import os # --------------------- USER SETTINGS -------------------# file_name = 'HelloWorld_FranzininhoC0' connection_string = 'port=swd freq=4000 mode=normal' run_after_prog = True # True / False run_address = '0x08000000' verbosity_level = '3' # 1, 2, 3 mass_erase = False # True / False # ------------------ USER SETTINGS END ------------------# # File Settings file_format = 'bin' file_folder = 'build\debug\\build' file_path = os.getcwd() # File path string creation file_string = file_path + '\\' + file_folder + '\\' + file_name + '.' + file_format # Command String initialization command_string = 'cmd /k "STM32_Programmer_CLI -c ' + connection_string # Verbosity Level command_string += ' -vb ' + verbosity_level # Erase String if(mass_erase == True): command_string += ' -e all' #Programming String command_string += ' -w ' + file_string + ' 0x08000000' # Run after programming String if(run_after_prog == True): command_string += ' ' + '-s ' + run_address # End of String command_string += '"' os.system('cls') print(command_string) os.system(command_string) |
Após salvar o script em Python, execute-o pelo VSCode e veja o resultado!
Fonte: Captura de tela realizada pelo autor.
Programando a Franzininho C0 pelo VSCode
Dado que a placa Franzininho C0 não inclui um gravador ST-LINK, ela utiliza o bootloader interno do microcontrolador para a programação. Por consequência, a extensão da ST para o VSCode não suportará a programação dessa placa. Como discutido previamente, a criação de um script Python torna-se uma solução prática para realizar essa tarefa.
Para prosseguir, basta seguir os passos apresentados no tópico anterior para criar um arquivo em Python preenchido com o script fornecido, com uma alteração importante. Originalmente, o script foi elaborado para estabelecer uma conexão via SWD com o alvo a ser programado. No entanto, a Franzininho C0 estabelece uma conexão via UART com o computador. Por esse motivo, é essencial modificar o parâmetro “connection_string” no script, a fim de estabelecer a conexão via UART.
Alteração da string para conexão via UART:
1 |
connection_string = 'port=COM4’ |
Lembre-se de atualizar o número da porta conforme a porta aberta em seu computador.
Após ajustar o script, conecte a Franzininho C0 em seu computador via USB e a coloque em modo de gravação via bootloader. Após esta etapa, clique em build no VSCode e, em seguida, execute o arquivo Python.
Fonte: Captura de tela realizada pelo autor.
Com isso, concluímos o nosso artigo sobre a interface de linha de comando do STM32CubeProgrammer. Espero sinceramente que este conteúdo tenha enriquecido seu conhecimento no campo de sistemas embarcados e que ele se revele valioso em seus projetos atuais e futuros envolvendo a família STM32.
Desejo a você sucesso e realização em suas empreitadas com STM32.
Referências
Aqui vai alguns links de materiais e referências que foram utilizados para a composição deste artigo e que também trazem mais informações acerca dos assuntos tratados neste documento.
STM32CubeProgrammer software description – User manual
STM32CubeProg – STM32CubeProgrammer software for all STM32
STMicroelectronics provides full STM32 support for Microsoft Visual Studio Code