Apresentei no post anterior minhas aventuras com o porte do .NET nanoFramework para Linux e NuttX, nesse artigo irei mostrar como foi possível executar aplicações .NET nanoFramework usando esse porte em um Raspberry Pi Pico 🤯.
Para armazenar sua aplicação .NET temos duas opções. Carregar os assemblies de um SDCard, ou gerar um arquivo .uf2
com os assemblies compilados em conjunto com o firmware do runtime.
⚠️ Para gerar o firmware do runtime é necessário ter o Docker rodando no seu computador de desenvolvimento.
⚠️ Se você optar por usar o SDCard para carregar os assemblies, conecte o módulo SDCard como segue no modelo a seguir:
Connection:
SD card slot Raspberry Pi Pico
DAT2 (NC)
DAT3/CS ----- GP17 (SPI0 CSn) (Pin 22)
CMD /DI ----- GP19 (SPI0 TX - MOSI) (Pin 25)
VDD ----- 3V3 OUT (Pin 36)
CLK/SCK ----- GP18 (SPI0 SCK) (Pin 24)
VSS ----- GND (Pin 3 or 38 or ...)
DAT0/DO ----- GP16 (SPI0 RX - MISO) (Pin 21)
DAT1 (NC)
Para o exemplo em C#
que irei demonstrar, também estou usando um push button conectado ao GP6
, pino 9 da Pi Pico:
⚠️ No NuttX os GPIOs não são alocados por demanda, mas sim pré configurados durante a build (isso é algo que estou trabalhando para modificar). Sendo assim, por enquanto apenas os seguintes GPIOs da Pi Pico estão disponíveis para uso:
GP25 = GpioPinDriveMode_Output;
GP2 = GpioPinDriveMode_Output;
GP3 = GpioPinDriveMode_Output;
GP4 = GpioPinDriveMode_Output;
GP5 = GpioPinDriveMode_Output;
GP6 = GpioPinDriveMode_Input;
GP7 = GpioPinDriveMode_Input;
GP8 = GpioPinDriveMode_Input;
GP9 = GpioPinDriveMode_Input;
Você pode usar qualquer solução criada pela extensão do .NET nanoFramework para Visual Studio.
Caso você seja usuário Linux, infelizmente não há ainda um template para o dotnet
CLI (para ficar independente do VS 2019 por exemplo). Para esse caso eu criei um exemplo que você pode clonar o repositório e usar com o VS Code.
Siga os passos com um terminal aberto:
1- Clone o repositório dos exemplos:
git clone https://github.com/dotnuttx/nanoFrameworkPOSIX-samples.git
2- Entre na pasta PiPico
:
cd nanoFrameworkPOSIX-samples/PiPico
Para fins de demonstração vamos compilar o seguinte Program.cs
:
using System.Diagnostics;
using System.Threading;
using System.Device.Gpio;
using nanoFramework.Runtime.Native;
GpioController gpioController = new GpioController();
// GP25 (onboard LED)
GpioPin onBoardLED = gpioController.OpenPin(25, PinMode.Output);
// GP6 (pin 9)
GpioPin button = gpioController.OpenPin(6, PinMode.Input);
while (true)
{
// blink
onBoardLED.Toggle();
// check if button is pressed
if (button.Read() == PinValue.High)
{
Debug.WriteLine($"Running nanoFramework on {SystemInfo.TargetName}");
Debug.WriteLine($"Platform: {SystemInfo.Platform}");
Debug.WriteLine($"Firmware info: {SystemInfo.OEMString}");
}
Thread.Sleep(500);
}
⚠️ Se você estiver no Windows usando o VS 2019 e a extensão do nanoFramework, basta realizar oBuild Solution
para gerar os assemblies.
⚠️ Se você estiver no Linux siga os comandos do CLI. Irei usar comandos que fazem parte do Mono. Tenha certeza de ter instalado o pacote mais recentemono-complete
em sua distro Linux.
3- Faça download dos pacotes NuGet listados no packages.config
, execute na raiz da pasta PiPico/
:
nuget restore
⚠️ A versão2.6.4.6
do runtime pararp2040
precisa exatamente da versão1.10.5-preview.18
do pacotenanoFramework.CoreLibrary
4- Compile a solução, execute:
msbuild
Após a build você deverá ter os seguintes arquivos com extensão .pe
na pasta bin/Debug/
do projeto:
ls -l bin/Debug/*.pe
-rw-r--r-- 1 castello castello 960 Jun 23 00:34 bin/Debug/PiPico.pe
-rwxr--r-- 1 castello castello 5684 Jun 19 08:09 bin/Debug/System.Device.Gpio.pe
-rwxr--r-- 1 castello castello 31668 Jun 19 07:25 bin/Debug/mscorlib.pe
-rwxr--r-- 1 castello castello 3412 Jun 19 07:44 bin/Debug/nanoFramework.Runtime.Events.pe
-rwxr--r-- 1 castello castello 1496 Jun 19 07:46 bin/Debug/nanoFramework.Runtime.Native.pe
Esses são os Portable executables
/assemblies
que o interpretador do .NET nanoFramework sabe ler e executar. Se você tem eles listados na pasta bin/Debug/
do projeto PiPico
, parabéns 🎉 você compilou a aplicação com sucesso.
1- Formate um SDCard para FAT32
e copie todos os arquivos .pe
da pasta bin/Debug/
para a raiz do SDCard.
⚠️ Não se preocupe com capacidade de armazenamento do SDCard, recomendo usar o de menor capacidade disponível. Os assemblies gerados são bem pequenos.
4- Remova o SDCard do seu computador de desenvolvimento e plugue no módulo SDCard conectado ao Pi Pico.
3- Instale o nanoFramework Runtime (Raspberry Pi Pico RP2040) na placa. Você pode baixar binários pré-compilados do runtime para Raspberry Pi Pico RP2040 aqui: https://github.com/dotnuttx/nf-Community-Targets/releases
Baixe o arquivo dotnet-nf.rp2040-Nuttx.2646.uf2 .
Ligue o Raspberry Pi Pico, com o botão BOOTSEL
pressionado, via USB ao seu computador de desenvolvimento:
Copie o arquivo dotnet-nf.rp2040-Nuttx.2646.uf2
para o armazenamento listado. Pronto, runtime instalado 😎.
1- Faça pull da Docker image:
docker pull dotnuttx/generate-pico-uf2
2- Na pasta da sua solução, no nosso exemplo nanoFrameworkPOSIX-samples/PiPico
, execute o seguinte comando:
docker run --rm -it -v "$(pwd)/bin/Debug:/nf" dotnuttx/generate-pico-uf2
Esse comando ira compartilhar com o container a pasta bin/Debug
da sua solução e irá gerar um arquivo .uf2
, esse irá conter o .NET nanoFramework runtime com os assemblies .pe
já embutidos, pronto para ser gravado na sua Raspberry Pi Pico.
Após a execução do comando verifique se um novo arquivo chamado dotnetnf.uf2
foi criado na pasta bin/Debug
da sua solução. Caso positivo, parabéns 🎉 você gerou seu firmware customizado.
3- Instale seu nanoFramework Runtime (Raspberry Pi Pico RP2040) na placa. Ligue o Raspberry Pi Pico, com o botão BOOTSEL
pressionado, via USB ao seu computador de desenvolvimento:
Copie o arquivo dotnetnf.uf2
para o armazenamento listado. Pronto, seu runtime foi instalado 😎.
Após a instalação do firmware (cópia do arquivo .uf2
), a placa irá se auto reiniciar e o runtime irá executar a aplicação automaticamente.
⚠️ O firmware também cria uma porta serial via o USB conectado ao seu computador, assim podemos visualizar o retorno doDebug.WriteLine
. Se conecte na serial, no caso do Linux será listada em/dev/ttyACMx
e no Windows o padrãoCOMx
, com um baud rate de115200
.
Se após instalar o runtime você tiver o LED on board da Pi Pico piscando, e ao pressionar o botão a seguinte mensagem for escrita na serial:
Parabéns 🎉! Você executou sua primeira aplicação .NET em uma Raspberry Pi Pico 🤯.
.NET nanoFramework 🤘! Mas vale lembrar que:
⚠️ Esse em um porte não oficial! É algo que estou trabalhando nos finais de semana e durante meu tempo livre, algoEXTREMAMENTE EXPERIMENTAL
. Não estou sendo financiado por nenhum grupo ou instituição para tal.
Há muito trabalho pela frente, por enquanto das features específicas de hardware, só GPIO (in e out) estão implementadas (suporte há i2c vem em breve). Para mais informações leia o blog post: Portando .NET nanoFramework para Linux e Nuttx
Já sabemos que o time principal do .NET nanoFramework está trabalhando em um porte da Pi Pico para o Azure RTOS. Os meus experimentos são válidos (eu acho 🤔) como prova de conceito do porte POSIX do nanoFramework. Trabalhando nesse porte podemos rodar o nanoCLR
em um arsenal de + de 67 placas microcontroladas de diferentes arquiteturas, das quais o NuttX tem suporte (NuttX é um RTOS com compatibilidade incrível à POSIX), e + uma infinita lista de plataformas e arquiteturas microprocessadas que rodam Linux.
Gostou da possibilidade? Se isso for de alguma forma útil, ou fizer sentido para você, deixe me saber. Me mande um alô no Twitter @math_castello ou no Linkedin 👍