Livello: Base - Autore: Andrea Angella
Il presente articolo è suddiviso nelle seguenti sezioni:
- Introduzione allo sviluppo su piattaforme embedded
- Che cos'è e perché è stato creato il .NET Micro Framework
- Versioni disponibili e caratteristiche principali
- Architettura del framework e Common Language Runtime
- Uno sguardo alla Base Class Library
- Come iniziare a sviluppare con il .NET Micro Framework
- Risorse utili per ottenere maggiori informazioni
1. Introduzione allo sviluppo su piattaforme embedded
I sistemi embedded sono sistemi informatici dedicati che vengono progettati, al contrario dei sistemi general purpuse, per svolgere compiti ben precisi e determinati. L'hardware in questo tipo di sistemi è spesso progettato ad hoc e l'interazione con il mondo esterno rende indispensabile la capacità di raccogliere, campionare e trasmettere segnali utilizzando dispositivi quali sensori, attuatori e convertitori A/D e D/A. L'interazione con l'utente avviene con mezzi spesso semplificati quali pulsanti e display di dimensione ridotta. L'affidabilità, il costo e il consumo di energia diventano metriche importantissime da valutare in fase di progettazione e spesso questi sistemi sono soggetti a particolari vincoli real-time che se non rispettati posso anche portare a conseguenze molto gravi.
Esempi di sistemi embedded sono sportelli bancomat, apparecchi POS, telefoni cellulari e smartphone, dispositivi di rete come router o firewall, stampanti, distributori di bevande, elettrodomestici , centraline di controllo nelle automobili, robot industriali ecc. In pratica, qualunque dispositivo hardware dotato di software con lo scopo di risolvere uno specifico problema può essere classificato come un sistema embedded.
Nell'ambito dei sistemi embedded sono disponibili un'ampia varietà di microprocessori dedicati a 8, 16 e 32 bit. Visto il crescente utilizzo di questo tipo di sistemi sia in ambiente industriale sia in ambiente consumer, Microsoft negli ultimi 10 anni ha rilasciato diversi strumenti e in particolare sistemi operativi per l'utilizzo delle risorse hardware dei sistemi embedded, che nel tempo si sono rapidamente evoluti fino ai recenti "Windows XP Embedded" e "Windows Embedded CE".
Windows XP Embedded è costruito a partire dal sistema desktop Windows XP ed è caratterizzato da un'alta modularità che permette allo sviluppatore di selezionare solo i moduli e i servizi desiderati, con il vantaggio di ottenere un sistema operativo "ritagliato" in base alle proprie esigenze con basso profilo di memoria e maggiore velocità di boot.
Windows Embedded CE è una piattaforma più leggera di Windows XP Embedded e, in particolare, fornisce il supporto alla realizzazione di applicazioni real-time e la possibilità (in certe configurazioni) di sviluppare applicazioni managed tramite il Microsoft .NET Compact Framework.
Negli ultimi anni, in numero sempre crescente, sono stati realizzati piccoli dispositivi embedded, spesso connessi in qualche modo fra loro, che svolgono "semplici" ma utili funzionalità. Questi dispositivi utilizzano piattaforme hardware molto limitate in termini di memoria disponibile e capacità di elaborazione tanto che spesso non è necessario l'utilizzo di un sistema operativo. In questo scenario, fino a qualche anno fa, non era possibile sfruttare le tecnologie Microsoft, perché i sistemi operativi embedded che essa fornisce hanno requisiti hardware e di memoria eccessivi.
Per questo motivo entra in gioco una nuova e innovativa proposta di Microsoft: il .NET Micro Framework.
2. Che cos'è e perché è stato creato il .NET Micro Framework
La maggior parte degli sviluppatori di sistemi embedded utilizza codice nativo scritto in linguaggio C e talvolta anche direttamente in linguaggio assembly. La necessità di interfacciarsi direttamente con l'hardware richiede una profonda conoscenza della piattaforma sopra la quale si sviluppa e quest'aspetto rende notevolmente complessa anche la realizzazione di semplici applicazioni. A complicare la situazione vi è la disuniformità di tool e ambienti di sviluppo per sistemi embedded che ancora oggi non sono sufficientemente completi. Tutto questo rende difficile la realizzazione, il debugging, il testing e soprattutto la manutenzione dei propri progetti.
La frase utilizzata da Microsoft per far comprendere in poche parole le motivazioni che hanno portato allo sviluppo del Micro Framework è la seguente: "Il .NET Micro Framework si propone per lo sviluppo embedded come ha fatto Visual Basic 6 per lo sviluppo delle vecchie applicazioni desktop".
Il .NET Micro Framework è un ambiente operativo per processori embedded a 32 bit, ormai diventati molto economici e a basso consumo, che aumenta il livello di astrazione al quale lo sviluppatore software di sistemi embedded deve lavorare evitando di "sporcarsi le mani" con fastidiosi dettagli relativi all'hardware sottostante. In questo modo lo sviluppatore potrà preoccuparsi maggiormente dei problemi di alto livello che vuole risolvere: l'interazione con elementi hardware si limiterà all'utilizzo di opportune classi in modo completamente object-oriented, favorendo quindi la realizzazione di software indipendente dalla piattaforma.
Il .NET Micro Framework vuole portare nel mondo embedded i principali vantaggi offerti dal mondo managed, permettendo l'utilizzo di una ricca libreria di funzionalità indipendenti dall'hardware ed accessibili tramite la scrittura di codice C#, supportata da un completo e potente ambiente di sviluppo come Microsoft Visual Studio, che offre anche avanzate funzionalità di debugging ed emulazione del dispositivo reale.
Con il .NET Micro Framework qualsiasi sviluppatore familiare al mondo .NET può diventare, in modo estremamente semplice e veloce, anche uno sviluppatore embedded!
3. Versioni disponibili e caratteristiche principali
Il .NET Micro Framework è stato rilasciato pubblicamente, e messo a disposizione di tutti gli sviluppatori, a partire dalla versione 2.0, resa disponibile nei primi mesi del 2007.
Le principali caratteristiche del .NET Micro Framework sono:
- Disponibilità per i processori a 32 bit a basso costo quali ARM7 e ARM9
- Occupazione di spazio (footprint) molto ridotta, dell'ordine di qualche centinaio di Kilobyte
- Runtime che gestisce il boot autonomamente (non richiede MMU)
- Efficiente controllo sul consumo di energia
- Portabilità su nuove architetture grazie all'utilizzo di un Porting Kit
- Interfacciamento con dispositivi hardware tramite porta seriale RS232, bus I2C o bus SPI
- Ricca libreria indipendente dall'hardware (Base Class Library)
- Runtime grafico basato su un sottoinsieme di WPF (Windows Presentation Foundation)
- Caratteristiche e vantaggi ereditati dal Framework .NET
- Supporto alla localizzazione e alla globalizzazione delle applicazioni
- Notevole supporto alla serializzazione dei dati in forma compressa anche su memoria non volatile
- Estensibilità a livello software e hardware
- Sicurezza grazie all'utilizzo di assembly firmati e meccanismi di crittografia
- Ambiente di sviluppo Microsoft Visual Studio con debugging ed emulazione del device
La versione 2.5 aggiunge il supporto nativo allo stack TCP/IP e ai Web Services (rilasciati in forma separata).
Le novità della versione 3.0, rilasciata nel mese di Ottobre 2008, sono:
- Supporto alla famiglia di processori Blackfin di Analog Devices e il set di istruzioni ARM Thumb e Thumb2
- Riduzione del footprint minimo a 64KB di RAM
- Miglioramenti nell'interoperabilità con codice nativo permettendo l'accesso diretto all'hardware
- Un Porting-Kit più accessibile e facile da utilizzare
- Nuovo supporto alla connettività che comprende Wi-Fi, USB, Web Services for Devices, SSL
- Supporto per un file system compatibile con FAT32
- Supporto delle funzionalità Touch e Gesture per sviluppare applicazioni più interattive
- Integrazione con Visual Studio 2008 e Visual C# 2008 Express Edition
4. Architettura del framework e Common Language Runtime
E' sbagliato e limitativo classificare il .NET Micro Framework come un sistema operativo per lo sviluppo di sistemi embedded. Rispetto alla versione completa del .NET Framework tuttavia il .NET Micro Framework deve in qualche modo sovraintendere alla gestione delle risorse hardware, al controllo dell'esecuzione del codice e alle funzionalità di input/output che rappresentano tipiche caratteristiche fornite intrinsecamente da un sistema operativo. La capacità di essere eseguito direttamente sull'hardware, senza la presenza di un vero e completo sistema operativo, permette di dire che il .NET Micro Framework è un bootable runtime.
Analizziamo ora in maggior dettaglio l'architettura del .NET Micro Framework:

Alla base di tutto c'è la HAL (Hardware Abstraction Layer) che ha il compito di gestire le funzionalità di basso livello direttamente connesse all'hardware e alle periferiche. In particolare la HAL contiene codice assembler per gestire la fase di boot del sistema, le operazioni di I/O, le richieste di interruzioni (IRQ), i timer nativi e i driver delle periferiche implementati dallo specifico OEM (Original Equipment Manufacturer).
Immediatamente sopra la HAL è presente un'importante componente chiamato PAL (Platform Abstaction Layer) che permette di realizzare la completa astrazione dalla piattaforma hardware sottostante fornendo quindi una interfaccia di alto livello per l'implementazione del CLR (Common Language Runtime).
Sulla base delle precedenti affermazioni è facilmente intuibile che il porting del .NET Micro Framework su nuove piattaforme si limiti alla sola riscrittura dei due componenti HAL e PAL. Nel caso in cui si volesse costruire una versione del .NET Micro Framework che venga eseguita sopra un particolare sistema operativo è possibile implementare la sola PAL utilizzando direttamente i servizi offerti dal sottostante sistema operativo. Questo è esattamente il modo in cui è stato realizzato l'emulatore presente nel SDK.
Il CLR del .NET Micro Framework rispetta la CLS (Common Language Specification) e permette l'esecuzione di assembly contenenti l'applicazione sotto forma di codice IL (Intermediate Language). L'utilizzo del codice IL permette teoricamente lo sviluppo con differenti linguaggi di programmazione, tuttavia al momento della scrittura di questo articolo l'unico linguaggio direttamente supportato è il C#.
In particolare il CLR è costituito dalle seguenti parti:
La versione completa del .NET Framework implementa un modello di esecuzione che al momento della chiamata di una funzione prevede la compilazione al volo del codice IL in codice nativo mediante l'utilizzo del JIT (Just in Time Compiler). Dal punto di vista dell'occupazione di memoria un approccio di questo tipo richiede uno spazio doppio in quanto è necessario memorizzare sia la versione IL che la versione nativa del codice applicativo. Siccome la riduzione del footprint dell'applicazione è un aspetto troppo importante per questo tipo di sistemi embedded, i progettisti del .NET Micro Framework hanno deciso di interpretare direttamente il codice IL a scapito di una minore velocità di esecuzione. Tuttavia è importante sottolineare che il codice IL essendo in forma binaria permette di evitare complesse operazioni di parsing dei sorgenti e questo ha permesso la realizzazione di un interprete molto efficiente. Il CLR inoltre realizza l'astrazione dei thread implementando un multitasking di tipo cooperativo con la possibilità di assegnare una priorità a ciascun thread e assegnare un tempo massimo di esecuzione ad una porzione di codice.
Il Type System definisce l'infrastruttura dei tipi all'interno del framework che si possono suddividere in due grandi categorie: value-types e reference-type.
Per il .NET Micro Framework è stata realizzata una versione semplificata e molto leggera del Garbage Collector basata su un algoritmo di Mark and Sweep non incrementale. Il suo vantaggio principale è la minimizzazione dello spazio occupato per la sua implementazione. Inoltre tramite l'utilizzo dei Weak Reference è possibile permettere al Garbage Collector di reclamare e liberare memoria quando si è molto vicini all'esaurimento della stessa (condizioni di Memory Pressure).
Il meccanismo di Interop permette di scrivere funzioni direttamente in codice nativo. Il motivo per cui può essere necessaria un'operazione di questo tipo è quanto si hanno parti dell'applicazione che sono molto critiche in termini di performance. E' importante sottolineare che utilizzando questo meccanismo la portabilità della propria applicazione diventa molto più difficile da gestire quindi, se possibile, è bene evitare di utilizzare questa caratteristica offerta dal CLR.
Sopra il CLR è stato implementato un ricco insieme di funzionalità che fanno parte di quella che viene comunemente chiamata BCL (Base Class Library ).
5. Uno sguardo alla Base Class Library
La BCL del .NET Micro Framework cerca di mantenere il più possibile la compatibilità con la versione completa del framework .NET. Per questo motivo, le funzionalità direttamente ereditate sono accessibili utilizzando gli stessi namespace e le stesse classi disponibili all'interno della versione completa. Per la realizzazione di funzionalità specifiche al .NET Micro Framework sono stati introdotti i nuovi namespace Microsoft.SPOT, Dpws e Ws. Il nome SPOT (Smart Personal Object Technology) è quello di un progetto, risalente all'anno 2001, dal quale è nata la prima implementazione del .NET Micro Framework, a cui era stato dato il nome di TinyCLR.
I namespace ereditati dalla versione completa del .NET Framework sono i seguenti:
- System
- System.Collections
- System.ComponentModel
- System.Diagnostics
- System.Ext
- System.Globalization
- System.IO
- System.IO.Ports
- System.Net
- System.Net.Sockets
- System.Reflection
- System.Resources
- System.Runtime.CompilerServices
- System.Runtime.InteropServices
- System.Runtime.Remoting
- System.Text
- System.Threading
- System.Xml
Rispetto al framework completo, si segnalano le seguenti caratteristiche:
- Sono disponibili tutti i tipi primitivi del framework .NET ad eccezione del tipo decimal
- Le stringhe sono memorizzate internamente nel formato UTF8 per minimizzare lo spazio occupato
- E' presente la classe System.Text.Encoding per convertire stringhe in array di byte e viceversa
- La classe System.Text.StringBuilder non è disponibile
- Non sono presenti le funzionalità di parsing per i numeri e funzioni matematiche sofisticate
- E' possibile utilizzare solamente gli jagged array e non gli array rettangolari
- I generics non sono disponibili all'interno del .NET Micro Framework
- ArrayList è l'unica collection disponibile nel framework
I namespace specifici del .NET Micro Framework sono:
- Microsoft.SPOT
- Microsoft.SPOT.Cryptography
- Microsoft.SPOT.Hardware
- Microsoft.SPOT.Ink
- Microsoft.SPOT.Input
- Microsoft.SPOT.IO
- Microsoft.SPOT.Messaging
- Microsoft.SPOT.Net
- Microsoft.SPOT.Net.NetworkInformation
- Microsoft.SPOT.Net.Security
- Microsoft.SPOT.Presentation
- Microsoft.SPOT.Presentation.Controls
- Microsoft.SPOT.Presentation.Media
- Microsoft.SPOT.Presentation.Shapes
- Microsoft.SPOT.Touch
Le classi Microsoft.SPOT.Dubug e Microsoft.SPOT.Trace sono particolarmente importanti per effettuare operazioni di debugging e tracing del codice. La classe Microsoft.SPOT.Hardware.Utility fornisce un insieme di funzionalità utili per lo sviluppo delle proprie applicazioni come impostare la data di sistema e la Time Zone o combinare insieme due array. La classe Microsoft.SPOT.ExtendedTimer fornisce altre funzionalità di timing come la possibilità di avviare un timer a una specifica data.
Per quanto riguarda l'interazione con l'hardware, sono importanti le classi contenute nel namespace Microsoft.SPOT.Hardware. In particolare, le classi OutputPort, InputPort, InterruptPort e TristatePort permettono di gestire in modo estremamente semplice i pin di I/O digitale offrendo un consistente modello a eventi. E' interessante la possibilità di inserire un filtro antiglitch in modo da evitare il rilevamento di transizioni spurie sui piedini in ingresso. Con le classi SerialPort, I2Cdevice ed SPI è possibile facilmente gestire l'interazione con un componente hardware che comunica rispettivamente tramite porta seriale, bus I2C o bus SPI al fine di costruire una opportuna classe (managed driver) che astrae l'interfacciamento al componente stesso e ne semplifica l'utilizzo.
All'interno del namespace Microsoft.SPOT.Hardware è inoltre presente la classe Battery per interrogare lo stato della batteria, la classe Cpu per ottenere informazioni relative alla velocità di elaborazione e la classe SystemInfo.SystemID per conoscere i codici identificativi del dispositivo hardware su cui l'applicazione viene fatta girare.
Il namespace Microsoft.SPOT.Net e System.Net con l'implementazione della classe Socket aprono il mondo del networking al .NET Micro Framework. Con la classe Microsoft.SPOT.Net.NetworkInformation.NetworkInterface è possibile ottenere informazioni sulle interfacce di rete disponibili, programmarle con un indirizzo di rete statico o attivare l'acquisizione dinamica dell'indirizzo tramite il protocollo DHCP. Con la classe System.Net.Dns, se è stata stabilita una connessione, è possibile facilmente risolvere un nome di dominio in un indirizzo IP.
Ricordiamo anche il DPWS (Device Profile for Web Services), che consiste in un sottoinsieme delle specifiche dei Web Services con l'aggiunta di un meccanismo di ricerca dei dispositivi. Grazie a questa infrastruttura è possibile collegare in rete tanti dispositivi (o nodi), ciascuno dei quali offrirà diversi servizi agli altri. Il campo in cui questa tecnologia potrebbe essere applicata con interesse sono le reti di sensori wirelesss.
Le funzionalità del DPWS sono contenute all'interno dei vari namespace Dpws e Ws:
- Dpws.Client
- Dpws.Client.Discovery
- Dpws.Client.Eventing
- Dpws.Client.Transport
- Dpws.Device
- Dpws.Device.Services
- Ws.ServiceModel
- Ws.Services
- Ws.Services.Faults
- Ws.Services.Mtom
- Ws.Services.Serialization
- Ws.Services.Soap
- Ws.Services.Transport
- Ws.Services.Transport.HTTP
- Ws.Services.Transport.UDP
- Ws.Services.Utilities
- Ws.Services.WsaAddressing
- Ws.Services.Xml
Per gestire le questioni legate alla sicurezza il .NET Micro Framework fornisce l'implementazione del protocollo di cifratura simmetrica XTEA (Extended Tiny Encryption Algorithm) e l'implementazione del famoso protocollo a chiave pubblica e privata RSA tramite le classi Microsoft.SPOT.Cryptography.Key_TinyEncryptionAlgorithm e Microsoft.SPOT.Key_RSA.
Tramite la classe Microsoft.SPOT.ExecutionContraint è possibile monitorare se una certa operazione viene eseguita all'interno di una prefissata quantità di tempo al termine della quale viene sollevata una eccezione.
Estremamente importante è la capacità offerta dal .NET Micro Framework per la serializzazione binaria degli oggetti, utile per trasferire informazioni con il mondo esterno o persisterle su dispositivi di memoria non volatile. Tramite la classe Microsoft.SPOT.Reflection è possibile effettuare le operazioni di serializzazione e deserializzazione. Utilizzando opportuni attributi inoltre è possibile alterare il comportamento dell'algoritmo di serializzazione in modo da ridurre al massimo lo spazio occupato dallo stream binario generato. Un valido supporto alla memorizzazione di dati in modo permanente sulla memoria flash e il loro recupero dopo il riavvio del dispositivo è offerto da quelli che sono chiamati ExtendedWeakReference.
Per quanto riguarda l'interazione con il display e quindi la realizzazione dell'interfaccia grafica della propria applicazione è possibile utilizzare la classe Microsoft.SPOT.Bitmap per disegnare figure geometriche, immagini e testo in differenti colori. Per realizzare qualcosa di più sofisticato è possibile utilizzare le classi presenti all'interno del namespace Microsoft.SPOT.Presentation che rappresentano un piccolissimo sottoinsieme delle funzionalità offerte da WPF. Non è disponibile il linguaggio XAML (eXtensible Application Markup Language) e gli unici pannelli utilizzabili sono Canvas e StackPanel. I controlli a disposizione sono Border, ListBox, ListBoxItem, ScrollViewer, Window, Image, Text e TextFlow. Infine sono presenti le classiche figure geometriche rappresentate dalle classi Ellipse, Line, Polygon e Rectangle.
A partire dalla versione 3.0 del framework inoltre è presente il namespace Microsft.SPOT.Touch che fornisce i tipi necessari alla gestione di uno schermo sensibile al tocco.
E' molto importante sottolineare la possibilità di gestire in modo strongly-typed le risorse (grazie a Visual Studio che genera la classe Resources) e la possibilità di gestire la globalizzazione e la localizzazione della propria applicazione in modo da realizzare prodotti per il mercato mondiale. A questo scopo si devono realizzare opportuni assembly satelliti e utilizzare la classe System.Globalization.CultureInfo.
Per concludere è fondamentale ricordare che la maggior parte delle classi fornite con il .NET Micro Framework possono essere estese per ottenere funzionalità che altrimenti non sarebbero disponibili.
6. Come iniziare a sviluppare con il .NET Micro Framework
Per sviluppare applicazioni con il .NET Micro Framework versione 2 o 2.5:
Per sviluppare applicazioni con il .NET Micro Framework versione 3.0:
E' importante evidenziare che l'intero SDK del .NET Micro Framework è rilasciato gratuitamente da Microsoft quindi utilizzando la versione Express di Visual C# 2008 è possibile realizzare qualsiasi applicazione senza alcun costo. L'unica spesa inevitabile rimane l'acquisto di una scheda di valutazione (evaluation board) tramite la quale è possibile eseguire e testare la propria applicazione direttamente sull'hardware.
Esistono diversi kit di sviluppo ciascuno dei quali fornisce una evaluation board che supporta in modo più o meno completo una o più versioni del .NET Micro Framework. Per maggiori informazioni consultare nel sito ufficiale del .NET Micro Framework la pagina "Get Hardware" che viene costantemente aggiornata in base alle nuove piattaforme su cui viene fatto il porting.
7. Risorse utili per ottenere maggiori informazioni
Ecco alcune risorse per ottenere informazioni in generale sullo sviluppo di sistemi embedded con tecnologia Microsoft:
Per ottenere maggiori informazioni sul .NET Micro Framework e il suo utilizzo consultare le seguenti pagine:
I libri sul .NET Micro Framework attualmente disponibili all'acquisto sono: