Executando aplicações .NET no Linux Embarcado em processadores ARM com Mono

Por que falar de .NET em Linux Embarcado?

 

No início, Bill Gates criou o Windows....

 

E aí, com a popularização da computação, vieram milhares de programas para fazer com que os computadores fossem úteis. Na área de sistemas embarcados, apenas nos últimos anos, a arquitetura ARM se popularizou e com ela o uso de Linux Embarcado (considerando que você não está utilizando um microcontrolador).

 

O aumento da capacidade de processamento dos ARMs junto com o custo reduzido, robustez e baixo consumo (e consequentemente pequena geração de calor) leva muitas empresas que adotam arquitetura x86 em seus equipamentos avaliarem a migração para ARM. O problema surge quando tais empresas possuem software legado desenvolvido para o sistema operacional Windows, principalmente utilizando a tecnologia .NET. A má notícia é: Windows não roda em ARM!

 

Sendo mais preciso, o cenário atual é que apenas as versões do Windows Embedded Compact são capazes de rodar em processadores ARM, entretanto a Microsoft já anunciou que não vai mais atualizar a linha Windows Embedded Compact. Atualmente, existe o Windows 10 IoT Core que pode rodar em ARM, ele utiliza uma tecnologia chamada Universal Apps que permite que tais aplicativos sejam executados em qualquer plataforma rodando Windows 10, desde uma RPi3, passando pelo XBOX, Hololens, até um computador tradicional. Isso, entretanto, não resolve o problema. O Windows Embedded Compact não funciona com .NET (ou seja, é preciso recompilar a aplicação utilizando o .NET Compact – um subset do .NET tradicional) e o Universal Apps requer uma nova programação. Assim em nenhum caso o software legado é aproveitado.

 

 

Profecias do futuro...

 

Recentemente a Qualcomm demonstrou o Windows 10 full rodando em um processador ARM SNAPDRAGON 820. Será o fim da era x86? Será que alguém na Intel está muito irritado? Enquanto ficamos ansiosos por cenas dos próximos capítulos, comecei minha poupança pessoal para meu próximo notebook que deverá ser lançado em breve de acordo com diversas notícias circulando na rede.

 

 

Mono, uma solução para .NET em Linux Embarcado

 

Enquanto o futuro não chega, algumas opções são possíveis para executar software legado em Linux Embarcado rodando em processadores ARM. Uma delas é o Mono, uma implementação open source do .NET patrocinado pela própria Microsoft. Visite o seu site. Ele permite compilar e executar arquivos “.exe” criados para x86/Windows tradicional em Linux Embarcado, por exemplo. Vale a pena a leitura e pequenos testes descritos no artigo Mono Basics.

 

Para validar a utilização do Mono, propusemos dois pequenos desafios. Criar um programa que, compilado em Visual Studio 2015 para Windows 10 em x86, desenvolvido em C# utilizando .NET framework 4.0, fosse executado em Linux Embarcado em ARM através do Mono e:

  1. Fosse capaz de enviar e receber comandos via interface serial;
  2. Fosse capaz de modificar e ler o status de um pino de IO digital (GPIO).

 

O hardware que utilizamos é um Colibri iMX6DL 512 MB em conjunto com uma Iris Carrier Board, ambos da Toradex.

 

 

Suportando o Mono em um SoM Toradex Colibri iMX6DL

 

Para instalar o mono, será necessário um build padrão do Linux Embarcado. Para informações de como conseguir esse build, consulte este artigo. Após adquiri-lo, iremos adicionar o Mono em nossa imagem. O procedimento se resume a baixar o Mono de um repositório e adicionar o comando que realiza a sua instalação. Para isso, siga os passos abaixo:

 

Clonar do repositório "git://git.yoctoproject.org/meta-mono" dentro do diretório “oe-core/layers”.

 

Adicionar a linha citada abaixo no arquivo "bblayers.conf" no diretório "oe-core/build/conf/bblayers.conf".

 

Adicionar o comando citado abaixo no arquivo “local.conf”, que pode ser encontrado no diretório “/oe-core/build/conf/local.conf”.

 

Após realizar os passos citados acima, é necessário compilar a imagem. Caso você esteja começando a aprender Linux, sugiro que assista este webinar, onde encontram-se informações mais detalhadas.

 

 

Realizando os testes

 

Realizamos os testes com sucesso e realmente o Mono deu conta do recado. O vídeo abaixo apresenta o teste em execução e o sistema rodando:

 

 

Agora vamos aos detalhes. O Windows nomeia as portas seriais como COM1, COM2, etc. Já o Linux as abstrai através de um “arquivo” em “/dev/tty***”. A programação do aplicativo .NET utilizou um componente conhecido como SerialPort e diversas configurações foram realizadas. O único detalhe foi dar o nome correto da porta ao executar a aplicação no Linux. Veja a figura abaixo:

 

Desenvolvimento de aplicação .NET no Visual Studio para rodar no Mono.
Figura 1 - Desenvolvimento de aplicação .NET no Visual Studio para rodar no Mono.

 

Já o acesso ao GPIO não é feito de forma padronizada no Windows como no Linux. Como de costume, o Linux abstrai GPIOs através de drivers de kernel (sysclass). Sendo assim, o código em C# para acessar o pino de GPIO e para modificar seu status fica tão simples como pode ser visualizado na figura abaixo:

 

Código em C# para acessar o pino de GPIO - Execução no Mono
Figura 2 - Código em C# para acessar o pino de GPIO

 

 

Conclusão

 

Nem tudo são flores, de uma forma ou de outra, alguma adaptação será necessária para utilizar o Mono e rodar seu software legado Windows em um sistema embarcado com Linux. Entretanto, isso pode ser alcançado com sucesso.

 

Se você não quer ou não tem tempo para reescrever seu código, Mono pode ser uma saída para o problema, pelo menos até você migrar para Linux ou o Windows migrar para ARM!

 

Agradecimento especial ao Daniel Morais que executou os testes do Mono e escreveu o artigo em conjunto!

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Daniel Augusto Soré de Morais
Estudante de Engenharia Elétrica com ênfase em eletrônica na UNIP de Jundiaí e técnico mecatrônico pelo Divino Salvador. Estagiário em Linux embarcado na empresa Toradex Brasil.

3
Deixe um comentário

avatar
 
3 Comment threads
0 Thread replies
2 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
Guilherme FernandesGuilherme RamalhoRodrigo Cesar Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Guilherme Fernandes
Visitante
Guilherme Fernandes

Rodrigo e Guilherme,

Realmente o problema do método de DataReceived foi algo que percebemos e contornamos com polling! De qualquer forma, conforme comentamos no artigo, esperamos ansiosos pelos primeiros notebooks rodando em ARM!

Guilherme Ramalho
Membro
GuilhermeRamalho20

Ótimo post, parabéns ! Trabalho em um projeto exatamente com essa arquitetura, ou seja, desenvolvo todo o código no Visual Studio e rodo o executável no meu Linux embarcado via mono. O Daniel comentou bem, "Nem tudo são flores", existem algumas limitações. Tive o mesmo problema relatado pelo Rodrigo Cesar. Até onde eu sei o mono não contempla o evento para recepção serial, porém isso pode ser "contornado" utilizando pollings. Recentemente também tive dificuldade para referenciar uma DLL externa em um diretório, mesmo que a DLL tivesse no mesmo diretório do executável o mono retornava erro: "DLL not found", nesse… Leia mais »

Rodrigo Cesar
Visitante
Rodrigo Cesar

Já migramos nossa aplicação, com WCF, SqLite, comunicação USB e Serial para rodar no Mono e RaspberryPi 3. Tivemos que contornar problemas em todos os casos. Mas tá funcionando.
No Serial, por exemplo, o evento DataReceived do SerialPort não é disparado. Tivemos que criar uma Task para ficar lendo constantemente os dados recebidos.