Este artigo compõe a série Primeiros Passos com o ESP32 e o Apache NuttX. Uma série cujo objetivo é apresentar um overview do Sistema Operacional de Tempo Real Apache NuttX e prover instruções para utilizar o Apache NuttX no ESP32.
Caso você esteja iniciando no universo Apache NuttX, é recomendada a leitura deste artigo, no qual Sara Monteiro explica o processo de preparação do ambiente de desenvolvimento e descreve os passos necessários para compilar o Apache NuttX e fazer o upload do firmware para a memória Flash do ESP32.
Neste artigo, como o repositório oficial do QEMU não tem suporte ao ESP32, compilaremos o fork da Espressif do QEMU, configurar o NuttX para funcionar com o emulador e compilar um exemplo para demonstração. Vale notar que, apesar de existir uma variação do QEMU com suporte ao ESP32 desenvolvida pela Espressif, a empresa não oferece suporte oficial ao QEMU.
O que é QEMU ?
QEMU (de Quick EMUlator) é um software open source criado por Fabrice Bellard para a criação de ambientes de virtualização e emulação.
Em emulações, seu principal objetivo é executar sistemas operacionais e aplicações desenvolvidas para outra plataforma de hardware. Por exemplo, executar um software criado para a plataforma ARM em um computador baseado em x86.
Já em virtualizações, o QEMU emula dispositivos e instruções privilegiadas utilizando módulos de kernel (KQEMU ou KVM) e o ambiente de máquina virtual provido pelo sistema operacional. É tipicamente utilizado para executar o sistema Windows em computadores utilizando Linux.
Caso deseje saber mais, visite a página oficial do projeto.
Por quê utilizar QEMU ?
Uma das principais vantagens da utilização do QEMU é a possibilidade de testar um software sendo desenvolvido sem precisar adquirir o hardware necessário para executá-lo.
Além disso, outras vantagens incluem a depuração de problemas sem precisar de um conversor JTAG/Serial e a possibilidade de emulação com mais memória que no módulo físico correspondente.
Instalação
Pré-requisitos
Assumiremos aqui que o ambiente de desenvolvimento com Apache NuttX já esteja configurado conforme o passo a passo descrito no primeiro artigo da série utilizando o sistema Ubuntu 20.04 LTS. Além disso, assegure-se de que os repositórios nuttx e nuttx-apps estejam atualizados.
cd ~/nuttxspace/nuttx
git pull origin master
cd ~/nuttxspace/apps
git pull origin masterPrimeiramente, precisamos instalar alguns pacotes necessários para a compilação do QEMU:
sudo apt install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build libgcrypt-dev python3Agora podemos prosseguir com o download do fork da aplicação QEMU. Nesse tutorial, clonaremos o repositório na pasta esp-qemu dentro do diretório home do usuário:
git clone https://github.com/espressif/qemu ~/esp-qemuCom esses passos, temos tudo o que precisamos para a compilação do QEMU com suporte a processadores com arquitetura Xtensa.
Compilação
Com os arquivos preparados para a configuração e compilação, podemos configurar o sistema de compilação para selecionar as funcionalidades necessárias para o funcionamento do ESP32 (caso deseje saber mais sobre as opções de configurações disponíveis, execute ./configure --help dentro da pasta esp-qemu):
cd ~/esp-qemu
./configure --target-list=xtensa-softmmu \
--enable-gcrypt \
--enable-debug --enable-sanitizers \
--disable-strip --disable-user \
--disable-capstone --disable-vnc \
--disable-sdl --disable-gtkApós o processo de configuração ser concluído, podemos compilar a aplicação para gerar o executável do QEMU com suporte ao ESP32:
ninja -C buildApós concluída esta etapa, será gerado o executável qemu-system-xtensa na pasta build. Com o QEMU instalado, precisamos configurar nosso sistema NuttX para funcionar em conjunto com o QEMU.
Configuração do RTOS NuttX
Agora precisamos configurar a nossa aplicação para ter suporte ao QEMU. Como o emulador requer que as partições da memória estejam em um arquivo só, precisamos habilitar a configuração de fusão dos arquivos binários em apenas um.
Primeiramente, garanta que não exista nenhuma configuração aplicada no sistema NuttX:
cd ~/nuttxspace/nuttx
make distcleanEm seguida, podemos selecionar uma aplicação para ser compilada. Utilizaremos a aplicação NuttShell como exemplo a ser emulado.
./tools/configure.sh esp32-devkitc:nshPara a execução no emulador QEMU, precisamos alterar algumas opções de configuração. Acesse o menu de configuração:
make menuconfigDentro do menu, navegue para Board Selection e selecione a opção ESP32 binary image for QEMU. Salve e saia do menu.
Iremos, agora, gerar a imagem do sistema NuttX com a aplicação NuttShell para ser executada no emulador:
make ESPTOOL_BINDIR=../esp-bins -jCaso os passos tenham sido seguidos corretamente, a mensagem Generated: nuttx.merged.bin (QEMU compatible) deverá ser exibida no fim da compilação.
Execução de Aplicações
Para executarmos nossa aplicação, precisamos voltar na pasta onde se encontra nosso executável do QEMU e rodá-lo com as configurações corretas para o ESP32:
cd ~/esp-qemu/build
./qemu-system-xtensa -nographic \
-machine esp32 \
-drive file=~/nuttxspace/nuttx/nuttx.merged.bin,if=mtd,format=rawCaso tudo tenha ocorrido com sucesso, a aplicação será executada no terminal em um ESP32 emulado pelo QEMU:
Para encerrar a aplicação, aperte Ctrl-A e em seguida a tecla X.
Depuração usando GDB
Podemos também executar o emulador com o servidor do GDB ativo para podermos fazer debug no programa sendo executado. Para isso, precisamos primeiro instalar o GDB para o ESP32:
sudo apt install python2.7 libpython2.7-dev
wget -qO- https://github.com/espressif/binutils-gdb/releases/download/esp-gdb-v12.1_20221002/xtensa-esp-elf-gdb-12.1_20221002-x86_64-linux-gnu.tar.gz | tar -xvz
sudo mv xtensa-esp-elf-gdb/ /opt/xtensa/
echo "export PATH=\$PATH:/opt/xtensa/xtensa-esp-elf-gdb/bin" >> ~/.bashrc
echo "export QEMU_XTENSA_CORE_REGS_ONLY=1" >> ~/.bashrc
source ~/.bashrcAgora podemos executar o QEMU esperando por uma conexão do GDB para debug:
./qemu-system-xtensa -nographic -s -S \
-machine esp32 \
-drive file=~/nuttxspace/nuttx/nuttx.merged.bin,if=mtd,format=rawA emulação não será iniciada até uma conexão do GDB ser realizada. Para isso, executamos em um outro terminal o seguinte comando para executar o debugger:
xtensa-esp32-elf-gdb ~/nuttxspace/nuttx/nuttx \
-ex "target remote :1234" \
-ex "monitor system_reset" \
-ex "tb app_main"Com o GDB conectado, é possível adicionar breakpoints e watches para debug. Para continuar a emulação, basta executar o comando continue ou c.
Para uma depuração mais a fundo, não se esqueça de habilitar as opções de debug desejadas no menuconfig do NuttX.
Considerações Finais
Nesse tutorial você viu como instalar e utilizar o QEMU, executar o sistema NuttX em um ESP32 emulado e utilizar ferramentas de depuração no mesmo.
Para saber mais sobre as limitações de emular o ESP32 utilizando o QEMU ou possui alguma dúvida, acesse a wiki do fork.
Referências
Site Oficial QEMU: https://www.qemu.org/
Wiki QEMU Espressif: https://github.com/espressif/qemu/wiki
Documentação ESP-IDF: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-tools.html
Documentação NuttX: https://nuttx.apache.org/docs/latest/index.html





Bacana! Funcionou tranquilo.
Isso também me lembrou a possibilidade de emular esp32 com nuttx também no picsimlab (qemu-fork integrado).
Tutorial perfeito Lucas! Parabens, me ajudou bastante aqui!