Utilizzare Microblaze con la tecnologia VoIP è, di certo, una scelta non proprio facile perché richiede un intervento diretto sulle librerie dell’ambiente di sviluppo al fine di realizzare una configurazione in grado di garantirne il supporto.
Al giorno d’oggi la tecnologia offre maggiori spazi di manovra e, a mano a mano che si acquisisce maggiore maturità, assume sempre più posizioni di prevalenza all’interno del nostro ambiente di vita e di lavoro. La recente diffusione di sistemi di sviluppo o di librerie open source non fa altro che incrementare soluzioni alternative e di maggiore impatto economico. Non solo, anche lo sviluppo di sistemi con microprocessori embedded all‘interno di un chip quali un FPGA possono offrire soluzioni interessanti, perché permettono di ottenere un design di tipo ibrido allo scopo di offrire una maggiore velocità di elaborazione e versatilità da un punto di vista software.
La crescita di soluzioni di tipo VoIP (Voice over IP) su diversi standard di telecomunicazione assicura la realizzazione di sistemi più completi e integrati anche utilizzando un processore di tipo Soft IP come il Microblaze. Per VoIP (Voice Over Internet Protocol o Voce Tramite Protocollo Internet) si intende una tecnologia capace di convertire il segnale vocale in un segnale digitale, trasferendo l’informazione, compresso in pacchetti, sulla rete dati utilizzando un protocollo internet. A questo scopo l’informazione, composta da componenti video e audio, subisce un processo di conversione. Le regole che sovrintendono al funzionamento della tecnologia VoIP, di per sé non sono complicate: basta avere un programma adatto, un paio di cuffie e un microfono o, nel caso si volesse compiere chiamate da un apparecchio telefonico, basterà collegare il modem (o anche al router ADSL) e il normale telefono. Alla base di una tecnologia di questo tipo, hanno un ruolo ben definito il protocollo base del tipo TCP/IP, il mezzo trasmissivo della rete, e il convertitore di formato, da analogico a digitale e viceversa, che permette di trasformare il nostro contenuto informativo in uno stream di dati più facile da trattare. Quando parliamo di telefonia, a volte, indirettamente, ci riferiamo anche ad Asterisk. In effetti, con Asterisk è possibile configurare un PBX, o Private Branch Exchange, ossia una centrale telefonica, impostando percorsi o parametri di funzionamento: Asterisk, poi, è una libreria software libera utilizzata in diversi ambienti operativi. In questo articolo vogliamo mettere in evidenza in che modo sia possibile sfruttare il microprocessore Microblaze di Xilinx in questo particolare contesto, in una configurazione del tutto particolare. In effetti, tenteremo di descrivere le diverse strade per realizzare un client VoIP per Microblaze in grado di comunicare con un server o altri client della rete IP. Le possibilità sono diverse. È possibile realizzare il tutto, ad esempio, sfruttando PetaLinux di PetaLogix e portare su questo una libreria VoIP Linux compatibile o, ancora, pensare di inserirvi uCAsterix, un porting originariamente previsto per le soluzioni blackfin ma che nessuno ci vieta anche di sfruttarlo, appositamente modificato, per Microblaze. In realtà, la nostra scelta è diversa. Possiamo pensare di utilizzare il softcore di Xilinx basato su Microblaze, ma sfruttando una diversa libreria di rete in grado di supportare il protocollo SIP allo scopo di gestire tutte le transizioni di rete: pensiamo a PJSIP o, in alternativa, Yate con RTOS FreeRTOS e solo in seguito si può pensare di portare anche Asterisk per la gestione della linea.
Microblaze
I dispositivi FPGA (Field Programmable Gate Array) sono dispositivi digitali la cui funzionalità può essere programmabile via software: in realtà, in questo particolare contesto, non parliamo della classica programmabilità di un processore, ma dalla possibilità di configurare in altro modo le risorse logiche disponibili a livello di circuito, al fine di ottenere un nuovo modulo funzionale con una semplice interconnessione delle porte logiche esistenti. Un modulo IP (Intellectual Property Module) è un blocco circuitale parzialmente o completamente pre-progettato e disponibile per essere inserito in un progetto più complesso. Nel panorama commerciale esistono due diverse soluzioni IP classificate come Hard IP o Soft IP. Un SoC è in sostanza un dispositivo FPGA in cui è stato inserito un core, a volte in accordo con uno specifico contratto IP, con la funzionalità di un processore in grado di gestire diverse periferiche: i processori classificati come soft-processor sono sintetizzabili sulle celle presenti su tutte le FPGA, opportunamente programmate e collegate tra loro, riuscendo ad offrire una soluzione molto comoda e portabile. MicroBlaze è un soft-processor prodotto da Xilinx e ottimizzato per le FPGA della medesima casa produttrice. Microblaze è stato definito in accordo ad un’architettura di tipo Harvard con 32 bit di indirizzi. Il costruttore assicura la presenza del core Microblaze in qualsiasi sistema embedded utilizzando una suite software appositamente realizzata. Un sistema basato su Microblaze, figura 1, comprende un processore Microblaze, una memoria locale on chip, un sistema di bus e periferiche OPB (on chip Peripheral Bus).
Il processore supporta fino a tre interfacce per gli accessi alla memoria: Local Memory Bus (LMB), On-Chip Peripheral Bus (OPB) e Xilinx Cache Link (XCL). Il Microblaze rientra tra i processori di tipo RISC a 32 bit le cui caratteristiche principali comprendono un set d’istruzioni ortogonale, la presenza di 32 registri general purpose, architettura di memoria di tipo Harvard con la separazione tra memoria dati ed istruzioni, un bus indirizzi a 32 bit (spazio d’indirizzamento di 4GB) con un’architettura pipeline a 3 o 5 stadi. In base alle specifiche Xilinx è anche possibile sfruttare una rappresentazione dei dati in formato Big endian con la possibilità di supportare i tipi word (32 bit), half word e byte. Grazie alla presenza della sua descrizione in VHDL, il processore può essere configurato in differenti modi. Tutte le istruzioni del MicroBlaze, che si dividono in aritmetiche, logiche, branch, di load/store e speciali, sono a 32 bit a tre operandi con due modalità di indirizzamento. Il processore dispone di trentadue registri a 32-bit di tipo general purpose, numerati da R0 fino a R31. Il register file è resettato al momento della programmazione ed il valore di reset è 0x00000000. Il gruppo dei registri speciali, il cui numero dipende dalle opzioni di configurazione, dispone del Program counter (PC), registro che contiene l’indirizzo dell’istruzione corrente, e del Machine Status register (MSR), registro contenente i bit di stato, del controllo di errore del processore, che permette ad esempio di abilitare o disabilitare interruzioni ed eccezioni. Il Microblaze è veramente flessibile poiché permette di essere interfacciato con differenti bus. A questo riguardo in MicroBlaze non è prevista la presenza del bus PLB, mentre esiste un’interfaccia che permette al soft processor di comunicare direttamente con il bus OPB. Non solo, è anche possibile utilizzare i bus XCL (Xilinx CacheLink) e FSL (Fast Simplex Link). Il processore dispone fino a tre interfacce per gli accessi alla memoria: Local Memory Bus (LMB), Processor Local Bus (PLB) o On-Chip Peripheral Bus (OPB) e Xilinx Cache Link (XCL) ed il range di indirizzamento della memoria LMB non deve sovrapporsi. Il processore di casa Xilinx offre una latenza di un singolo ciclo di clock per gli accessi alla memoria locale (LMB) e per la lettura della cache, tranne quando è abilitata. La cache del MicroBlaze per le istruzioni e per i dati può essere configurata per usare fino a 4 o 8 word. Al processore Microblaze possono essere collegate una serie di periferiche che forniscono un’ampia gamma di funzioni, tra cui si possono tranquillamente ricordare il Watchdog Timer/Timebase, General purpose Timer/Counters, Interrupt Controller, SRAM Controlller, Flash Memory Controller, ZBT Memory Controlller, BRAM Controller, DDR Controller, SDRAM Controller, UART Lite, General purpose I/O, SPI, I2C, UART 16450/550, Ethernet 10/100 MAC. Per realizzare il progetto è stata utilizzata la suite Xilinx Embedded Development Kit (EDK) che consente di definire la nostra risorsa; in effetti, l’EDK è un programma che permette rapidamente di configurare un microprocessore (Microblaze) e caricarlo su una board (Spartan, Virtex, ecc...). In particolare, intervenendo sulle differenti opzioni, è possibile impostare la velocità del processore, la dimensione della memoria, le sue interfacce con l’esterno e si possono inoltre importare una o più periferiche esterne (descritte in codice VHDL o Verilog) da collegare con il processore attraverso diversi indirizzi.
VoIP
Voice over IP (Voip) è un termine piuttosto generico che serve ad indicare un nuovo sistema di comunicazione non attraverso le linee tradizionali di tipo analogico, ma utilizzando i nuovi sistemi di comunicazione basati sulle reti. In particolare, il VoIP consente, per l’appunto, di trasportare il contenuto informativo, ovvero audio e video, utilizzando l’Internet Protocol IP, anche se, in alternativa, esiste la possibilità di sfruttare anche la tradizionale tecnologia a commutazione di circuito. Per sfruttare questa particolare tecnologia si utilizzano, in pratica, due differenti soluzioni: IAX e SIP. Con il primo, acronimo di Inter-Asterisk eXchange, si intende un protocollo per connettere due server asterisk in modo più efficiente del protocollo SIP, mentre con il secondo, Session Initiation Protocol, si intende un protocollo generico per instaurare, modificare e rilasciare una sessione. Il pacchetto che si trasmette con questa sessione di lavoro può contenere qualsiasi tipo di dati: nella sessione instaurata tra i due client nel caso VoIP viene scambiato un flusso multimediale. Nello specifico, con la tecnologia VoIP si intende l’insieme dei protocolli di comunicazione di strato di tipo applicativo che rendono possibile questo tipo di comunicazione. Gli standard principali per la gestione delle comunicazioni Voip è H.323, definito dall’ITU, e il più diffuso è SIP, definito invece dall’IETF. Esistono poi tutta una serie di protocolli proprietari che utilizzano una rete di tipo peer-to-peer. Il protocollo SIP (Session Initiation Protocol) è un protocollo di controllo a livello applicativo per creare, modificare e terminare sessioni multimediali tra due o più partecipanti ed è stato accettato come standard dalla IETF nel marzo del 1999. Le applicazioni più comuni di questo protocollo sono rappresentate dalla telefonia su IP, lo streaming audio-video, le conferenze e la messaggistica istantanea. SIP è un protocollo orientato allo scambio di messaggi e al Web, con una struttura simile ad HTTP/1.1 che gli permette di utilizzare paradigmi di tipo “Client-Server” con l’instaurazione di comunicazioni di tipo Punto-Punto. Il protocollo SIP è strutturato a strati, consentendo una descrizione dei comportamenti dei singoli strati in termini di un insieme di processi semplici ed indipendenti, limitando lo studio sull’interazione tra livelli adiacenti. Non è necessario che gli elementi specificati dal protocollo contengano tutti gli strati definiti. Inoltre spesso tali strati sono soltanto logici e non fisici. Il protocollo SIP non definisce tutte le funzioni richieste per stabilire una sessione interattiva multimediale, per questa ragione agenti ed applicazioni SIP richiedono la presenza di altri protocolli per svolgere diverse operazioni. Ad esempio, occorre utilizzare un’applicazione specifica che descriva le caratteristiche di una sessione o che si impegni a gestire i contenti multimediali. In effetti, in ambito SIP trova spazio l’RTP, o real-time Transport Protocol, che permette di trasmettere dati in tempo reale tra terminali endpoint coinvolti in una sessione. Il protocollo RTCP (Real-time Transport Control Protocol), definito nella RFC 3550, specifica operazioni di monitoraggio e di reporting al mittente dei livelli di QoS relativi al corrispondente stream RTP. I messaggi in ambito SIP si dividono principalmente in richieste (Request) da client a server, e risposte (Response) da server a client.
VoIP per Microblaze
Per realizzare la nostra applicazione, si è pensato di fare il porting di una libreria VoIP open source. Dopo un’attenta analisi di diversi ambienti, inclusi Yate, PJSIP e LibSRTP, la nostra scelta si è rivolta a PJSIP. In effetti, la libreria in questione assicura, in effetti, diverse interessanti caratteristiche:
- portabilità: 32 e 64 bit, in versione big/little endian e su qualsiasi sistema operativo;
- documentazione: la suite software è in grado di offrire una enorme quantità di documentazione spaziando su qualsiasi argomento: dalla conduzione di una sessione di porting fino all’attenta annotazione sul codice sorgente;
- open source: tutto il codice è disponibile pubblicamente per ogni eventuale controllo;
- prestazione: la libreria offre centinaia di interfacce con un buon rapporto prestazionale;
- scalabilità e PJSIP: risulta estremamente scalabile per applicazioni di ogni tipo, da desktop fino a piccoli sistemi embedded.
Al contrario, Yate, definito dai suoi ideatori come il “next-generation telephony engine” (motore telefonico di nuova generazione), riesce a mettere in comunicazione i due protocolli H323 e SIP, gestendo e convertendo esclusivamente gli stack di segnalazione. Il software Voip Yate, inoltre, può perfino agire da Server Jingle (un protocollo di instant messaging in rapida ascesa). Infine, la libreria LibSRTP è un’implementazione del protocollo SRTP, Secure Real-time Transport Protocol (SRTP), originariamente sviluppato da Cisco Systems, Inc. ed è ora disponibile con la licenza BSD-style license. Per la nostra realizzazione, al momento, non prevediamo la possibilità di gestire il codec Audio, Codec AC97, eventualmente interfacciato sul bus OPB: il controller AC97 configura il codec ed estrae i dati audio. Nella prima versione della nostra realizzazione ipotizziamo di trattare comunicazioni da un telefono IP e instradiamo le informazioni relative, figura 2 e 3.
A riguardo, utilizziamo la libreria PJSIP per gestire la suite VoIP, anche perchè la libreria pjsip offre una serie di strumenti di sicuro interesse. Ad esempio, è possibile sfruttare un’implementazione dell’RTP ridotto, meno di 1 KB, con una realizzazione che ha curato ogni aspetto, incidendo sulle sue prestazioni. Non solo, la libreria scelta supporta diversi codec, inclusi la famiglia G.711 (PCMA, PCMU), Speex/8000 (narrowband), Speex/16000 (wideband), e Speex/32000 (ultra-wideband) con un bit rate fisso e impostabile. L’insieme dei Codec supportati prevedono anche iLBC in 20 or 30ms mode,GSM, G.722, G.722.1 e G.722.1C, diversi codec forniti da Intel (G.723.1, G.726, G.728, G.729A, AMR e AMRWB), Nokia (AMR, G.729, iLBC e PCMU/PCMA) e la famiglia L16 in versione mono e stereo. Il primo passo affrontato è stata una serie di attività finalizzate al porting verso l’architettura MicroBlaze. Fortunatamente, le librerie presenti PJLIB, PJLIB-UTIL, PJSIP e PJMEDIA sono state realizzate per favorirne la loro portabilità con basso footprint: in sostanza, una suite da poter utilizzare senza problemi in sistemi di tipo embedded. Come primo passo è necessario prestare particolare attenzione alla definizione dei tipi. Fortunatamente la libreria PJLIB ci viene incontro; in effetti, PJLIB incapsula tutti i tipi di dati integrali in un corrispondente pj_* data type in <pjtypes.h>. Al momento, allo scopo di ridurre la complessità del lavoro, si è preferito disabilitare il meccanismo di Threading. In effetti, disabilitando il Threading si è potuto evitare di implementare codice presente in pj/os_*. Questo non vuol dire, in realtà, evitare di utilizzare meccanismi di multithreading, ma piuttosto si utilizza una politica del tipo multitasking cooperativo. Si è cercato anche di realizzare le due chiamate presenti in libreria, LibC, ovvero setjmp() e longjmp(). Entrambe le funzioni setjmp () e longjmp () sono necessarie per far funzionare il framework che gestisce l’eccezione. Il meccanismo di eccezione presente in PJLIB è del tipo try/catch, ovvero lo stesso meccanismo per i programmi C, e viene normalmente utilizzata negli scanner/parser per gestire correttamente errori di sintassi o nel pool di memoria PJLIB per sollevare eccezione in caso di allocazione di memoria non riuscita. Queste routine devono essere implementate in <pj/compat/setjmp.h>. Infine, occorre anche considerare la funzione malloc() utilizzato come allocatore di memorie per PJLIB Memory Pool. In realtà, la routine può essere modificata allo scopo di creare una nuova politica memory pool (simile a pj/pool_policy_malloc.c). Non solo, nella realizzazione si è deciso anche di tenere presente delle politiche di sincronizzazione degli oggetti presenti nella libreria PJLIB. La libreria prevede già al suo interno routine quali semafori, mutex, recursive mutex e read-write mutex. È possibile utilizzare queste funzioni o ricorrere alle funzioni presenti in un RTOS.
Conclusione
Con la prima parte del nostro progetto ci siamo preoccupati di inserire in un’architettura Microblaze un insieme di servizi VoIP; con la seconda parte mostreremo come inserire Asterisk sfruttando la libreria PJLIB appena portata.
In teoria il sistema VOIP è una ulteriore digitalizzazione del nostro mondo analogico, ma tutte le volte che abbiamo provato ad utilizzare i servizi VoIP a distanza, ci siamo scontrati con la larghezza di banda, con la qualità del servizio (interruzioni, brevi ‘buchi’ di segnale, voce metallica o robotica), ecc. E’ inevitabile che una teoria così affascinante poi si deve affidare ad un trasporto che non sempre è quello teorico. L’unica possibilità che vedo per comunicazioni affidabili è quella di richiedere una banda minima garantita al fornitore di connettività…. Detto questo però, bisogna ammettere che oggi la situazione è nettamente migliorata rispetto a qualche anno fa.
Mi ricorderò sempre un esperimento riuscito 5 anni fa allo SMAU di Padova quando si è svolto un concerto con strumenti a fiato e voce a Padova e batteria e piano a Vicenza (40 km circa), con collegamento IP in fibra e con ponte radio con latenza inferiore a 4 ms, video e suono!