By João Peterson on 4 Jul 2024 | 20:00 .
Categories | Linux | Tutorials | Embedded
Tempo de leitura: #
Visualizações: #
Sumário
Introdução
Desenvolver sistemas embarcados sempre é uma dor de cabeça para começar. Configurar ambientes em máquinas com softwares proprietários geralmente leva muito tempo e acabamos com um setup frágil, então quando se precisa mudar de máquina, formatar ou compilar projetos em outro local tendemos a descobrir que não vai funcionar de primeira novamente.
Por isso gosto sempre de ir atrás de soluções mais open source e mais simples, sem IDE’s integradas, apenas um editor de texto e uma linha de comando. Queria mostrar assim então como podemos instalar e configurar de forma simples um SDK de programação, neste caso o MCUXpress da NXP, e como usá-lo com o editor de texto favorito da gurizada, Vscode.
Quero notar também que existe uma extensão oficial para o Vscode que facilita todo esse processo, e é de fato, a forma mais fácil de usar o SDK com o Vscode, mas ele te tira um pouco a liberdade de usar como quiser, e se você usar a extensão a experiência será muito semelhante a usar a IDE própria da NXP, que pode até ser melhor pois tem ferramentas dedicadas para o desenvolvimento.
Também vale notar que também poderíamos usar a extensão Platform.io, que também permite instalação e desenvolvimento com MCUXpress SDK e também de diversa plataformas embarcadas.
SDK
Dependências
Para instalar o SDK precisamos primeiros instalar as seguintes dependências:
Archlinux
No archlinux podemos instalar tudo a partir do pacman:
$ sudo pacman -Ss git arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-gdb arm-none-eabi-newlib
Exceto o west, que podemos instalar via pip:
$ pip3 install --user -U west
OU pelo aur:
$ yay -S python-west
Repositório
Vamos então clonar o repositório usando a ferramenta west, que a NXP escolheu como forma de manejo dos repositórios.
A forma de organização é a seguintes, a NXP disponibiliza o SDK, exemplos e middlewares na forma de diferentes repositórios no Github, então, se você deseja somente os componentes básicos como acesso as registradores, drivers de periféricos, camada CMSIS, ferramentas e scripts de build, basta clonar o repositório principal.
Agora de você deseja a camada de middleware, com mais abstrações e também exemplos, temos que usar a ferramenta west, qual vai coordenar o pull desses vários repositórios com a versão desejada. Aqui vamos puxar tudo pra ser mais completo.
Primeiro vamos definir qual versão desejamos, no github do SDK, e clicando no menu das branches, onde se diz main
, vamos clicar em tags e escolher a versão desejada, vamos usar aqui a última versão estável, MCUX_2.16.000
.
Então vamos criar uma pasta temporária e usar o west para puxar o SDK na versão escolhida.
$ mkdir mcuxsdk
$ west init -m "https://github.com/NXPmicro/mcux-sdk" --mr "MCUX_2.16.000" mcuxsdk
$ cd mcuxsdk
$ west update
$ cd ..
Aceite as confirmações e aguarde o download, vai demorar, aqui ficou em cerca de 13 Gb a instalação total.
Agora vamos instalar em um lugar mais fixo em nossa máquina para facilitar referencia-lo em nossas ferramentas, eu recomendo mover o repositório para usr/share/mcuxsdk
.
$ sudo mv mcuxsdk /usr/share/
$ cd /usr/share/
$ sudo chown -R root:root mcuxsdk
Variáveis de ambiente
Para que os arquivos de build se achem depois, vamos definir algumas variáveis de ambiente, para a arm toolchain e para o sdk. Para isso vai depender do seus tipo de shell vamos os valores serão basicamente estes:
ARMGCC_DIR=/usr
SdkRootDirPath=/usr/share/mcuxsdk
ZSH ou BASH
Para estas basta adicionar as seguintes linhas em .bashrc
ou .zshrc
:
export ARMGCC_DIR=/usr
export SdkRootDirPath=/usr/share/mcuxsdk/2.16
Configurando Projeto
O SDK provém templates e exemplos prontos já, mas você irá notar que estes só funcionam dentro das pastas do SDK pois algumas referências são feitas de forma relacional e não absoluta, então para copiar e usar os templates precisamos arrumar alguns paths.
Vamos demonstrar usando a demo hello_world da placa EVKBIMXRT105, vamos copiar o exemplo para uma pasta de trabalho.
$ cp -r /usr/share/mcuxsdk/examples/evkbimxrt1050/demo_apps/hello_world .
Dentro da pasta armgcc
do projeto temos vários scripts bat
e sh
, que chamam o sistema de build Cmake para compilar os projetos do SDK. Só que esses tem a referência relacional ao sdk, vamos mudar essa para o path absoluto do SDK via a variável de ambiente SdkRootDirPath
e assim vamos conseguir compilar.
Recomendo usar a ferramenta de search and replace do Vscode para substituir o seguinte regex:
DCMAKE_TOOLCHAIN_FILE=".+/core
por:
DCMAKE_TOOLCHAIN_FILE="$SdkRootDirPath/core
``
apenas no arquivos *.sh
.
Assim, por exemplo, build_debug.sh
irá ser:
#!/bin/sh
if [ -d "CMakeFiles" ];then rm -rf CMakeFiles; fi
if [ -f "Makefile" ];then rm -f Makefile; fi
if [ -f "cmake_install.cmake" ];then rm -f cmake_install.cmake; fi
if [ -f "CMakeCache.txt" ];then rm -f CMakeCache.txt; fi
cmake -DCMAKE_TOOLCHAIN_FILE="$SdkRootDirPath/core/tools/cmake_toolchain_files/armgcc.cmake" -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=debug .
make -j 2>&1 | tee build_log.txt
Agora dentro de armgcc
ainda, podemos tentar compilar invocando:
$ ./build_debug.sh
Se algo der errado, verifique se a sua linha de comando está carregando as variáveis de ambiente, se as variáveis estão sendo configuradas corretamente e se o valores delas batem com os paths de instalação.
Flash / Debug
Para gravar programas vai depender muito do fabricante do seu chip, por exemplo, para familia AVR podemos usar um conversor USB/Serial e o programa avrdude para gravar. Já o STM32 precisamos de um STLink e do programa que vem com o SDK.
No caso do IMXRT105 da NXP não é diferente, mas em todos os casos nós podemos usar o programa openocd, que nos permite gravar diretamente no processador um programa de debug e ter capacidades de debug com GDB, o que é bastante interessante pois o openocd funciona bastando apenas que nosso chip/placa possua uma interface SWD/JTAG, sem precisar de uma probe proprietária e específica.
Assim que configurarmos o openocd, vamos poder abrir um servidor GDB qual nosso vscode poderá interagir e utilizar as suas funções de debug e watch, que é uma das regalias que desejamos e o principal motivo de usar o vscode.
Para instalar vai depender do seus sistema mas ele está disponível geralmente no gerenciador de pacotes ou então com executáveis no website.
No archlinux:
$ sudo pacman -S openocd
Depois disso vamos criar dentro da pasta do projeto um arquivo de configuração:
openocd.cfg
:
source [find interface/cmsis-dap.cfg] # interface da minha placa é a padrão CMSIS-DAP
source [find imxrt.cfg] # target customizado para a familia do processador
set _CHIPNAME MXRT105 # nome
adapter speed 2000 # velocidade
O arquivo de configuração basicamente define:
- A interface a ser usada, por exemplo, probes JLink, STLink, ou no meu caso, minha placa já vem com interface debug em hardware padrão CMSIS-DAP.
- O target, ou arquitetura, por exemplo, atmega32, stm32, ou no meu caso, imxrt. (Normalmente usaríamos algo como “target/atmega” ou algo do tipo, mas nesse caso em específico o arquivo não vem instalado com o openocd nessa versão dentro da pasta
target/
, portanto eu baixei o arquivo aqui, e coloquei na pasta do projeto para poder importar dentro desse arquivo de configuração) - Configurações secundárias como nomes, velocidade de comunicação e protocolo, por exemplo SWD ou JTag.
Assim basta executar:
$ openocd
E o servidor GDB será aberto e sua conexão com o chip será feita
Vscode
Debug
Agora do lado do Vscode vamos fazer o debug funcionar, para isso vamos a pasta (se não existir ainda) .vscode
, e dois arquivos dentro dela:
Launch define iniciar o debug, executando uma build task, se conectando ao GDB e então mostrando a interface de debug no editor. (Lembre de trocar PROJETO
pelo nome do seu executável e a preLaunchTask
também)
launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"name": "PROJETO (debug)",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/armgcc/debug/PROJETO.elf",
"preLaunchTask": "build debug",
"MIMode": "gdb",
"miDebuggerPath": "arm-none-eabi-gdb",
"miDebuggerServerAddress": "localhost:3333",
"useExtendedRemote": true,
"postRemoteConnectCommands": [
{"text": "mon reset"},
{"text": "mon halt"},
{"text": "load"}
]
}
]
}
Em tasks definimos a task para ser executada antes do debug, ou seja, a build_debug. (Note como definimos as variáveis de ambiente aqui também novamente, pois o vscode não usa as mesma variáveis que a linha de comando)
tasks.json
:
{
"version": "2.0.0",
"tasks": [
{
"label": "build debug",
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "armgcc",
"env": {
"ARMGCC_DIR": "/usr",
"SdkRootDirPath": "/usr/share/mcuxsdk/2.16"
}
},
"command": "./build_debug.sh"
}
]
}
Agora abra um terminal, execute o openocd, e dentro do vscode você poderá apertar F5, e a aplicação será compilada, gravada e o debug será aberto no vscode.
Autocomplete
Por fim, para facilitar a vida, vamos adicionar algumas extensões e configurações para podermos ter autocomplete enquanto programamos.
Extensões:
E a configuração dentro de .vscode
:
settings.json
:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/share/mcuxsdk/core/CMSIS/Core/Include/**",
"/usr/share/mcuxsdk/core/CMSIS/Driver/Include/**",
"/usr/share/mcuxsdk/core/drivers/**",
"/usr/share/mcuxsdk/core/components/**",
"/usr/share/mcuxsdk/core/utilities/**",
"/usr/share/mcuxsdk/core/cmsis_drivers/**",
"/usr/share/mcuxsdk/core/boards/evkbimxrt1050/**",
"/usr/share/mcuxsdk/core/devices/MIMXRT1052",
"/usr/share/mcuxsdk/core/devices/MIMXRT1052/**"
],
"defines": [
"CPU_MIMXRT1052DVL6B",
"MCUXPRESSO_SDK",
"SERIAL_PORT_TYPE_UART=1"
],
"compilerPath": "/usr/bin/arm-none-eabi-gcc",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "linux-gcc-arm"
}
],
"version": 4
}
Onde definimos alguns paths para o vscode achar os arquivos fonte do sdk, e alguns defines, esses refletem as configurações do CMake do SDK oficial. Só lembre de apontar para o seu chip específico.
Conclusão
É isso rapaziada, tudo funcionando, só cuidar pra adicionar mais paths no vscode caso ele não ache algum arquivo, ver no console mesmo se tudo está compilando e debugando certinho. Provavelmente você querer fazer alguma coisa extra e vai dar algum pau, mas você terá a liberdade de mexer no processo de compilação e gravação e não vai ficar refém de ferramentas que fazer tudo por trás dos panos.
Vale lembrar que algumas opções mais fáceis como a IDE da NXP, a extensão MCUXpress e Platform.io são maneiras mais fáceis de usar tudo isso, vai do seu grau de conforto, minha opinião é, é fácil no inicio e depois só atrapalha.
E é isso, qualquer sugestão de melhorias ou comentários comente abaixo. Valeu e até a próxima!
Referências
- Giscus
- Getting Start with MCUXpresso SDK
- CMAKE_TOOLCHAIN_FILE
- mcux-sdk-examples/evkbimxrt1050
- MCUXpresso Software Development Kit (SDK)
- MCUXpresso SDK API Reference Manual
- OpenOCD with iMXRT1050 / imxRT1064
- openocd/tcl/target/imxrt.cfg
- Embedded GDB (+ OpenOCD) with VSCode for RP2040
- openocd Config File Guidelines
- OpenOCD/CMSIS-DAP Debugging with Eclipse and without an IDE
- Run a project using armgcc
- Vscode for mcux - Training Getting Started RT1060