Applicazioni USB con PIC18Fx455/x550

Lo sviluppo di sistemi embedded basati sul protocollo di comunicazione USB sono sempre più diffusi e tendono a soppiantare altri tipi di comunicazioni come quella seriale. A differenza di quest’ultima, la trasmissione dati tramite l’Universal Serial Bus può essere abbastanza difficoltosa per il progettista che voglia sviluppare da zero l’intero protocollo. Le specifiche USB 2.0 sono, infatti, un documento di oltre 650 pagine. Fortunatamente molti produttori di microcontrollori hanno cercato di facilitare il lavoro del progettista, realizzando dispositivi che gestiscono interamente il protocollo USB, rendendolo molto semplice ed intuitivo nell’uso, come fosse una semplice interfaccia seriale. Un modo per mantenere la compatibilità con i vecchi sistemi è quello di emulare la seriale su USB. Si cercherà di comprendere come realizzare ciò senza bisogno di entrare nel dettaglio dello standard USB. Nel presente articolo si analizzeranno in dettaglio i micro della Microchip PIC18F2455/2550/4455/4550.

INTRODUZIONE AL PROTOCOLLO USB

I micro della Microchip PIC18F2455/2550/4455/4550 sono dotati di controller USB compatibile con lo standard 2.0. Supportano le velocità Low Speed (1.5Mbits/s) e Full Speed (12Mbits/s); implementano tutti i tipi di trasferimento previsti dalla specifica (Control, Interrupt, Isocrono e Bulk) e supportano fino a 32 endpoint, di cui 16 bidirezionali. Si cercherà ora di focalizzare l’attenzione su alcuni concetti base del protocollo USB, per essere poi pronti ad affrontare un esempio applicativo con i PIC sopra descritti. In particolare, si mostrerà come emulare una porta seriale utilizzando una connessione USB di un PC. Questo è un problema che si presenta spesso con i moderni computer che ormai non sono dotati di porta seriale, mentre molte applicazioni embedded comunicano con il PC proprio con tale interfaccia. L’emulazione RS-232 è un buon compromesso, poiché non richiede la modifica dell’applicazione software implementata sul PC; quest’ultima, infatti, continuerà a credere di utilizzare un COM anziché una porta USB.

USB overview

Il bus USB è di tipo host controlled. Ci può essere soltanto un host per ogni bus. La specifica non prevede nessuna forma di sistema multimaster, anche se con l’USB OTG (On-The-Go) sembrerebbe che tale regola sia violata. Il protocollo HNP (Host Negotiation Protocol), infatti, consente a due dispositivi di negoziare per il ruolo di host; in ogni caso, al termine di tale processo, il dispositivo host è sempre uno e uno solo. L’host si occupa di stabilire tutte le transazioni e di ripartire la banda tra i vari dispositivi. I dati possono essere inviati mediante differenti metodi, usando un protocollo token-based. Come il nome stesso suggerisce, l’USB è un bus seriale. Esso utilizza 4 cavi schermati di cui 2 per l’alimentazione (+5V e GND). I rimanenti due costituiscono una coppia intrecciata per ottenere un segnale differenziale. La Figura 1 riporta un’immagine del cavo, dei colori standard e della schermatura, mentre la tabella 1 elenca le corrispondenze cavi/colore.

Figura 1. Schema del cavo USB

Figura 1. Schema del cavo USB

Tabella 2. Corrispondenze cavi/colori

Tabella 1. Corrispondenze cavi/colori

Lo schema di codifica utilizzato è la NRZI (Non Return to Zero Invert) e per la sincronizzazione dei clock del ricevitore e del trasmettitore si usa un segnale di sincronismo in testa al pacchetto trasmesso. Una delle caratteristiche di successo dell’USB è di essere plug&play, con caricamento dinamico dei driver. L’host rileva l’inserimento del dispositivo USB e lo interroga per sapere quale driver caricare. La capacità dell’host di decidere il driver corretto è possibile grazie alla combinazione di PID (Product ID) e VID (Vendor ID). Il VID è fornito dall’USB Implementor’s forum dietro compenso. Altre organizzazioni forniscono un extra VID per attività non commerciali come insegnamento, ricerca o per hobbisti in forma gratuita. Questa è anche la soluzione adottata da Microchip che fornisce una serie di VID/PID utilizzabili.

Connettori

Tutti i dispositivi hanno una connessione di upstream per dialogare con l’host e tutti gli host hanno una connessione di downstream per interfacciarsi con i dispositivi. Ovviamente, onde evitare errori di connessione, i due connettori (upstream e downstream) non sono intercambiabili. Per esempio, la specifica USB 1.1 introduce due tipi di connettori (in figura 2 sono riportati sia le prese che i plug):

  1. Tipo A
  2. Tipo B
Figura 2. Connettori USB di tipo A e B

Figura 2. Connettori USB di tipo A e B

Con lo standard 2.0 si è introdotto il connettore mini B (figura 3).

Figura 3. Connettori mini B

Figura 3. Connettori mini B

Il motivo di questo cambiamento è da imputare soprattutto alla necessità di integrazione dei dispositivi elettronici (come cellulari o lettori MP3). Gli ultimi standard hanno introdotto cavi USB Type C con aggiornamenti vari in termini di velocità dati e larghezza di banda.

Caratteristiche elettriche

USB utilizza un coppia differenziale per la trasmissione dei dati (D- e D+). Nel caso di USB 1.1, un livello logico 1 è trasmesso quando D+ è portato alla tensione di 2.8V mediante un resistore di pull-down il cui valore è 15ko e D- ad una tensione di 0.3V con un resistore di pull-up il cui valore è 1.5k. Il ricevitore capirà di ricevere 1 se D+ è superiore rispetto a D- di 200mV, mentre interpreterà 0 se D+ è inferiore di 200mV rispetto a D. Un transceiver USB deve essere in grado di generare oltre che segnali differenziali anche segnali single ended, in corrispondenza di certi stati del bus. Ad esempio, uno stato logico 0 di tipo single ended (SE0) può essere utilizzato per indicare il reset del dispositivo se tenuto per più di 10ms. Lo stato SE0 è ottenuto mantenendo sia D- che D+ al livello basso (<0.3V). Come ricordato in precedenza i PIC18F2455/2550/4455/4550 implementano internamente un transceiver che rispetta tali specifiche. L’indicazione della velocità del dispositivo è effettuata alla connessione, portando al livello alto entrambe le linee dati. Un dispositivo Full Speed utilizza un resistore di pull-up sulla linea D+, come mostrato in figura 4.

Figura 4. Identificazione dispositivo Full Speed

Figura 4. Identificazione dispositivo Full Speed

Tale resistore viene anche usato dall’host per rilevare la presenza di un dispositivo connesso alla sua porta. Senza tale resistenza l’host considera che nessun dispositivo è collegato. Spesso tale componente è realizzato on-chip sul dispositivo, mentre in altri casi è necessario aggiungerlo esternamente. Nel caso dei PIC è possibile scegliere se utilizzare i resistori interni oppure quelli esterni. I chip sono inoltre dotati di un regolatore con uscita a 3.3V, che consente di alimentare il chip con una tensione singola a 5V. Nel caso di dispositivo Low Speed si utilizza la stessa tecnica, ma con il resistore sulla linea D-, come illustrato in figura 5.

Figura 5. Identificazione dispositivo Low Speed

Figura 5. Identificazione dispositivo Low Speed

Il discorso è leggermente diverso per i dispositivi High Speed. Inizialmente la connessione viene eseguita come un Full Speed (1.5Ko a 3.3V). In seguito, durante la fase di reset, il dispositivo invierà all’host una sequenza per segnalare la velocità di 480Mbits/s. Un’altra caratteristica importante dello standard USB è la possibilità di trasportare l’alimentazione sul bus. Da questo punto di vista si distinguono due differenti classi di dispositivi:

  1. Bus-power. Prelevano l’alimentazione dal bus.
  2. Self-power. Prelevano l’alimentazione da una sorgente esterna.

Ovviamente, per la prima categoria è specificato un limite alla potenza assorbita dal bus. A ciascun dispositivo sono assicurati 100mA@5V (quindi una potenza di 500mW). Una potenza addizionale può essere richiesta fino ad un massimo di 500mA. La specifica USB definisce anche una modalità di sospensione (Suspend Mode). In tale condizione la corrente massima non deve superare i 500µA. Un dispositivo entra in suspend mode se rimane inattivo per oltre 3ms.

Figura 6. Resistenze di pull-up interne ed esterne nei PIC

Figura 6. Resistenze di pull-up interne ed esterne nei PIC

Enumerazione e protocollo

Quando il dispositivo è collegato al bus, l’host avvia un processo di enumerazione allo scopo di identificarlo. In pratica, l’host interroga il dispositivo, raccoglie informazioni utili come consumo di potenza, velocità e protocollo utilizzato. La figura 7 riporta le varie fasi che costituiscono tale processo.

Figura 7. Diagramma di flusso del processo di enumerazione

Figura 7. Diagramma di flusso del processo di enumerazione

Il protocollo USB è basato su particolari pacchetti costituiti dai seguenti campi (i vari tipi di pacchetti sono riportati in Figura 8):

  • Sync. Tutti i pacchetti devono iniziare con questo campo. È formato da 8bit e serve per la sincronizzazione del ricevitore con il trasmettitore.
  • PID (Packet IDentification). Serve per identificare il tipo di pacchetto che si deve trasmettere. La tabella 2 elenca tutte le possibili combinazioni di questo campo.
  • ADDR. Specifica a quale dispositivo è destinato il pacchetto. È costituito da 7bit e quindi 27 = 127 dispositivi complessivamente possono essere presenti su di un bus USB.
  • ENDP. Questo campo è formato da 4bit e quindi 16 possibili endpoints. I dispositivi low speed sono però dotati solo di massimo 4 endpoints. Gli endpoints possono essere visti come sorgenti/destinazione di dati. Essi sono una sorta di interfaccia tra l’hardware ed il firmware del dispositivo (figura 9).
  • CRC. Serve per garantire l’integrità dei dati.
  • EOP. Indica la fine del pacchetto.
Figura 8. Formato del pacchetto USB

Figura 8. Formato del pacchetto USB

Tabella 3. Campo PID per l’identificazione dei pacchetti

Tabella 2. Campo PID per l’identificazione dei pacchetti

Un altro aspetto interessante del protocollo sono le modalità di trasmissione. La specifica ne riporta 4 complessivamente:

  • Isocrona. Utile soprattutto per trasmettere grandi quantità di dati (video e audio), senza però nessuna garanzia sull’integrità dei dati.
  • Bulk. Simile alla prima, ma garantisce l’integrità.
  • Interrupt. È destinata alla trasmissione di ridotte quantità di dati, in cui però è essenziale garantire che i dati non siano corrotti.
  • Control. Utilizzata per il setup del dispositivo.

È importante sottolineare che i dispositivi low speed sono dotati solo delle ultime due modalità di trasferimento. Utilizzare i PIC18FX455/X550 per applicazioni USB La figura 10 riporta lo schema completo dell’architettura implementata a bordo del PIC18FX455/X550.

Figura 9. Schematizzazione degli endpoints

Figura 9. Schematizzazione degli endpoints

Figura 10. Schema completo della sezione USB

Figura 10. Schema completo della sezione USB

Si può subito notare la presenta del regolatore di tensione a 3.3V interno, per consentire di utilizzare i resistori di pull-up on-chip, necessari per il riconoscimento della velocità. I due transistor MOS consentono di abilitare uno dei due resistori, a seconda della velocità desiderata. Il cuore di tutto il sistema è costituito dal SIE (Serial Interface Engine) che consente comunicazioni veloci tra il PIC e l’host. La scelta architetturale usata da Microchip consente di utilizzare sia il transceiver interno che uno esterno. In quest’ultimo caso bisogna utilizzare anche un regolatore a 3.3V e le relative resistenze. Per migliorare le performance è stata inserita una memoria dual port da 1KB (USB RAM) all’interno dell’area dati, come riportato in Figura 11.

Figura 11. USB RAM

Figura 11. USB RAM

Per trasferire grandi quantità di dati può essere utilizzata l’interfaccia SSP (Streaming Serial Port). I registri necessari per la gestione ed il trasferimento con interfaccia USB sono di seguito elencati:

  • USB Control register (UCON).
  • USB ConFiGuration register (UCFG).
  • USB Transfer Status register (USTAT).
  • USB device ADDRess register (UADDR).
  • Frame Number register (UFRMH: UFRML).
  • Endpoint Enable register da 0 a 15 (UEPn).

Per ottimizzare la gestione della porta USB è stata introdotta una struttura logica per gli interrupt USB (figura 12), simile a quella già esistente per gli interrupt del PICMicro.

Figura 12. Logica degli interrupt USB

Figura 12. Logica degli interrupt USB

In particolare, essi si suddividono in due livelli: le interruzioni dovute allo stato e quelle relative agli errori. Tutte le sorgenti di interrupt confluiscono, mediante porte AND e OR, in un’unica linea (USBIF), portata alla CPU. Per il funzionamento dell’hardware relativo all’USB è necessario un clock con frequenza pari a 48MHz.

LA PICDEM FS USB

Per ridurre il time-to-market nello sviluppo di sistemi embedded, Microchip ha reso disponibile tempo fa un demo board: la PICDEM FS USB, di cui è mostrata un’immagine in figura 13.

Figura 13. PICDEM FS USB

Figura 13. PICDEM FS USB

Essa è equipaggiata con il micro PIC18F4550 ed interfaccia USB 2.0 full speed. Le caratteristiche principali di questa EVK sono di seguito elencate:

  • Frequenza di clock massimo 48MHz (12MIPS);
  • 32KB di memoria programma;
  • 2KB di RAM (di cui 1KB USB RAM di tipo dual port);
  • 256bytes di EEPROM dati.

La scheda viene fornita con il bootloader precaricato; questo evita l’uso di un programmatore, poiché il download del firmware può essere eseguito semplicemente da seriale. Inoltre, sono resi disponibili gli schematici della scheda, figura 14, per eventuali sviluppi custom.

 

Figura 14. Schematico della PICDEM FS USB

Figura 14. Schematico della PICDEM FS USB

SIMULAZIONE DELL’INTERFACCIA SERIALE SU USB

Un’applicazione che può essere molto utile con l’interfaccia USB è l’emulazione di una porta seriale. La RS-232 è stata per molto tempo il principale metodo di comunicazione tra un PC ed un sistema embedded, anche grazie alla sua semplicità d’uso. Con l’avvento dei nuovi PC diventa sempre più raro trovare ancora una porta seriale. Una possibile soluzione a questo problema è la migrazione verso USB. Mediante emulazione della seriale su USB il software continua a vedere un connessione RS-232 (quindi non è necessario modificarlo), mentre è necessario modificare leggermente l’hardware del sistema embedded. La figura 15 riporta uno schema della variazione architetturale che comporta il passaggio da RS-232 a USB.

Figura 15. Migrazione da RS-232 a USB

Figura 15. Migrazione da RS-232 a USB

In rosso sono riportate le modifiche che è necessario apportare per adottare questa strada. Per quanto riguarda i driver CDC questi sono forniti con Windows oppure direttamente da Microchip. Per quanto riguarda l’hardware USB lato PICMicro, il problema è anche risolto poiché è sufficiente ricorrere ai modelli dei PIC elencati sopra. Rimane da progettare le funzioni (API) nel firmware del PICMicro per la gestione del protocollo USB. La buona notizia è che tali funzioni sono già stata sviluppate da Microchip (e riportate in tabella 3).

Tabella 4. Lista e descrizione delle funzioni USB/UART

Tabella 3. Lista e descrizione delle funzioni USB/UART

Le funzioni sono scritte utilizzando il compilatore C18 e sono molto simili nel nome e nel funzionamento a quelle utilizzate per controllare la seriale. Si analizzeranno ora nel dettaglio alcune delle funzioni implementate e si cercherà far di comprendere come esse devono essere utilizzate per ottimizzare le prestazioni del firmware.

Invio di dati: la funzione “putrsUSBUSART”

Questa funzione scrive una stringa di dati verso porta USB, includendo il carattere di terminazione stringa (null character). Il dato da trasferire deve essere contenuto nella memoria programma, a differenza della funzione putsUSBUSART in cui il dato deve trovarsi nella RAM. Il prototipo della funzione è:

void putrsUSBUSART (const rom char *data)

dove data rappresenta un puntatore ad un stringa null-terminated.

Di seguito sono riportati due esempi di utilizzo di questa funzione:

void example_1(void){
     if(mUSBUSARTIsTxTrfReady())
     putrsUSBUSART(“Hello World.”);
}   //end example_1

rom char example_string[] = {“Pippo”};
void example_2(void){
      if(mUSBUSARTIsTxTrfReady())
      putrsUSBUSART(example_string);
}  //end example_2

In entrambi gli esempi, oltre alla funzione putrsUSBUSART, è stata utilizzata mUSBUSARTIsTxTrfReady(). Essa restituisce 1 se il controller è pronto a ricevere altri dati. Prima di qualsiasi trasferimento è consigliabile utilizzarla onde evitare problemi di overbuffer dei dati.

Ricezione di dati: la funzione “getUSBUSART”

Questa funzione riceve una stringa dall’host USB e la trasferisce in una determinata locazione della RAM. Si tratta di un funzione cosiddetta “non bloccante” in quanto se non ci sono dati in ingresso non rimane in attesa ma restituisce 0 per segnalare tale condizione. La sintassi è di seguito riportata:

byte getUSBUSART (char *buffer, byte len)

dove buffer è la stringa in cui memorizzare i dati ricevuti, mentre len individua la lunghezza massima della stringa ricevuta. Se vengono ricevuti più byte di quelli indicati da len, allora solo i caratteri attesi saranno copiati nel buffer. Se invece accade di ricevere meno caratteri di quelli attesi, allora solo i caratteri ricevuti saranno inseriti in buffer. Il massimo valore di len deve essere inferiore alla massima dimensione dell’endpoint utilizzato per la ricezione dei dati. Per modificare questo valore bisogna intervenire sulla costante CDC_BULK_OUT_EP_SIZE all’interno del file usbcfg.h. Tale costante può assumere i valori 8,16, 32 oppure 64bytes. La funzione restituisce un valore di tipo byte, ossia il numero di caratteri ricevuti (0 indica che non sono stati ricevuti caratteri). Anche per questa funzione sono riportati due esempi di utilizzo:

char input_buffer[64];
void example_1(void){
    byte index, count, total_sum;
    if(getsUSBUSART(input_buffer, 8)){
      count = mCDCGetRxLength();
      total_sum = 0;
      for(index = 0; index < count;
      index++)
      total_sum += input_buffer[index];
}  //end if
}  //end example_1

void example_2(void){
   if(getsUSBUSART(input_buffer,
   CDC_BULK_OUT_EP_SIZE)){
   // Do something…
   } //end if
}  //end example_2

Nel primo esempio è stata utilizzata un’altra funzione:

mCDCGetRxLength()

Essa ha lo scopo di determinare il numero di caratteri ricevuti con la precedente chiamata della funzione

getsUSBUSART(input_buffer, 8)

Osservazione sulle funzioni bloccanti

Ci sono alcune considerazioni da fare relativamente alla programmazione con le funzione USB/UART, per ottenere il massimo delle prestazioni:

  • Il firmware fornito da Microchip è un ambiente multitasking di tipo cooperativo. Questo significa che non possono esserci funzioni bloccanti nel codice utente, poiché queste causerebbero lo stallo della macchina. In generale, conviene utilizzare una macchina a stati anziché funzioni bloccanti. Un esempio tipico di funzione bloccante è il seguente codice:
    while(!mUSBUSARTIsTxTrfReady());
  • Le funzioni putrsUSBUSART, putsUSBUSART, mUSBUSARTTxRom e mUSBUSARTTxRam sono non bloccanti.

Si riportano ora due esempi di programmazione, rispettivamente incorretta e corretta, con le funzioni di cui sopra:

Esempio di programmazione errata:

if(mUSBUSARTIsTxTrfReady())

{

putrsUSBUSART(“Hello World”);

putrsUSBUSART(“Hello Again”);

}//end if

 

Esempio di programmazione corretta

(macchina a stati): byte state = 0; if(state == 0){

if(mUSBUSARTIsTxTrfReady()){ putrsUSBUSART(“Hello World”); state++;

} //end if

}

else if(state == 1){ if(mUSBUSARTIsTxTrfReady()){ putrsUSBUSART(“Hello Again”); state++;

} //end if

} //end if

Installazione del software e dell’hardware Come descritto in precedenza, un modo veloce per sviluppare le proprie applicazioni è quello di fare uso della PICDEM FS USB. È possibile effettuare il download dal sito Microchip del software di gestione, all’indirizzo: http://ww1.microchip.com/downloads/en/AppNotes/CDC_RS232_Emulation.EXE. Se sono stati utilizzati i parametri di default, il percorso di installazione è C:\MCHPFSUSB\. Se si collega la PICDEM al PC mediante il cavo USB si nota la tipica schermata di quanto viene rilevata una periferica USB e bisogna specificare il percorso del driver (figura 16).

Figura 16. Richiesta del driver CDC RS-232 da parte del S.O

Figura 16. Richiesta del driver CDC RS-232 da parte del S.O

Il nome del driver è mchpcdc.inf e si trova al seguente percorso: C:\MCHPFSUSB\fw\Cdc\inf\win2k_winxp. Dopo aver completato l’installazione del driver si nota, andando nella finestra Gestione Periferiche, che è comparsa un’altra COM (porta seriale virtuale). Il lato PC a questo punto è pronto. Prima di utilizzare il file .inf nei propri progetti è necessario cambiare le impostazioni di default, tra cui VID e PID. È sufficiente aprire il file con un editor di testi (anche blocco note) e ricercare la stringa “USB\VID_xxxx&PIDyyyy” dove “xxxx” è il valore esadecimale del VID e “yyyy” il valore esadecimale del PID; generalmente la stringa è contenuta sotto l’header [DeviceList]. Oltre a queste modifiche è possibile cambiare i parametri riportati sotto l’header [Strings]; quelli riportati di default sono:

  • MCHP=”Microchip Technology Inc.”
  • MFGNAME=”Microchip Technology Inc.”
  • DESCRIPTION=”Communications Port”
  • SERVICE=”USB RS-232 Emulation Driver”

Resta da configurare il lato micro. Per le prime prove è possibile utilizzare il progetto già pronto C:\MCHPFSUSB\fw\Cdc\MCHPUSB.mcp. Esso consiste di diversi files tra cui il già citato usbcfg.h ed il cdc.c che contiene invece tutte le funzioni USB/UART. Per la realizzazione di un progetto custom, invece, è necessario:

  1. Inserire #include “system\usb\usb.h” in ciascun file che utilizza le funzioni in oggetto.
  2. Definire la costante USB_USE_CDC all’interno del file usbcfg.h.
  3. I file cdc.c e cdc.h devono essere aggiunti al progetto. Essi si trovano al percorso: C:\MCHPFSUSB\fw\Cdc\system\usb\class\cdc

CHIP DEDICATI

Per la conversione seriale/USB con USB slave esistono anche chip dedicati che da un lato forniscono una connettività USB, dall’altro rendono disponibile una (o più) porte seriali standard. È il caso del chip MCS7703 prodotto da Moschip Semiconductor di cui si riportano le caratteristiche fondamentali:

  • Alimentazione a 5V con regolatore interno a 3,3V;
  • Certificazione WHQL;
  • Data rates supportati: da 75mbps fino a 3Mbps;
  • USB1.1 compliant;
  • VID e PIC riconfigurabili mediante EEPROM esterna;

La figura 17 mostra lo schema a blocchi ed il pinout del dispositivo.

Figura 17. Schema a blocchi e pinout del convertitore seriale/USB MCS7703

Figura 17. Schema a blocchi e pinout del convertitore seriale/USB MCS7703

Il vantaggio nell’usare un chip del genere risiede principalmente nel fatto che i driver vengono forniti direttamente dal costruttore e l’operazione di conversione avviene in modo del tutto trasparente all’utilizzatore.

FTDI FT232R: una soluzione alternativa

Un’altra possibilità per la conversione USB/seriale è offerta per esempio dal chip della FTDI, FT232R, con alcune caratteristiche:

  1. Tutti i componenti chiave sono stati integrati nel chip (tra cui la EEPROM, il clock configurabile ed altri componenti passivi).
  2. L’identificativo del dispositivo fornito da FTDI è univoco.
  3. Possibilità di ridurre fino al 50% del area riservata al convertitore.
  4. Due differenti package: 28-pin SSOP (FT232RL) and 32-pin QFN (FT232RQ)

La Figura 18 riporta lo schema a blocchi di questo chip. Inoltre, il produttore riporta tutti gli schematici per implementare il convertitore USB/Seriale.

Figura 18. Schema a blocchi dell’FT232R

Figura 18. Schema a blocchi dell’FT232R

 

 

 

Scarica subito una copia gratis

Una risposta

  1. Avatar photo Maurizio 8 Settembre 2016

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend