OpenTCP con FUJITSU

Benvenuti a un nuovo appuntamento con la Rubrica Firmware Reload di Elettronica Open Source. In questa Rubrica del blog EOS abbiamo raccolto gli articoli tecnici della vecchia rivista cartacea Firmware, che contengono argomenti e temi passati ancora di interesse per Professionisti, Makers, Hobbisti e Appassionati di elettronica. Portare uno Stack TCP/IP su un microcontrollore è di per sé un’attività interessante. In questo articolo mostreremo le diverse attività che devono essere considerate per utilizzare OpenTCP su una qualsiasi interfaccia Ethernet.

Introduzione

Oggi esistono diversi stack Ethernet disponibili e utilizzabili per i propri scopi e tra questi OpenTCP è sicuramente uno di quelli che riscuote maggiore credito. Questo stack è stato sviluppato da Viola System ed è anche disponibile su Sourceforge, il repository per eccellenza del software/firmware targato open source. OpenTCP, come ogni altro stack open source, dispone di diversi moduli integrati con la possibilità, in particolare per questo stack, di utilizzare un’applicazione client server già perfettamente disponibile. La pila richiede poche risorse fisiche, cosa particolarmente gradita per sistemi embedded di piccolo taglio; in effetti, in base alle indicazioni di Fuijtsu, OpenTCP utilizza 27 Kb di memoria flash e 7 Kb di ram. Lo stack, poi, garantisce il supporto verso altri protocolli quali ARP, IP, UDP, TCP e ICMP che possono essere utilizzati per costruire applicazioni standard o custom, quali HTTP, TELNET, POP3, SMTP o TFTP richiamabili attraverso il funzionamento dal suo thread principale.

FACCIAMO IL PORTING

La prima cosa che dobbiamo fare è procurarci l’ultima versione, quella corrente è la 1.0.4, dell’OpenTCP stack. Il file compresso include tutto ciò di cui abbiamo bisogno, ossia il codice sorgente con alcune indicazioni di massima per realizzare correttamente il nostro lavoro. È possibile anche recuperare la documentazione tecnica presente, attraverso un file compresso, allo stesso link. La Figura 1 mostra la struttura dell’OpenTCP e, come possiamo notare, è suddivisa su diverse sotto cartelle, dove ognuna identifica una specifica funzionalità.

Figura 1: struttura OpenTCP.

Figura 1: Struttura OpenTCP

Rispetto alla versione di riferimento, in ambito Fuijtsu sono state apportate diverse migliorie; in effetti, possiamo trovare nuovi moduli quale il Telnet Server o il modulo finalizzato alla gestione della memoria Flash o, anche, la possibilità di gestire il driver hardware CS8900. Per offrire queste nuove funzionalità sono state effettuate diverse modifiche: in OpenTCP è possibile gestire un web server con la possibilità di trattare contenuti dinamici o la possibilità di fare il downloading di nuovi file per la presenza di un driver Tftp. Piccola avvertenza: al fine di utilizzare questo stack in una rete ipotetica è necessario configurare alcuni parametri presenti nel codice, quale il valore del MAC address per indirizzare correttamente il chip hardware di rete. Ad ogni modo, nel file help.c, presente nel file compresso, è possibile trovare diverse indicazioni in questo senso, inclusa la possibilità di ottenere valide informazioni sui valori del suo IP Address, subnet mask e default gateway. Non solo, come ricorda la stessa documentazione di riferimento della Fujitsu, al fine di ottenere maggiori prestazioni è anche possibile modificare il numero delle connessioni per il server web, accluso nella distribuzione, attraverso il parametro globale:

NO_OF_HTTP_SESSIONS

contenuto nel file http_server.h. A questo riguardo si osserva, comunque, che se si aumenta il valore massimo del numero delle sessioni http, è necessario anche aumentare il numero delle socket con NO_OF_TCPSOCKETS presente nel file tcp_ip.h: il tutto ha però un costo in termini di occupazione di memoria.

IL PROBLEMA DEL TEMPO

Uno stack di rete ha la necessità di utilizzare un timer per gestire le differenti condizioni temporali che sono presenti in una connessione o in una sessione di rete; in effetti, si ha la necessità, ad esempio, di leggere con una certa frequenza l’eventuale pacchetto arrivato alla porta del componente. Per sopperire a questa particolarità si ha l’esigenza di utilizzare un timer con una risoluzione nell’ordine dei millisecondi. Per questa funzionalità è necessario offrire le seguenti routine che saranno poi utilizzate nella distribuzione al momento della compilazione/linker del prodotto:

clock_time_t clock_time(void) // restituisce
il tempo corrente in millisecondi
void clock_init(void) // inizializza il clock
// in più
__interrupt void RLT0IRQHandler(void)
// ricarica il timer
void delay_ms(unsigned long delay) //
sopperisce alla funzionalità di delay

In questa particolare versione di OpenTCP si utilizza un timer definito come reload, con una frequenza di dieci millisecondi: allo scadere di questo periodo il componente solleva un evento asincrono che sarà gestito dal software e, successivamente, lo stack si preoccuperà di riarmare il timer per l’evento successivo. Non solo, è anche necessario munirsi di una serie di routine, definite talora come low-level functions, che si interfacciano direttamente con lo stack OpenTCP: i differenti pacchetti, ricezione o trasmissione, dovranno utilizzare queste interfacce per passare direttamente sul componente e a questo proposito la Tabella 1 ne mostra la loro consistenza, così come riportato nella documentazione ufficiale.

Tabella 1: High level Ethernet functions.

Tabella 1: High level Ethernet functions

Al contrario, la lista delle funzioni riportata nella Tabella 2 pone in risalto le diverse funzioni di basso livello utilizzate dal nostro stack per interfacciarsi direttamente con il dispositivo Ethernet.

Tabella 2: Low level Ethernet functions.

Tabella 2: Low level Ethernet functions

Si può notare che la funzione init() deve preoccuparsi di inizializzare il nostro componente e sarà, di certo, eseguita al boot del sistema. La procedura d’inizializzazione accederà al componente fisico in modalità I/O e solo successivamente sarà possibile accedere al dispositivo in memory mapped, Figura 2.

Figura 2: fase di boot.

Figura 2: Fase di boot

Grazie a questa possibilità la gestione dei pacchetti di rete è più facile e trasparente. Per ultimo, ma non meno importante, è la necessità di utilizzare un interrupt per ogni pacchetto ricevuto o trasmesso, a seconda della reale necessità. La fase di inizializzazione dovrà preoccuparsi di impostare correttamente il MAC address, operazione fondamentale perché senza un valido indirizzo MAC il componente utilizzato, CS8900A, non potrà funzionare. Il componente CS8900A permette di gestire i pacchetti in ricezione con particolare flessibilità; in effetti, le diverse opzioni di controllo dei pacchetti possono essere effettuate direttamente dal componente liberando il software da un carico eccessivo. Il chip di rete utilizzato dispone di 4 Kbyte SRAM on-chip, un valore sufficiente per quasi tre pacchetti di rete e, in caso di spazio insufficiente, il componente potrà perdere dati in arrivo. Pertanto, così come consiglia il costruttore del chip, per gestire i dati in modo più efficiente è importante copiarli nella RAM del microcontrollore ed elaborare i frame: l’elaborazione non potrà essere effettuata nella routine di gestione dell’interrupt.

La funzione dell’interrupt, o CS8900IRQHandler, conterà solo i diversi RXeventi in arrivo incrementando la variabile globale “ReceivePacket” ogni volta che viene attivato. In questo modo la variabile mostra sempre quanti pacchetti sono in attesa per l’elaborazione all’interno del chip Ethernet. La lettura di ogni pacchetto può essere fatta con il meccanismo del polling sulla variabile “ReceivePacket”. Le diverse risorse hardware della board, e del chip, devono essere correttamente configurate e inizializzate allo start up attraverso la funzione “start.asm” richiamata nel thread principale. Infatti, il modulo “start.asm” dovrà preoccuparsi di inizializzare la seriale, gli interrupt, il timer e il chip Ethernet.

ESEMPIO: TFTP SERVER

Un server ftp è di fondamentale importanza in un sistema embedded perché permette di ricevere e, se dispone anche di una funzionalità di client, di spedire file verso un qualunque computer. Ora, implementare un ftp server può richiedere molto spazio di memoria non sempre disponibile in sistemi embedded ridotti, ecco perché si preferisce mettere a punto un tftp, o trivial ftp. Non solo, tipicamente un ftp, o tftp, può richiedere anche un file system a bordo, in realtà, il problema può essere risolto realizzando un tftp flat. Non solo, con questo protocollo è possibile inviare e ricevere file con una massima dimensione di 32 MB e, a causa della limitazione funzionale, non vi è alcun controllo password per bloccare il trasferimento. Il file, o il dato, deve essere scritto direttamente nella sua memoria flash. Per ricevere un file da un host, ad esempio un PC, è necessario utilizzare un apposito client, Figura 3.

Figura 3: tftp.

Figura 3: Tftp

Se si vuole caricare un file dal target è necessario utilizzare il comando GET, Figura 4, con l’opzione –i perché i pacchetti sono byte oriented, in questo modo:

tftp –i ipaddr GET samplefile.bin samplefile. bin

Al contrario, per inviare un file sulla scheda è necessario, per prima cosa, determinare lo spazio disponibile su target, e utilizzare il comando PUT, Figura 5, con il seguente comando sul PC:

tftp –i ipaddr PUT samplefile.bin myupload. bin

anche in questo caso sarà visualizzata sul nostro terminale la scritta “Transfer successful” come conferma del successo dell’operazione svolta.

Figura 4: il comando GET tftp.

Figura 4: Il comando GET tftp

 

Figura 5: il comando PUT tftp.

Figura 5: Il comando PUT tftp

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend