Corso PIC-USB

106

description

Corso su i microprocessori serie PIC , interfaccia USB.

Transcript of Corso PIC-USB

Page 1: Corso PIC-USB
Page 2: Corso PIC-USB

uesto Corso si prefigge di spiegare lemodalità di programmazione delle funzio-

nalità USB incorporate nei microprocessori dellafamiglia PIC16C745/765 di Microchip. Le pun-tate sono state organizzate in maniera tale daoffrire un panorama completo sull'argomentopartendo dai rudimenti teorici dell'architetturaUSB fino ad arrivare allo sviluppo completo delfirmware e del software necessario a far comuni-care un computer con un dispositivo basato sutale microprocessore. Lo sviluppo verrà presen-tato attraverso l'utilizzo di un linguaggio moltosemplice come il BASIC ma non mancherannole porzioni di codice assembler e le spiegazionisu firmware già prodotto dalla casa madre. Perquanto riguarda lo sviluppo lato PC verrannopresentate delle soluzioni basate su Delphi maanche in questo caso ci saranno dei riferimentianalitici che permetteranno l'utilizzo di un qual-siasi ambiente orientato agli oggetti. Il percorsosi alternerà tra esempi di programmazione e rife-rimenti di utilizzo pratico, attraverso la realizza-zione di una serie di esperimenti che permette-

ranno di mettere in pratica le nozioni apprese.Per mettere in condizione tutti di realizzare gliesempi proposti si farà riferimento all’interfacciaUSB presentata sui numeri 90 e 91 (disponibilesia in kit col codice K8055 che già montata e col-laudata col codice VM110). Dopo questa brevepremessa, non ci resta che iniziare affrontandogli aspetti teorici e le definizioni che sarannoindispensabili per comprendere gli argomentiaffrontati nel prosieguo.

USB, motivazioni e caratteristiche

L'architettura USB (Universal Serial Bus) nascecome standard industriale riconosciuto alla finedel 1998 quando Compaq, Intel, Microsoft eNEC presentano le specifiche nella versione 1.1.L'idea alla base di tutto è stata quella di realizza-re un sistema di interconnessione con le periferi-che che fosse semplice da utilizzare, veloce, eco-nomico, che permettesse di collegare più dispo-sitivi su una medesima porta e che tale collega-mento supportasse una riconfigurazione dinami-

Elettronica In - ottobre 2004 81

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

1AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittààUUSSBB iimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorrii ddeellllaa MMiiccrroocchhiipp..UUnn aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittààiinn ccoonnssiiddeerraazziioonnee ddeellllaa ccrreesscceenntteeiimmppoorrttaannzzaa ddii qquueessttaa aarrcchhiitteettttuurraa nneellllaaccoommuunniiccaazziioonnee ttrraa ccoommppuutteerr eeddiissppoossiittiivvii eesstteerrnnii.. IInn qquueessttaa pprriimmaappuunnttaattaa ccii ooccccuuppiiaammoo ddeeggllii aassppeettttiitteeoorriiccii ddeellll’’UUSSBB,, pprreemmeessssaaffoonnddaammeennttaallee ppeerr aaffffrroonnttaarreelloo ssttuuddiioo ddeell ffiirrmmwwaarree..

a cura di Carlo Tauraso

Page 3: Corso PIC-USB

82 ottobre 2004 - Elettronica In

>

ca permettendo la connessione e disconnessionedei dispositivi senza particolari interventi. Ilsistema prevede inizialmente due modalità di tra-smissione: low-speed (1,5 Mbps) e full-speed(12 Mbps). Nel 2000 vengono presentate le spe-cifiche 2.0 che integrano le precedenti aggiun-gendo una terza modalità high-speed che rag-giunge i 480 Mbps (Megabit al secondo). Noi cioccuperemo principalmente della versione 1.1 inquanto attualmente la famiglia PIC16C745/765di Microchip permette di utilizzare esclusiva-mente la modalità low-speed, inoltre buona partedei PC installati sono equipaggiati con una portaconforme a tali specifiche ed i driver sviluppati

per i vari sistemi Microsoft hanno raggiuntoormai un buon grado di affidabilità. C'è da preci-sare comunque che Hub e porte certificati USB2.0 sono pienamente compatibili verso il bassotant'è vero che se devono comunicare con un dis-positivo precedente eseguono una risincronizza-zione della trasmissione, e tramite buffer riduco-no la velocità a 1,5 o 12 Mbps. In questo mododispositivi USB 1.1 possono convivere con siste-mi di nuova generazione senza dover subire alcu-na modifica. Ciò varrà, naturalmente, anche per iprototipi che andremo a realizzare. L'architetturaUSB gestisce collegamenti multipli di periferi-che ed in cascata fino ad un massimo di 127 dis-

CCoorrssoo PPIICC--UUSSBB

Schema a blocchi e pinout dell’integrato PIC16C745

L’integrato al quale faremo riferimento in questoCorso è il PIC16C745 di cui riportiamo in

questo box lo schema a blocchi interno e la pin-out. Il micro dispone di una Program

Memory da 8K e di 256 Byte di RAM.Il dispositivo integra anche 5 moduli A/D con

una risoluzione di 8 bit e 2 moduli PWM , oltreall’interfaccia USB che fa capo ai pin 15 e 16.

Page 4: Corso PIC-USB

Elettronica In - ottobre 2004 83

>

positivi per ciascun controller. Ciascun dispositi-vo, inoltre, può essere connesso e disconnessomentre il PC e le altre periferiche sono attive efunzionanti attraverso un sistema ingegnoso dicondivisione della banda ed una tecnica di rile-vamento dello stato delle periferiche. In questomodo l'attività dell'utente per la riconfigurazionedel proprio PC risulta enormemente semplificata.Chi di voi ha in passato fatto i conti con i conflittidi IRQ e lo spazio di indirizzamento quandoinstallava una scheda PCI (o ISA nella notte deitempi) può tirare un sospiro di sollievo; in questocaso non sarà necessario neppure aprire il casedel PC. Infine, bisogna tener presente che lostandard USB prevede la possibilità di fornire l'a-limentazione direttamente dal PC (fino a max500 mA) risolvendo anche il problema delle bat-terie o degli alimentatori esterni.

Architettura USB

Il modello di interconnessione USB si componeprincipalmente di due componenti fondamentali:USB Host: ogni sistema USB ha un unico Hostche è assimilabile al nostro PC. Più precisamen-te l'Host utilizza come interfaccia il controllerUSB integrato nella scheda madre o in una sche-da PCI aggiuntiva. Quest'ultimo, a sua volta,include un dispositivo che gestisce le diverseporte presenti chiamato "root-hub".USB Device: sono i dispositivi che colleghiamoalle porte USB del nostro PC e possono essere aloro volta di due tipi: Hub che offrono ulterioripunti di connessione con una porta di upstreamverso l'host e una o più porte di downstreamverso altri hub o dispositivi, o Terminali cheoffrono invece una serie di funzionalità al siste-ma e possono essere tastiere, mouse, il nostroprototipo PIC ecc. Quindi dal punto di vista topologico l'architettu-ra USB si basa su un'interconnessione a stellaorganizzata su più livelli, fino a 6 (vedi Fig. 1). Ilcentro stella è dato da un Hub, ogni segmento èrappresentato da un cavo di connessione che puòcollegare:- host e hub- host e terminale- hub e hub- hub e terminaleDal nostro punto di vista di sviluppatori PIC ciriferiremo fondamentalmente ad un modellosemplificato a solo due strati, visto che in realtàogni prototipo potrà essere collegato a qualunque

temporanea dai diversi apparati della catena. Labanda passante disponibile è di 12 Mbps e vienedivisa sulla base di chi prima arriva meglio allog-gia, perciò il primo apparato collegato al sistemaotterrà tutta la banda di cui ha bisogno e gli altridovranno dividere quel che resta fino a quandone resterà talmente poca da costringere il sistemadi autoconfigurazione a rifiutare nuove periferi-che che abbiano bisogno di più banda passante diquanta ne resti libera. Il PC si limiterà a scartareil dispositivo, senza però necessariamente segna-

CCoorrssoo PPIICC--UUSSBB livello della catena rimanendo invariate le pro-

blematiche di comunicazione che affronteremo.Anticipo, che le periferiche USB sono divise inclassi che raggruppano quelle con le medesimefunzionalità. Ad ogni classe viene assegnata unacerta priorità nell'utilizzo della banda passante. Ilnostro PIC verrà trattato dal Host Controller inmaniera preferenziale rispetto ad altri dispositivi.Sarà infatti un HID (Human Interface Device)cioè una periferica in grado di generare un inter-rupt quindi ad alta priorità (in realtà vedremo cheil concetto di interrupt nel USB è un pò differen-te da quello solito che conosciamo). Il modello adue strati diviene quindi ampiamente condivisi-bile visto che le specifiche USB fanno sì che ilcontroller ci prenoti sempre un "posto" nellasequenza di dati che transita nei vari strati. Pernoi risulterà quindi assolutamente trasparente ilfatto di collegare il nostro prototipo all'inizio oalla fine della catena visto che per il controllersaremo sempre tra i primi della classe.Naturalmente bisogna far attenzione a non esa-gerare. Se si osserva il modello, infatti, ci accor-giamo che mano a mano che il traffico risaledalle singole periferiche verso il PC, attraversan-do i diversi Hub, tutto si concentra in un numerosempre minore di fili e alla fine un solo cavo tra-sporta al PC tutte le informazioni fornite in con-

Modello Architettura USB

Fig. 1

Page 5: Corso PIC-USB

84 ottobre 2004 - Elettronica In

>

lare l'errore. L'impressione sarà che l'oggetto siadifettoso, anche se in realtà funziona benissimo,ma chiede semplicemente più di quello che puòessergli concesso, e perciò non riceve nulla. Nelcaso esagerassimo riempiendo il PC di periferi-che multimediali (apparati che abbiano un traffi-co isocrono come videocamere digitali o disposi-tivi audio) potremmo arrivare a saturare la bandapassante e far si che il nostro bel prototipo di mitipretese (si consideri che utilizzeremo pacchetticon lunghezza max di 8 byte su 1500) possa darfastidio a qualcuna di queste. Infatti, il nostro cir-cuito riceverà l'attenzione di cui necessita (ilnostro posto sul treno di pacchetti è prenotato) ascapito magari della nostra videocamera digitale.Qualcuno di voi forse avrà già intuito che con unsistema del genere è molto importante che la pro-gettazione del dispositivo e del relativo driversiano fatte in maniera intelligente ed oculata. Sipensi a che cosa succederebbe se il driver nonliberasse la banda utilizzata quando il dispositivonon è in uso. Nel prosieguo ci riferiremo ad unmodello semplificato a due soli strati con un hosted un device terminale che sarà il nostro prototi-po (vedi Fig. 2).I concetti di Host e Device sono fondamentaliper capire i diversi ruoli che si vengono a crearenell'interazione attraverso l'USB. In particolareattraverso queste due definizioni si può ben com-prendere la diversità di funzioni che dovrannoessere svolte dai due oggetti principali di questocorso: il firmware (lato device) ed il Client soft-ware (lato Host). Si tenga ben presente, che l'ar-chitettura USB è centrata sull'host. Quindi, inogni situazione è l'host a comandare nella comu-nicazione. Le periferiche non possono inviaredati se non sono contattate dall'host. Viene utiliz-zato un protocollo a "Token", l'host inizia invian-do un pacchetto che autorizza il terminale acomunicare. Se la periferica è pronta rispondeall'invito e si avvia la procedura di handshakingche inizia lo scambio dei dati. L'host controllatutto il sistema ed in questo modo si elimina il

problema dell'arbitraggio del canale di comuni-cazione. Se ci pensiamo un attimo è la situazioneinversa del modello Ethernet utilizzato nelle retidi PC, dove il terminale comunica non appena neha la necessità e si è dovuto prevedere, studiandoopportune tecniche di condivisione del canale, ilcaso in cui malauguratamente due terminali deci-dano di comunicare contemporaneamente.

Endpoints e Buffers

Assodato che la comunicazione USB avviene tradue personaggi principali: un host ed un devicecon ruoli ben distinti, focalizziamo la nostraattenzione sul seguente schema che ci permettedi introdurre due altri concetti chiave nello svi-luppo USB: Endpoints e Buffers (vedi Fig.3). Abbiamo visto che un Device si può considerarecome un dispositivo che offre delle funzionalità.Il sistema USB vede ogni Device come un insie-me di Endpoints che si possono considerarecome degli oggetti indipendenti l'uno dall'altro ingrado di trasmettere o ricevere dati o informazio-ni di controllo attraverso un canale di comunica-zione detto "pipe". In pratica, (lo vedremo ana-lizzando i descrittori) gli endpoints costituisconole interfacce verso le funzioni che il dispositivooffre. Inoltre le interfacce comporranno dalpunto di vista logico delle modalità di configura-zione per cui un dispositivo potrà avere diversimodi di funzionamento. Dalla parte Host ad ogniendpoint si associa un buffer di memoria che ilsoftware Client utilizzerà per trasmettere e rice-vere a sua volta i dati dal device. Quindi, dalpunto di vista logico tutta la comunicazione USBavviene tra un buffer ed un endpoint attraversouna pipe. Gli endpoint ed i buffer sono in praticagli estremi del flusso di comunicazione tra unhost ed un device. Nel firmware e nel softwareche andremo a sviluppare si utilizzeranno esclu-sivamente questi due oggetti per trasferire dati dauna parte all'altra. E' chiaro che bisognerà riusci-re ad identificare univocamente ogni endpoint.Ebbene ogni dispositivo ha un numero identifica-tivo assegnato dal sistema nel momento in cuiesso viene collegato alla porta. Ogni endpoint asua volta ha un numero che viene deciso almomento della costruzione del dispositivo.Infine, ogni endpoint ha una sua direzione dilavoro (IN/OUT) nel senso che trasmette o rice-ve. La direzione è sempre stabilita rispetto all'-host. La combinazione dei due numeri e delladirezione permette di identificare univocamente

CCoorrssoo PPIICC--UUSSBB

Modello semplificato USB

Fig. 2

Page 6: Corso PIC-USB

Elettronica In - ottobre 2004 85

>

ogni endpoint. Ogni dispositivo USB deve obbli-gatoriamente contenere almeno una coppia checostituisce l'Endpoint numero 0 (0-IN e 0-OUT).Questo è necessario perchè è stata prevista unapipe di default chiamata "Default Control Pipe"che viene utilizzata dal sistema per inizializzare,configurare e controllare lo stato del dispositivo.Nel momento in cui un dispositivo è collegatoalla porta, alimentato ed ha ricevuto un segnaledi reset l'endpoint zero deve essere sempre acces-sibile attraverso la pipe di default. La famigliaPIC16C745/765 implementa 6 endpoints sono,cioè, disponibili i tre numeri di endpoint 0,1,2ciascuno con due direzioni possibili. In generalesecondo le specifiche USB 1.1 i dispositivi chelavorano in full-speed possono avere fino a 15numeri di endpoint mentre quelli low-speed almassimo 6 (si devono sempre considerare a cop-pie una in ingresso ed una in uscita). Infine sitenga ben presente che le pipe aggiuntive e rela-tivi endpoints sono disponibili esclusivamentedopo la configurazione del dispositivo e nonsono direttamente accessibili se non dopo talefase. Fondamentalmente il software Clientrichiede i dati attraverso una pipe usando un IRP(I/O Request Packet) ed attende che la loro tra-smissione sia completata.

Tipologie di trasferimento dati

Le "pipes" possono utilizzare quattro tipologie ditrasferimento dei dati:Trasferimenti di Controllo: vengono effettuatiad intervalli non regolari e sono iniziati dall'hostattraverso una richiesta a cui segue una rispostada parte del dispositivo, tipico è il caso dell'hostche richiede lo stato del device. Trasferimenti Isocroni: corrispondono ad unacomunicazione continuativa tra host e device eriguardano tipicamente il trasferimento di infor-mazioni audio e video dove il tempo è rilevante

nel stabilire una corretta comunicazione.Trasferimenti Interrupt: riguardano pacchetti didati relativamente piccoli ed utilizzano un siste-ma chiamato "bounded-latency communication".Come vi avevo accennato il concetto di interruptin questo caso è diverso da quello usuale in quan-to la comunicazione è comandata dall'host ed innessun caso il dispositivo può prendere l'iniziati-va. Solitamente un interrupt viene visto come unsegnale attraverso il quale un dispositivo richiedel'attenzione di un host provocando da parte diquest'ultimo l'esecuzione di una routine di servi-zio per gestire la condizione che ha generato talerichiesta. Nell'architettura USB tale definizionenon può essere adottata per la posizione "master"dell'host pertanto al dispositivo viene assegnatauna frequenza di interscambio dei dati ed il siste-ma non fa altro che interrogarlo a tale frequenzaper vedere se ha pacchetti da inviare. Questatipologia di trasferimento è usata tipicamentenelle tastiere e nei dispositivi di puntamentocome i mouse.Trasferimenti Bulk: sono l'opposto di quelli iso-croni nel senso che la loro trasmissione può esse-re dilazionata nel tempo tipicamente sono adesempio i dati che provengono da uno scanner ovengono inviati ad una stampante.La famiglia PIC16C745/765 può utilizzareesclusivamente due tipi di trasferimento, quelli diControllo e quelli Interrupt.

Introduzione al concetto di descrittore

Ogni dispositivo conserva una serie di informa-zioni generali che ne descrivono la tipologia ed ilfunzionamento, tale struttura viene chiamatadescrittore. Nel momento in cui costruiremo inostri prototipi una buona parte dello svilupposarà dedicata alla determinazione di tale strutturache risulta indispensabile per farli funzionare.Nel prosieguo verrà presentato un paragrafo chedescrive analiticamente come si realizza undescrittore e quali sono i campi necessari. Per ilmomento ci basta considerarare che esistono 5tipologie di descrittori:1) Device: ogni dispositivo ha un unico "devicedescriptor" che contiene un insieme di informa-zioni generali come l'ID produttore, il serialnumber, la massima lunghezza dei pacchetti dausare per dialogare con l'endpoint 0 ecc.2) Configuration: ogni dispositivo può avereuno o più "configuration descriptor" che contie-ne le informazioni relative a ciascuna modalità di

CCoorrssoo PPIICC-UUSSBB

Flussi di comunicazione Endopints e Buffers

Fig. 3

Page 7: Corso PIC-USB

86 ottobre 2004 - Elettronica In

>

funzionamento dello stesso. In particolare ogniconfigurazione può definire una o più interfacceed ogni interfaccia può a sua volta contenere zeroo più endpoints (attenzione che non si consideral'endpoint 0 che deve essere sempre disponibile).Ad esempio in questo descrittore andremo a defi-nire i livelli di corrente necessari in ciascunamodalità, quindi ad esempio potremo precisareuna configurazione ad alto consumo ed un'altra abasso consumo. Nel caso di un’interfaccia ISDNche ha a disposizione due canali di comunicazio-ne da 64Kbps, potremo stabilire una modalità asingolo canale ed una che prevede l'utilizzocumuulativo di entrambe raggiungendo la veloci-tà di 128Kbps.3) Interface: permette di definire ciascuna inter-faccia all'interno di una specifica configurazioneprecisando il numero di endpoints che utilizza. 4) Endpoint: stabilisce le caratteristiche di cia-scun endpoint all'interno di un interfaccia, si pre-cisa ad esempio la grandezza dei pacchetti utiliz-zata per comunicare con esso e l'intervallo di pol-ling cioè l'intervallo di tempo a cui l'host interro-ga l'endpoint per conoscere il suo stato (vedremoche sarà essenziale per gestire i trasferimentiinterrupt).5) String: si tratta di descrittori opzionali codifi-cati tramite UNICODE. Attraverso di essi è pos-sibile codificare ad esempio le informazioni deldispositivo in più lingue. A ciascuno di essi,infatti, è associato un identificativo di linguaggio(LANGID) a 17 bit. L'host quando fa una richie-sta, precisa tale id ed il dispositivo rispondeinviando solo i descrittori nel linguaggio scelto. Non ci si preoccupi della grande libertà con cuisembra si possano definire device, configurazio-ni, interfacce, endpoint. Nella realtà dei disposi-tivi che sono stati implementati(PIC16C745/765) ci sono delle regole ben preci-se, delle configurazioni consigliate ed anchedelle limitazioni che dovremo osservare affinchétutto funzioni. Ad esempio avremo a disposizio-ne al massimo 6 endpoints e ci riferiremo a dei"Technical Brief" di Microchip per comprenderebene la struttura dei descrittori.

Il processo di enumerazione

Un altro concetto "teorico" indispensabile peruno sviluppatore di interfacce USB è il processodi enumerazione. Quando un dispositivo vienecollegato o scollegato dalla porta il sistema uti-lizza tale processo per identificarlo e per gestire

il cambiamento di stato conseguente. Lo si puòsintetizzare in 5 fasi fondamentali:1) L'hub a cui viene collegato il dispositivo infor-ma l'host dell'evento (attraverso una risposta aduna interrogazione a intervalli regolari da partedello stesso), si attendono 100ms affinchè il pro-cesso di inserimento sia terminato e l'alimenta-zione dal bus si stabilizzi.2) L'host abilita la porta a cui ci si è connessi edinvia un segnale di reset per un intervallo di10ms.3) L'host assegna un indirizzo univoco al dispo-sitivo.4) L'host legge i descrittori del dispositivo con leinformazioni di configurazione.5) Sulla base delle informazioni ricevute l'hostinvia un numero di configurazione al dispositivoche da questo momento in poi è pronto per esse-re utilizzato. Nel caso il dispositivo venga disconnesso, lacosa viene notificata all'host il quale disabilita laporta corrispondente ed aggiorna la situazionedei dispositivi collegati.Prima di addentrarci nel "USB DeviceFramework" ispiratore del Firmware Microchipche andremo ad utilizzare, soffermiamoci ancorasu due argomenti di contorno relativi alle carat-teristiche meccaniche ed elettriche dell'interfac-cia USB.

Caratteristiche Meccaniche

Per facilitare la vita agli utenti che devono con-nettere fisicamente il dispositivo al PC sono statirealizzati dei connettori specifici per il down-

CCoorrssoo PPIICC--UUSSBB

“B” Femmina

“B” Maschio

“A” Femmina

“A” Maschio

Page 8: Corso PIC-USB

Elettronica In - ottobre 2004 87

>

stream e per l'upstream in maniera da non con-fondere i due casi. In particolare si utilizzanoconnettori di tipo "A" per l'upstream quindi per ilcollegamento sullo host. Mentre si utilizzanoconnettori di tipo "B" per il downstream cioè percollegarsi al dispositivo. Naturalmente non èpossibile inserire un connettore "A" in una porta"B" e viceversa.Il cavo è costituito da quattro fili: due per l'ali-mentazione e due per i dati (vedi Fig.4). In parti-colare cavi adatti all'utilizzo in full-speed devonoavere il doppino per i dati intrecciato ed unaschermatura esterna. Per l'utilizzo in low-speed,invece, non è richiesto nè l'intreccio nè la scher-matura (i nostri prototipi utilizzeranno questamodalità pertanto i cavi si potranno auto-costrui-re senza particolari problemi).

Caratteristiche Elettriche

Su un cavo USB sono quindi veicolati i dati attra-verso una coppia intrecciata e una sorgente di ali-mentazione a 5V attraverso un'altra coppia nonintrecciata. Riguardo a quest'ultima possiamosuddividere i dispositivi USB in due grandi cate-gorie: quelli che utilizzano il bus per alimentarsi(bus powered devices) e quelli che invece utiliz-zano una fonte esterna (self-powered devices).Ma quanta corrente è possibile assorbire dal cavoUSB? Le specifiche 1.1 introducono il concettodi unità di carico (unit load) che equivale a100mA. In base a tale definizione le periferichesi raggruppano in due classi: quelle a basso con-sumo (<=100mA) e quelle ad alto consumo (da 1a 5 unit load). Di default tutti i dispositivi vengo-no trattati dal sistema come a basso consumogarantendo quindi una corrente di 100mA, men-tre se si vuole consumare di più sarà necessarioavviare una negoziazione per ottenere fino ad unmassimo di 500mA. La distribuzione della cor-rente è, infatti, gestita via software, sarà quindiquest'ultimo ad autorizzare o meno il passaggiodallo stato a basso consumo a quello ad alto con-sumo. Realizzando i nostri prototipi bisogneràtener presente quindi che ciascuna porta USBpuò veicolare una quantità di corrente pari ad unmassimo di 500mA e che comunque ne sarannosicuramente garantiti 100. Se progettiamo un dis-positivo che utilizzerà come fonte di alimenta-zione il bus dobbiamo anche considerare che l'as-sorbimento non può superare 1 unità di caricoper tutta la fase iniziale di configurazione dellaperiferica. Soltanto successivamente si potrà

negoziare ulteriori unità per far fronte alle neces-sità, ma, attenzione, non è detto che tale richiestavada a buon fine. Nel caso, infatti, il softwarenon riesca a reperire la corrente necessaria, nonfarà altro che negare l'autorizzazione alla perife-rica che rimarrà nello stato di basso consumo (enon ci sarà alcun modo di convincerlo ad agire inaltra maniera!). Se si prevede, quindi, di utilizza-re una funzione con un assorbimento di correntepiuttosto elevato o che comunque si avvicinapericolosamente al massimo consentito è benedotare la nostra periferica di un alimentatoreseparato affinchè il dispositivo possa venir utiliz-zato in qualunque condizione si trovi la sorgentesul bus. Infine, un approfondimento per i piùcuriosi. I pacchetti trasmessi sul doppino datiUSB vengono codificati attraverso un algoritmochiamato NRZI (Non Return to Zero Invert) cheelimina la necessità degli impulsi di clock (piùpropriamente li mescola alla sequenza dati).Attraverso la codifica NRZI uno '0' è rappresen-tato da un cambiamento nel livello di tensionementre un '1' corrisponde all'assenza di tale cam-biamento.Una lunga sequenza di 0 comporta l'alternanza dilivello per ciascun bit mentre una lunga sequen-za di 1 comporta un segnale statico sulla linea(vedi Fig.5).Per ovviare al problema di non avere alcunatransizione per un lungo periodo di tempo, vieneinserito ogni 6 bit uno zero detto "stuffing bit". Inquesto modo viene forzata una transizione alme-no ogni 7 bit garantendo quindi una sincronizza-zione del sistema.Il ricevente deve, quindi, decodificare lo streamNRZI riconoscere lo "stuffing bit" e scartarlo.Ogni pacchetto è preceduto da 7 bit a 0 seguiti daun 1 che compongono la sequenza di sincroniz-

CCoorrssoo PPIICC--UUSSBB Fig. 4

Page 9: Corso PIC-USB

88 ottobre 2004 - Elettronica In

>

zazione (vedi Fig. 6). Infine, ogni pacchetto èracchiuso tra due delimitatori: un segnale di SOP(Start of Packet) ed uno di EOP (End of Packet).In particolare il SOP si realizza nel momento incui D+ e D- passano dallo stato di Idle al livel-lo logico opposto (K state). Per le tensioni rela-

operazioni definite nelle specifiche visto cherisulta ben più produttivo conoscere l'implemen-tazione specializzata Microchip. Si consideri cheattraverso l'utilizzo di 9 API (ApplicationProgram Interfaces) e 2 funzioni ridefinibili dal-l'utente è possibile automatizzare tutte le opera-

CCoorrssoo PPIICC--UUSSBB

tive ai livelli di segnale (stato J,K,0,1) nellevarie modalità di comunicazione Low-Speed,Full-Speed, High-Speed vi rimando alle specifi-che v2.0. Nel diagramma V-in è riferito al connettoreposto sul dispositivo terminale mentre V-outalla porta sorgente del Hub (vedi Fig. 7).Nel caso del EOP, invece, D+ e D- vengonomessi low per un tempo pari a 2 bitTime segui-ti da un bitTime allo stato J. La durata delsegnale EOP è chiaramente dipendente dallavelocità di comunicazione. Per lo stato di low dientrambe le linee ci si riferisce a SE0 che sta per"Single Ended Zero" (vedi Fig. 8).

USB DEVICE FRAMEWORK

Nelle specifiche 1.1 il capitolo 9 è riservato alladescrizione degli stati di un dispositivo USB e

delle relative operazioni che esso supporta. Ilfirmware Microchip contiene un'implementazio-ne di tali operazioni tant'e' vero che il sorgente èstato chiamato USB_CH9.asm (CH9 sta perChapter 9). Noi non analizzeremo nel dettaglio le

zioni descritte permettendo all'utente di concen-trarsi esclusivamente sui dettagli specifici dellapropria implementazione senza dover perdertempo a sviluppare delle funzionalità comuni.Definiamo quindi quali sono gli stati assumibilida un dispositivo e quali sono le operazioni chedeve supportare.Gli stati possibili in cui può venirsi a trovare undispositivo USB sono fondamentalmente 6:Collegato, Alimentato, Stato di Default,Indirizzato, Configurato o Sospeso. Ogni perife-rica è assimilabile ad una macchina a stati finitiche attraverso le successive interazioni con l'hostcambia di stato a seconda della azione intrapresada quest'ultimo. Il modello presentato ci permette di raccoglierele idee e di capire quale sarà il comportamentodinamico dei prototipi che andremo a costruire.Analizziamo quindi i vari casi:

Stato Collegato: la periferica viene collegata allaporta, l'alimentazione non viene erogata imme-diatamente pertanto si dice che il dispositivo ècollegato ma non alimentato (connected but notpowered). Soltanto successivamente alla confi-

Fig. 5

Fig. 6

Page 10: Corso PIC-USB

Elettronica In - ottobre 2004 89

>

gurazione dell'hub da parte dell'host la portaviene alimentata. In generale, considerando ilnostro modello semplificato a due soli strati, pos-siamo tranquillamente pensare che il nostro col-legamento avverrà direttamente sul hub root (giàconfigurato) pertanto l'unica azione dell'host è

Register" corrispondente ad una delle modalitàdi funzionamento elencate nel descrittore (di tipoconfiguration).Stato Configurato: il dispositivo è pronto perassolvere alle funzioni che gli sono state asse-gnate.

CCoorrssoo PPIICC--UUSSBB

quella di attendere un breve intervallo di tempotra la notifica dell'hub e la stabilizzazione dell'a-limentazione sul bus. E' proprio quello cheabbiamo visto nella prima fase del processo dienumerazione.Stato Alimentato: il dispositivo è collegato ericeve l'alimentazione del bus, a questo puntointerviene il segnale di Reset inviato dall'host cheimpone un altro cambiamento di stato.Stato di Default: una volta terminato il segnaledi reset il dispositivo è indirizzabile attraverso unindirizzo di default e può comunicare con l'hostattraverso una pipe preferenziale (vi ricordate laDefault Control Pipe e l'endpoint 0 ?). L'hostancora una volta inizia un'azione che comportaun ulteriore cambiamento di stato, assegna cioèun indirizzo univoco al dispositivo.Stato Indirizzato: il dispositivo ha un suo indi-rizzo ben preciso ma non è ancora pronto a fun-

zionare. Infatti l'host sulla base delle informazio-ni scambiate deve configurarlo. Nella pratica nonfa altro che assegnargli un numero di configura-zione, cioè scrivere un valore in un registro par-ticolare chiamato "Device Configuration

Stato Sospeso: per il risparmio di energia nelmomento in cui il bus rimane inattivo (non c'e'traffico di pacchetti) per un determinato periododi tempo (nelle specifiche si parla di 10ms).Durante tutto il periodo di sospensione il dispo-sitivo mantiene l'indirizzo assegnato e le relativeinformazioni di configurazione. Si noti che perciascun cambiamento di stato il modello prevedeun'azione progressiva ed una regressiva che portail dispositivo ad uno stato precedente. Ad esem-pio, se durante la sospensione il traffico sul busriprende, il dispositivo si porterà di nuovo in unostato attivo, tipicamente quello configurato (ameno che la sospensione non sia arrivata in unostato intermedio). Veniamo ora alle operazioni che ciascun disposi-tivo USB deve supportare. Considerando, infatti,che ci troviamo in un'architettura centrata sull'-host, il dispositivo non farà altro che rispondere

ad una serie di richieste precisate dal suo"Comandante". Tutti i dispositivi USB cheandremo a creare devono essere in grado dirispondere alle richieste dell'host attraverso laDCP (Default Control Pipe). In particolare tutte

Fig. 7

Fig. 8

Page 11: Corso PIC-USB

90 ottobre 2004 - Elettronica In

>

queste richieste sono costituite da 8 bytes cosìcome definite nella tabella di Figura 10.Le specifiche USB definiscono delle richiestestandard a cui tutti i dispositivi devono essere ingrado di far fronte. Esse si possono schematizza-re così come definito nella tabella di figura 11. Naturalmente nel campo bRequest nella realtàvengono passati due byte il cui valore convertitoin decimale è stato messo tra parentesi (ad esem-pio [12] = 00000000 00001100). Inoltre il tipodescrittore che incontriamo in GET/SETDESCRIPTOR viene selezionato attraverso latabella di figura 12.Infine il selettore di feature può essere solo didue tipi secondo la tabella di Figura 13.Analizziamo più nello specifico una sola di que-ste operazioni perchè ci ritornerà utile quandodovremo sviluppare il firmware del PIC. Sarànecessario infatti dare un significato specificoalla richiesta SET_CONFIGURATION a secon-da del dispositivo che si vuole realizzare. Taleoperazione è fortemente legata ai descrittori di

CCoorrssoo PPIICC--UUSSBB

tipo configuration.L'operazione di SET_CONFIGURATION èrelativamente semplice perchè non fa altro cheprecisare un valore di configurazione nel bytemeno significativo del campo wValue. Questo

valore può essere 0 oppure deve corrisponde-re esattamente a quello contenuto in undescrittore configuration che è stato pre-cisato sul dispositivo che si vuole uti-lizzare. Attraverso tale valore saràpossibile scegliere attraverso l'host la

modalità di funzionamento cheavremo sviluppato. Si faccia inol-

tre attenzione al fatto che nelcaso in cui il dispositivo si trovinello stato "Indirizzato", se ilcampo passato è 0 il devicerimane in tale stato altrimen-ti viene forzato un cambia-mento e il dispositivo assu-me la modalità specificatadal descrittore corrisponden-

te entrando in "Configurato".Nel caso invece il dispositivo

si trovi già in quest'ultimo sta-dio l'operazione di SET_CONFI-

GURATION lo farà ritornare allostato "Indirizzato" se il valore è

zero. Mentre se il valore è diverso dazero verrà inizializzata una nuova modalità

di funzionamento mantenendo lo stato"Configuration".A noi interesserà in particolare quest'ultimo casoquando vorremo realizzare nuove modalità diconfigurazione del nostro dispositivo e selezio-narle attraverso il software lato Host.Le altre operazioni possono essere così sintetiz-zate:CLEAR_FEATURE: Disabilita la feature passa-ta in wValue;GET_CONFIGURATION: Ritorna il valore diconfigurazione selezionato per il dispositivo.GET_DESCRIPTOR: Ritorna il descrittore sele-zionato attraverso il wValue nel linguaggio sele-zionato in wIndex.GET_INTERFACE: in ogni configurazione cipossono essere più interfacce i cui settaggi sonomutuamente esclusivi, con questa istruzione sipossono reperire tali parametri alternativi.GET_STATUS: ritorna lo stato di un dispositivo,di un interfaccia o di un endpoint. Un dispositivo può essere:- "self-powered": riceve l'alimentazione dall'e-

Fig. 9

Page 12: Corso PIC-USB

Elettronica In - ottobre 2004 91

>

CCoorrssoo PPIICC--UUSSBB

Fig. 10

Fig. 11

Page 13: Corso PIC-USB

92 ottobre 2004 - Elettronica In

sterno;- "bus powered": riceve l'alimentazione dal bus;- "remote wakeup enable": il dispositivo sospesopuò notificare all'host (anche lui sospeso) la

Un'interfaccia ritorna due byte che sono posti azero e secondo le specifiche sono riservati.Un endpoint può essere:- Halted: cioè bloccato, lo si usa esclusivamenteper gli endpoint in grado di gestire trasferimentiinterrupt e bulk;- Not Halted: sbloccato, quindi i trasferimentipossono avvenire tranquillamente.SET_ADDRESS: definisce l'indirizzo univocoche verrà utilizzato per l'accesso al dispositivo.SET_DESCRIPTOR: permette di aggiornare undescrittore o di aggiungerne altri.SET_FEATURE: permette di abilitare o disabili-tare una specifica feature, chiaramente tale ope-

CCoorrssoo PPIICC--UUSSBBnecessità di uscire dal suo stato di sospensione

per gestire un evento; - "remote wakeup disable": disabilita la featureprecedente.

razione influenza i possibili valori della get_sta-tus.SET_INTERFACE: le interfacce hanno dei set-taggi mutuamente esclusivi, questa istruzionepermette di selezionarli.SYNCH_FRAME: viene utilizzato esclusiva-mente nei trasferimenti isocroni in cui si utilizzauno schema di sincronizzazione specifico. Inpratica la comunicazione può avvenire attraversoframe di lunghezza diversa a seconda di un for-mato definito. Con questa istruzione si indicaall'host dove lo schema inizia a ripetersi (cioèquando si passa al pacchetto d'informazione suc-cessivo).Qualcuno, più attento, si sarà accorto che all'ini-zio di questo paragrafo (che presenta una pano-ramica sintetica ma sufficiente sul framework)non abbiamo fatto altro che ripercorrere il pro-cesso di enumerazione formalizzandolo in unaserie di cambiamenti di stato. Questo fa capireche tale procedura è in effetti il cuore di tutto ilmeccanismo perchè permette di raggiungere lostato "configurato" che potrà avere come evolu-zione soltanto la creazione di sessioni di comuni-cazione tra buffers e endpoints. Il firmwareMicrochip si basa tutto proprio su questa consi-derazione.Arrivati a questo punto siamo in grado di intro-durre il modello firmware presentato daMicrochip che studieremo in maniera approfon-dita iniziando finalmente la parte sperimentale diquesto corso. Via via che introdurremo le istru-zioni necessarie, infatti, inizieremo a sperimen-tarne il funzionamento sia analizzando il codicereso disponibile, sia iniziando a scrivere delleroutine che richiameranno tali funzionalità e chele manipoleranno per i nostri scopi. Si osservi loschema di Figura 14 che riassume con grandesemplicità il sistema di interazione con il firm-ware Microchip.Come si vede il codice che andremo a sviluppa-re andrà ad interfacciarsi con tre funzioni princi-pali che realizzano proprio la considerazione acui siamo giunti. Dopo il processo di enumera-zione gestito attraverso InitUSB che permetteràdi portare il dispositivo nello stato"Configurato", realizzeremo delle sessioni dicomunicazione attraverso le funzioni PutEPn(EPn sta per Endpoint numero n) e GetEPn checi permetteranno di scambiare dati attraverso gliendpoint che avremo definito. Bene, appunta-mento alla prossima puntata ... preparate PC edemoboard !

Fig. 12

Fig. 13

Fig. 14

Page 14: Corso PIC-USB

iprendiamo in mano lo schema che abbia-mo visto la scorsa puntata e raccogliamo

un po’ di idee (vedi fig. 1). C’eravamo lasciaticon questa considerazione: nel momento in cuiun device USB si trova nello stato“Configurato”, cioè successivamente al processod’enumerazione, sarà possibile realizzare dellesessioni di comunicazione attraverso gli end-point che avremo definito. Ricordiamo, inoltre,che il PIC16C745/765 implementa un moduloche supporta esclusivamente i trasferimenti Low-speed (1,5Mbps) di tipo Control e Interrupt e checi sono 3 numeri di endpoint a disposizione(0,1,2) per un totale di 6 endpoints (si ricordi cheogni endpoint può essere IN o OUT).

Introduzione alla struttura del firmwareMicrochip

Analizziamo ora un po’ più da vicino com’èstrutturato il firmware Microchip. Attualmentesul mercato sono state rilasciate due versioni la1.25 e la 2.00 che sono piuttosto differenti

soprattutto per la filosofia di funzionamento piùche per le funzioni disponibili. Ci riferiremo alla1.25 perché risulta essere l’unica modificatadalla microEngineering Labs Inc. per il compila-tore PBP (PICBasic PRO) e che quindi potremoutilizzare per i nostri programmi in Basic.Naturalmente, analizzeremo anche le innovazio-ni introdotte dalla 2.00 comparando i due pac-chetti. Il firmware messo a disposizione col com-pilatore si compone di 5 file essenziali:USB_DEFS.INC : contiene la definizione dellevariabili e delle macro utilizzate nel resto deisorgenti.USB_CH9.ASM: contiene l’implementazione ditutte le funzioni definite nel capitolo 9 delle spe-cifiche USB.HIDCLASS.ASM: contiene l’implementazionedelle funzioni definite nelle specifiche degli HID(Human Interfaces Devices) che vedremo neiprossimi paragrafi.USB_MAIN.ASM: un’applicazione d’esempio.DESCRIPT.ASM: una struttura di descrittorid’esempio.

Elettronica In - novembre 2004 83

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

2AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittààUUSSBB iimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorrii ddeellllaa MMiiccrroocchhiipp..UUnn aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittààiinn ccoonnssiiddeerraazziioonnee ddeellllaa ccrreesscceenntteeiimmppoorrttaannzzaa ddii qquueessttaa aarrcchhiitteettttuurraa nneellllaaccoommuunniiccaazziioonnee ttrraa ccoommppuutteerr eeddiissppoossiittiivvii eesstteerrnnii.. IInn qquueessttaa sseeccoonnddaappuunnttaattaa aannaalliizzzziiaammoo llaa ssttrruuttttuurraa ddeellffiirrmmwwaarree MMiiccrroocchhiipp ee llee ffaassii ddii ssvviilluuppppoorreellaattiivvee aall PPIICC1166CC774455..

a cura di Carlo Tauraso

Page 15: Corso PIC-USB

84 novembre 2004 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

La presenza del terzo file (HIDCLASS.ASM) cipermette di introdurre nello specifico la defini-zione di HID. Nel primo capitolo vi avevamoanticipato che avremmo fatto in modo che ilnostro PIC sarebbe stato trattato in maniera pre-ferenziale dall’host. Ebbene nell’insieme dei dis-positivi Low-speed che possono essere prototipa-ti attraverso il PIC16C745 esiste una classemolto particolare denominata Human InterfacesDevices. Storicamente rappresenta la prima clas-se di dispositivi ad essere stata implementata perl’USB e ad essere integrata nei sistemiMicrosoft. Nasce, com’è facile intuire dal suonome, per lo sviluppo di tutti quei dispositivi uti-lizzati dall’uomo per controllare il funzionamen-to di un elaboratore. Quindi, tra gli HID sono daannoverare mouse, tastiere, joystick, gamepadecc. Purtuttavia le specifiche HID sono sufficien-temente ampie per inglobare tutti i dispositiviche devono dialogare con un host a bassa veloci-tà (max 64Kb/s) ed in entrambe le direzioni.Ecco, quindi, che potremo tranquillamente utiliz-zare un HID come data logger, sistema di con-trollo accessi, termometro digitale, robot e chi neha più ne metta. Ma che cos’è che realmente ci fapropendere a sviluppare firmware per un HIDanziché per un qualsiasi altro device?Sicuramente Windows è il sistema operativo piùdiffuso al mondo e comprende, nelle versioni 98,2K, XP, i drivers necessari per la comunicazionecon tutta la classe di dispositivi HID. Questosignifica che il nostro prototipo non richiederàalcun altro software al di fuori del nostro firm-ware ed un’eventuale applicazione Host per fun-zionare. Non dovremo preoccuparci di sviluppa-re driver particolari o di conoscere a fondo lefunzioni e le librerie di sistema, ma potremo per-sonalizzare il modo con cui il sistema riconosceil dispositivo con dei semplici file di testo (.inf).In secondo luogo, un HID semplifica la defini-

Fig. 1

zione dei descrittori permettendo allo sviluppato-re di concentrarsi sulla definizione dell’interfac-cia e dei dati che saranno scambiati con l’host.Con quest’ultima affermazione siamo arrivati alpunto più importante per lo sviluppo firmware suUSB: la definizione di report.

HID Report

I dispositivi HID utilizzano tre descrittori sup-pletivi oltre a quelli standard già visti nella pre-cedente puntata secondo il seguente schema:

Fig. 2

Fig. 3

Il descrittore HID è in pratica una tabella chedefinisce quali sono gli altri descrittori che sonostati definiti. Semplificando, le informazioniminime necessarie sono un flag (SI/NO) per lapresenza o meno del descrittore di tipo specifica-to ed un valore pari alla sua lunghezza. I descrittori successivi possono essere:Report: definisce tutti i dati che saranno scam-biati con l’host.Fisico: è opzionale e definisce le parti fisiche delcorpo umano che saranno utilizzate per azionareil dispositivo.Inserendo il tutto nella struttura dei descrittoristandard (vista nella scorsa puntata) possiamoriassumere la situazione con il seguente diagram-ma:

Page 16: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - novembre 2004 85

>

Fig. 4

Fig. 5

Focalizziamo la nostra attenzione sul descrittoreReport perché ci permetterà di definire nel detta-glio quali saranno i dati scambiati con l’host cheè basilare per poter poi realizzare il firmware chefarà funzionare il dispositivo. Senza aver defini-to i report in pratica non potremo comunicare sulbus i dati acquisiti o elaborati dal PIC ed il nostrodispositivo diverrebbe inservibile. Ogni report sipuò vedere come un insieme di celle informativechiamate Item. Gli Item possono essere di duetipi: Short Item lunghi da 1 a 5 bytes utilizzatinelle applicazioni più comuni, e Long Item lun-ghi da 3 a 258 bytes utilizzati laddove è necessa-rio scambiare strutture dati molto ampie.Vediamo com'è strutturato uno Short Item (fig. 4)ed a cosa corrisponde ogni singolo bit (fig. 5):

Come si vede esistono diversi tipi di Item, i piùimportanti sono i Main Item perché permettonodi stabilire i campi dati provenienti da un con-trollo (ad esempio il tasto premuto su una tastie-ra o il click del mouse). Essi possono essere di tre tipi:Input: dati che vanno dal dispositivo verso l’hostOutput: dati che vanno dall’host verso il disposi-tivo (ad es. lo stato dei led di una tastiera)Feature: dati sia d’input che d’output che nonsono utilizzati dall’utente ma s’intendono per unutilizzo interno di controllo del dispositivo.Collection - End Collection: permettono di deli-mitare un raggruppamento di Input, Output oFeature.Mentre i Main Item stabiliscono la lunghezza diun campo, se il suo valore è assoluto o relativo e

così via, i precedenti Global e Local stabilisconodegli attributi più generali ad esempio il minimoed il massimo valore dei campi. In particolare iLocal descrivono i campi del successivo MainItem mentre i Global descrivono degli attributiche si applicano a tutti gli item. Tutti questi tagformano una struttura che verrà analizzata da unparser incluso nel driver del sistema operativoche permetterà di rendere disponibili all’applica-zione Host i dati necessari.Tutto ciò potrebbe generare un po’ di confusioneallo sviluppatore per la quantità d’informazioniche deve strutturare per poter far funzionare ilsuo prototipo. Nella realtà la struttura da realiz-zare diviene molto più semplice e lineare se sivanno ad estrarre i campi necessari e sufficienti.L’architettura che è stata pensata per gli HID,infatti, è molto ampia nel senso che si possonoutilizzare delle feature molto specifiche, ma allostesso tempo considera come necessarie soloalcune informazioni che costituiscono le fonda-menta su cui poggia tutta la struttura. Ebbene,ogni descrittore Report deve contenere gli Itemmostrati in Fig. 6 (tutti gli altri sono opzionali).Tale struttura sarà quella che utilizzeremo in tuttii nostri esperimenti, ed è quella che è alla basedello sviluppo HID in ambito professionale. Perquanto riguarda gli Usage esistono dei documen-ti ufficiali che definiscono i cosiddetti UsageTables (sul sito della rivista è possibile scaricar-li): sfogliandoli è possibile trovare definizioniper i più disparati dispositivi. Ad esempio allaUsage Page numero 3 che tratta i dispositivi direaltà virtuale (VR=Virtual Reality Devices) sitrova un usage denominato “Glove” che rappre-senta fino a 20 valori angolari relativi alla posi-zione delle dita dell’utilizzatore. Forti delleconoscenze acquisite fino a questo punto possia-mo iniziare a sviluppare qualcosa inaugurando laparte più interessante di questo corso.

Fasi di sviluppo Firmware PIC16C745

I passi da compiere nello sviluppo di un sistemacompleto che utilizzi i moduli USB del nostroPIC si possono sintetizzare in 4 punti:1) Analisi e precisazione degli Enpoints2) Realizzazione e testing dei descrittori standard+ HID3) Sviluppo applicazione principale lato device4) Sviluppo applicazione principale lato Host Al punto 2 nessuno ci vieta di sviluppare un dis-positivo non HID. Infatti il PIC16C745 ha come

Page 17: Corso PIC-USB

86 novembre 2004 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

unica limitazione quella di essere un deviceLow-Speed ma potrà funzionare sia come HIDche non-HID. Nel secondo caso taglieremo unaparte importante del firmware (HIDCLASS.asm)ma dovremo preoccuparci di sviluppare il driverdi comunicazione per il S.O. (Sistema Operativo)che utilizzeremo. Analizziamo i diversi punticostruendo il nostro primo semplice firmware:un termometro USB.

ESPERIMENTO nr. 1

Per i nostri esperimenti utilizzeremo la demo-board VM110 presentata sui numeri 90 e 91 dellarivista, andando ovviamente a sostituire il micro-controllore PIC16C745 OTP con un modellofinestrato, in modo da poterlo riprogrammare piùvolte. In questo primo esempio sfrutteremo lecapacità di conversione A/D del nostro PIC, uti-lizzeremo infatti un’entrata analogica per calco-lare la caduta di tensione su una NTC. Come tutti voi ben saprete questo componente(Negative Temperature Coefficient) è caratteriz-zato dal fatto che il suo valore ohmico diminui-sce all’aumentare della temperatura.Utilizzeremo quindi la variazione di tensionecorrispondente al fine di monitorare la tempera-tura dell’ambiente. In particolare abbiamo utiliz-

zato una NTC con R25=33 kOhm e l’abbiamocollegata direttamente sui pin del ponticello SK2della demoboard. Nel programma utilizzeremocome tensione di riferimento proprio la Vdd delPIC quindi l’inserzione in questo punto è moltocomoda. Inoltre eventuali tarature (anche per l’u-tilizzo di resistenze con R25 differenti) potrannoessere effettuate agendo sul trimmer ATT1.Naturalmente si tratta di un dispositivo decisa-mente semplice ma che ci permetterà di analiz-zare tutti i passi di sviluppo che poi verrannoripercorsi con diversi livelli di dettaglio e d’inte-grazione negli esperimenti più complessi.

Fase 1: Analisi degli Endpoints

La decisione relativa a quali enpoints utilizzare èessenziale per impostare le modalità di comuni-cazione con l’host. Ci sono però delle limitazio-ni dovute al chip, al firmware e alle specificheche dobbiamo scrupolosamente osservare.Innanzitutto il nostro PIC è un dispositivo Low-Speed pertanto secondo le specifiche USB 1.1esso può avere soltanto due endpoint oltreall’endpoint0 che ricordiamo deve essere semprepresente e bidirezionale. Il chip utilizza duestrutture principali per gestire gli endpoints:l’EPCn (Enpoint Control Register) che contienei bit relativi all’abilitazione di ciascun endpointse alla sua direzione di funzionamento (si ricordiche ogni ep è caratterizzato da un numero ed unadirezione) e la BDT (Buffer Description Table)costituita da 40 byte suddivisi in 5 buffers da 8byte. Ora, di questi 5 buffer dobbiamo riservarne2 per implementare l’endpoint 0 In e Out (EP0IN/ EP0 OUT), rimangono quindi 3 buffer dadistribuire per i due endpoint suppletivi. La con-figurazione di default prevede l’assegnazione deiprimi quattro buffer rispettivamente a EP0 OUT,EP0 IN, EP1 OUT, EP1 IN. L’ultimo buffer è

Fig. 6

Page 18: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - novembre 2004 87

>

condiviso tra EP2 OUT e EP2 IN con un apposi-to sistema d’arbitraggio. Per le nostre applicazio-ni avremo quindi a disposizione esclusivamentele seguenti configurazioni:EP1 OUT o EP2 OUT (un solo endpoint in usci-ta comunicazione unidirezionale host -> device)EP1 IN o EP2 IN (un solo endpoint in entratacomunicazione unidirezionale device -> host)EP1 OUT -EP1 IN (due endpoint uno in ingres-so ed uno in uscita comunicazione bidirezionalecon l’host)EP1 OUT - EP2 IN (due endpoint uno in ingres-so ed uno in uscita comunicazione bidirezionalecon l’host)EP1 OUT - EP2 OUT (due endpoint tutti e due inuscita comunicazione unidirezionale host ->device)EP1 IN - EP2 OUT (due endpoint uno in ingres-so ed uno in uscita comunicazione bidirezionalecon l’host)EP1 IN - EP2 IN (due endpoint tutti e due inentrata comunicazione unidirezionale device ->host)L’unica configurazione non possibile è EP2 OUT- EP2 IN perché l’ultimo buffer è stato condivisoe può essere usato solo da un endpoint alla volta.Tale configurazione si può realizzare solo modi-ficando il firmware Microchip alla funzioneSET_CONFIGURATION (File ch9.asm). E’ qui, infatti, che viene stabilita la configurazio-ne di default degli endpoint e l’assegnazionedella struttura BDT. Bisogna tener presentecomunque che i buffer disponibili sono sempre esoltanto 5 pertanto se diamo maggior libertà agliendpoint 2 dovremo toglierla ad altri. In genera-le, la configurazione di default permette di rea-lizzare comunicazioni bidirezionali ad 1 canale ounidirezionali da 1 a 2 canali e ciò è più che suf-ficiente per il 99% dei dispositivi. La scelta di utilizzare uno o due canali, una

comunicazione unidirezionale o bidirezionale,dipende dal dispositivo che vogliamo creare. Nelnostro primo esperimento, oltre all’EP0 IN/OUT(bidirezionale), useremo la configurazione EP1IN. Quindi una comunicazione unidirezionaledevice - host affinchè sia reso disponibile nellapipe il valore digitale corrispondente alla cadutadi tensione. L’host leggerà ad intervalli regolari ilbuffer relativo acquisendo il dato e tramutandolonel valore di temperatura corrispettivo. Passiamoalla seconda fase.

Fase 2: creazione descrittori standard + HID

Realizzeremo un dispositivo HID, pertanto oradobbiamo cimentarci nella creazione di unastruttura di descrittori standard e HID.Innanzitutto bisogna capire come creare talestrutture e quali regole seguire. Per farlo è neces-sario introdurre i file messi a disposizione dal-l’ambiente PICBasic Compiler Pro.Essenzialmente si tratta della medesima strutturafirmware Microchip con alcune piccole modifi-che necessarie per rendere le routine compatibilicon il compilatore. Nella directory USB del pac-chetto troviamo:USB_DEFS.INC: versione PICBasic compatibi-le del medesimo file presente nel firmwareMicrochipUSB_CH9.ASM: versione PICBasic compatibi-le del medesimo file presente nel firmwareMicrochipHIDCLASS.ASM: versione PICBasic compati-bile del medesimo file presente nel firmwareMicrochipUSBDESC.ASM: file aggiunto al firmware con-tenente solo una include relativa al file che use-remo come contenitore di descrittori.USBMOUSE.BAS: versione in Basic dell’appli-cativo USB_MAIN.ASM contenuto nel firmwa-

La taratura del nostro sistema nel qualeviene utilizzata una NTC con R25= 33kOhm inserita sui pin di SK2 puòessere effettuata con un termometrocampione, ruotando il trimmer ATT1fino a quando il valore visualizzato amonitor non corrisponde con quellorilevato dal termometro. E’ possibiletuttavia utilizzare anche NTC di diverso valore: nella prossima puntatamostreremo come il nostro software sipuò adattare a diversi sensori.

La calibrazione della sonda di temperaturaNTC

ATT1

SK2

PIC16C745/JW

Page 19: Corso PIC-USB

88 novembre 2004 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

; ************************************************; Given a configuration descriptor index, returns; the beginning address; of the descriptor within the descriptions table; ************************************************Config_desc_index

movwf tempmovlw HIGH CDI_startmovwf PCLATHmovlw low CDI_startaddwf temp,wbtfsc STATUS,Cincf PCLATH,fmovwf PCL

CDI_startretlw low Config1retlw high Config1

;this table calculates the offsets for each; configuration descriptor from the beginning; of the table; more configurations can be added here; retlw low Config2; retlw high Config2

; ************************************************; Given a report descriptor index, returns ; the beginning address; of the descriptor within the descriptions table; ************************************************Report_desc_index

movwf tempmovlw HIGH RDI_startmovwf PCLATHmovlw low RDI_startaddwf temp,wbtfsc STATUS,Cincf PCLATH,fmovwf PCL

RDI_start retlw low ReportDescriptorLen retlw high ReportDescriptorLen ; this table calculates the offsets for ; each report descriptor from the ; beginning of the table, effectively; more reports can be added here; retlw low ReportDescriptorLen2; retlw high ReportDescriptorLen2

;**************************************************; This table is polled by the host immediately ; after USB Reset has been released. This table ; defines the maximum packet size EP0 can take.; See section 9.6.1 of the Rev 1.0 USB ; specification. These fields are application ; DEPENDENT. Modify these to meet your ; specifications.The offset is passed in P0 and P1; (P0 is low order byte).;**************************************************Descriptions

banksel EP0_startmovf EP0_start+1,wmovwf PCLATHmovf EP0_start,wmovwf PCL

DeviceDescriptorStartDevDescr

retlw 0x12 ; bLengthLength of this descriptorretlw 0x01 ; bDescType This is a DEVICE

descriptorretlw 0x10 ; bcdUSBUSB revision 1.10 (low byte)retlw 0x01 ; high byteretlw 0x00 ; bDeviceClasszero means each

; interface operates independentlyretlw 0x00 ; bDeviceSubClassretlw 0x00 ; bDeviceProtocolretlw 0x08 ; bMaxPacketSize0

; inited inUsbInit()retlw 0xD8 ; idVendor

; 0x04D8 is Microchip Vendor IDretlw 0x04 ; high order byteretlw 0x00 ; idProductretlw 0x00retlw 0x41 ; bcdDeviceretlw 0x04retlw 0x01 ; iManufacturerretlw 0x02 ; iProductretlw 0x00 ; iSerialNumber - 3retlw NUM_CONFIGURATIONS ; bNumConfigurations

; *************************************************; This table is retrieved by the host after the ; address has been set. This table defines the ; configurations available for the device. See ; section 9.6.2 of the Rev 1.0 USB specification ; (page 184). These fields are application ; DEPENDENT. Modify these to meet your ; specifications.; *************************************************Config1

retlw 0x09 ; bLengthLength of this descriptorretlw 0x02 ; bDescType2 = CONFIGURATION

retlw EndConfig1 - Config1retlw 0x00retlw 0x01 ; bNumInterfacesNumber of interfacesretlw 0x01 ; bConfigValueConfiguration Valueretlw 0x04 ; iConfigString Index

; for this config = #01retlw 0xA0 ; bmAttributesattributes

; bus poweredretlw 0x32 ; MaxPowerself-powered draws

; 0 mA from the bus.Interface1

retlw 0x09 ; length of descriptorretlw INTERFACEretlw 0x00 ; number of interface, 0 based arrayretlw 0x00 ; alternate settingretlw 0x01 ; number of endpoints used retlw 0x03 ; interface class-assigned by USBretlw 0x01 ; boot deviceretlw 0x02 ; interface protocol - mouseretlw 0x05 ; index to string descriptor

HID_Descriptorretlw 0x09 ; descriptor size (9 bytes)retlw 0x21 ; descriptor type (HID)retlw 0x00retlw 0x01 ; HID class release number (1.00)retlw 0x00 ; Localized country code (none)retlw 0x01 ; # of HID class descriptor to follow (1)retlw 0x22 ; Report descriptor type (HID)retlw (end_ReportDescriptor - ReportDescriptor)retlw 0x00

Endpoint1retlw 0x07 ; length of descriptorretlw ENDPOINTretlw 0x81 ; EP1, Inretlw 0x03 ; Interruptretlw 0x04 ; max packet size (4bytes) low byteretlw 0x00 ; max packet size (4bytes) high byteretlw 0x0A ; polling interval (10ms)

EndConfig1

ReportDescriptorLenretlw low (end_ReportDescriptor-ReportDescriptor)

ReportDescriptorretlw 0x05retlw 0x01 ; usage page (generic desktop)retlw 0x09retlw 0x02 ; usage (mouse)retlw 0xA1retlw 0x01 ; collection (application)retlw 0x09retlw 0x01 ; usage (pointer)retlw 0xA1retlw 0x00 ; collection (linked)retlw 0x05retlw 0x09 ; usage page (buttons)retlw 0x19retlw 0x01 ; usage minimum (1)retlw 0x29retlw 0x03 ; usage maximum (3)retlw 0x15retlw 0x00 ; logical minimum (0)retlw 0x25retlw 0x01 ; logical maximum (1)retlw 0x95retlw 0x03 ; report count (3)retlw 0x75retlw 0x01 ; report size (1)retlw 0x81retlw 0x02 ; input (3 button bits)retlw 0x95retlw 0x01 ; report count (1)retlw 0x75retlw 0x05 ; report size (5)retlw 0x81retlw 0x01 ; input (constant 5 bit padding)retlw 0x05retlw 0x01 ; usage page (generic desktop)retlw 0x09retlw 0x30 ; usage (X)retlw 0x09retlw 0x31 ; usage (Y)retlw 0x15retlw 0x81 ; logical minimum (-127)retlw 0x25retlw 0x7F ; logical maximum (127)retlw 0x75retlw 0x08 ; report size (8)retlw 0x95retlw 0x03 ; report count (2)retlw 0x81retlw 0x06 ; input (2 position bytes X & Y)retlw 0xC0 ; end collectionretlw 0xC0 ; end collection

end_ReportDescriptorStringDescriptions

banksel EP0_startmovf EP0_start+1,w

L I S T A T O D E L F I L E MF I L E M O U S D E S CO U S D E S C . A S M. A S M

Diventa la ROUTINE DIINDIRIZZAMENTO n.1 per l'indicedel descrittore CONFIGURATION

Diventa Tabella n.2 Descrittore CONFIGURATIONriscritte le definizioni dei campi

Diventa Tabella n.3DescrittoreINTERFACEriscritte le definizioni dei campi

Diventa Tabella n.4Descrittore HIDriscritte le definizionidei campi secondostandard (*)

Diventa Tabella n.5 Descrittore ENDPOINT.Le modifiche riguarderanno soprattutto lagrandezza del pacchetto e l'intervallo diinterrogazione useremo anche noi EP1/IN (*)

Diventa Tabella n.6Descrittore REPORTNaturalmente i campi vengonomodificati in base alle nostreesigenze, inoltre per chiarezzasi riportano le definizioni diciascun byte che compone ivari campi per far capire benela sequenza di istruzioni.Buona parte dei nostri sforzi sifocalizzeranno sulla definizione di un reportsufficientemente "universale"per riutilizzarlo. Nel sorgenteoriginale si notano delledescrizioni standard relativealla definizione di un mousesecondo specifiche HID. Noiuseremo dei campi vendor-defined perche' creeremo undispositivo non contemplatotra le specifiche HID. (*)

Diventa la ROUTINE DI INDIRIZZAMENTO n.2 per l'indice deldescrittore REPORT

Tutte le descrizioni dei campi vengonoriscritte secondo standard USB evidenzian-do i campi con piu' byte in low e high byteed evitando commenti di funzionamento cheverranno ben spiegati negli schemidescrittivi creati per ciascuna tabella.

Nel sorgente originale qui viene messo uno 0vanificando la possibilita' di estrarre il numseriale. Noi invece lo faremo puntare alla 3°stringa per poter usare la get relativa.

Evidenziati punti di ingresso ulterioridescrittori report

Evidenziati punti di ingresso ulterioriconfigurazioni del device. Come giàspiegato ci possono essere piu'valori di configurazione che vengonoscelti dall'host al termine delprocesso di enumerazione.

DiventaTabella n.1 DescrittoreDEVICE

Questatabella vienedivisa in 5sezioni perrispecchiarela sequenzadei varidescrittori.

Page 20: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - novembre 2004 89

movwf PCLATHmovf EP0_start,wmovwf PCL

; ************************************************; Given a configuration descriptor index, returns: the beginning address of the descriptor within ; the descriptions table; ************************************************string_index ; langid in W reg,

; string offset in EP0_startmovwf tempbcf STATUS,Crlf temp, fpagesel langid_indexcall langid_indexmovwf temp2incf temp, fpagesel langid_indexcall langid_indexmovwf tempmovf temp, wmovw fPCLATHmovf temp2,waddwf EP0_start+1,wbtfsc STATUS,Cincf PCLATH, fmovwf PCL

langid_indexmovlw high langidsmovwf PCLATHmovlw low langidsaddwf temp, wbtfsc STATUS,Cincf PCLATH,fmovwf PCL

langidsretlw low lang_1retlw high lang_1retlw low lang_2 ; string indexes of

; different languagesretlw high lang_2

lang_1 ; englishretlw low String0; LangIDsretlw high String0retlw low String1_l1retlw high String1_l1retlw low String2_l1retlw high String2_l1retlw low String3_l1retlw high String3_l1retlw low String4_l1retlw high String4_l1retlw low String5_l1retlw high String5_l1retlw low String6_l1retlw high String6_l1

lang_2retlw low String0; also point to LangIDretlw high String0retlw low String1_l2retlw high String1_l2retlw low String2_l2retlw high String2_l2retlw low String3_l2retlw high String3_l2retlw low String4_l2retlw high String4_l2retlw low String5_l2retlw high String5_l2

String0retlw low (String1_l1-String0);length of string retlw 0x03; descriptor type 3?retlw 0x09; language ID (defined by MS 0x0409)retlw 0x04retlw 0x04; some other language ID for testingretlw 0x08

String0_endString1_l1

retlw String2_l1-String1_l1; length of stringretlw 0x03; string descriptor type 3retlw 'M'retlw 0x00...Microchip...retlw 'p'retlw 0x00

String2_l1retlw String3_l1-String2_l1retlw 0x03retlw 'P'retlw 0x00retlw 'i'retlw 0x00...PIC16C745/765 USB Mouse...retlw 'e'retlw 0x00

String3_l1retlw String4_l1-String3_l1retlw 0x03

retlw 'V'retlw 0x00retlw '1'retlw 0x00retlw '.'retlw 0x00retlw '1'retlw 0x00retlw '1'retlw 0x00

String4_l1retlw String5_l1-String4_l1retlw 0x03retlw 'C'retlw 0x00retlw 'f'retlw 0x00retlw 'g'retlw 0x00retlw '1'retlw 0x00

String5_l1retlw String6_l1-String5_l1retlw 0x03retlw 'E'retlw 0x00retlw 'P'retlw 0x00retlw '1'retlw 0x00retlw '0'retlw 0x00retlw 'I'retlw 0x00retlw 'n'retlw 0x00

String6_l1

String1_l2 ; lang 2, chinese. ; String can be totally different ; than english

retlw String2_l2-String1_l2; length of stringretlw 0x03; string descriptor type 3retlw 'M'retlw 0x00...Microchip...retlw 'p'retlw 0x00

String2_l2retlw String3_l2-String2_l2retlw 0x03retlw 'P'retlw 0x00retlw 'i'retlw 0x00...PIC16C745/765 USB Mouse...retlw 'e'retlw 0x00

String3_l2retlw String4_l2-String3_l2retlw 0x03retlw 'V'retlw 0x00retlw '1'retlw 0x00retlw '.'retlw 0x00retlw '1'retlw 0x00retlw '1'retlw 0x00

String4_l2retlw String5_l2-String4_l2retlw 0x03retlw 'C'retlw 0x00retlw 'f'retlw 0x00retlw 'g'retlw 0x00retlw '1'retlw 0x00

String5_l2retlw String6_l2-String5_l2retlw 0x03retlw 'E'retlw 0x00retlw 'P'retlw 0x00retlw '1'retlw 0x00retlw '0'retlw 0x00retlw 'I'retlw 0x00retlw 'n'retlw 0x00

String6_l2

Diventa la ROUTINE DI INDIRIZZAMENTOn.2 per l'indice del descrittore STRING ilcodice sorgente fornito con ilcompilatore indica erroneamente l'indicedel descrittore configuration.

Numero Seriale useremo ESP.1 che staper esperimento numero 1

Descrizione Configurazione, ce nesara' soltanto una in questo primoesempio. Useremo CFG1.

Stringhe Linguaggio 2. Si noti che nelsorgente originale e' stato usato ilCinese, anche se si tratta solo di unesempio perche' in realta' hannomantenuto i valori della lingua inglese.

Descrizione Endpoint useremo EP1/IN

Nome prodotto secondolinguaggio.

Numero seriale secondolinguaggio.

Descrizione configurazionesecondo linguaggio.

Descrizione endopointsecondo linguaggio.

(*) Queste tabelle verranno analizzate nel corso della prossima puntata.

Diventa il vettore dei LANGIDVerranno previsti due linguaggiItaliano e Inglese anzichè Inglesee Cinese come nel sorgente originale.

Nome Prodotto: useremo"TermoUSBCorso PIC-USB"

Nome Costruttore (indiceiManufacturer=1)Le stringhe vengonomodificate per le nostreesigenze, in particolarequelle relative al nomeprodotto, numero seriale ecc.Si noti che le stringheseguiranno la sequenza cheavremo indicato nei varicampi index dei descrittoriusati. Ad esempio per ilnumero seriale indichiamol'index 3 (campoiSerialNumber) e quindi ladescrizione si trovera' nellastringa 3.

Diventa la Tabella n.7 Descrittori STRINGDovendo gestire piu' linguaggi sifara' riferimento alla codificaMicrosoft per i LANGID che si puo'reperire su Internet presso l'MSDN.Sono evidenti i punti di ingressodelle stringhe definite secondo unacodifica del tipo String+nr.Stringa+lnr.linguaggio, in pratica la stringa 1del linguaggio 2 e' String1_l2. Ilsistema di denominazione ci èapparso molto chiaro e funzionalequindi non e' stato modificato. (*)

Page 21: Corso PIC-USB

90 novembre 2004 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

re MicrochipMOUSDESC.ASM: versione PICBasic compa-tibile del file DESCRIPT.ASM contenuto nelfirmware Microchip e inserita nell’include delfile USBDESC.ASMQuindi per creare i nostri descrittori dovremofare un nuovo file che sostituiràMOUSDESC.ASM e inserirlo nell’include delfile USBDESC.ASM.Chiameremo il file contenitore di descrittori:TERMODSC.ASM. Esso è costituito da 10sezioni: 3 relative a procedure d’indirizzamentoe 7 relative alla definizione delle tabelle conte-nenti i campi dei descrittori.

Vediamo di analizzare tale struttura nel dettaglio:1) Routine che dato un indice di descrittoreConfiguration ritorna l’indirizzo iniziale deldescrittore all’interno della tabella dei descrittori2) Routine che dato un indice di descrittoreReport ritorna l’indirizzo iniziale del descrittoreall’interno della tabella dei descrittori3) Routine che dato un indice di descrittoreString ritorna l’indirizzo iniziale del descrittoreall’interno della tabella dei descrittori4) Tabella 1 descrittore DEVICE5) Tabella 2 descrittore CONFIGURATION6)Tabella 3 descrittore INTERFACE7)Tabella 4 descrittore HID

retlw 0x12 ; bLengthretlw 0x01 ; bDescriptorTyperetlw 0x10 ; bcdUSB (low-b)retlw 0x01 ; bcdUSB (high-b)retlw 0x00 ; bDeviceClassretlw 0x00 ; bDeviceSubClassretlw 0x00 ; bDeviceProtocolretlw 0x08 ; bMaxPacketSize0retlw 0xd8 ; idVendor (low-b)retlw 0x04 ; idVendor (high-b)

retlw 0x00 ; idProduct (low-b)retlw 0x00 ; idProduct (high-b)retlw 0x00 ; bcdDevice (low-b)retlw 0x01 ; bcdDevice (high-b)retlw 0x01 ; iManufacturerretlw 0x02 ; iProductretlw 0x03 ; iSerialNumberretlw NUM_CONFIGURATIONS ; bNumConfigurations

Tabella 1 - DDeessccrriittttoorree DDEEVVIICCEE

L I S T A T O 1

Page 22: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - novembre 2004 91

>

8)Tabella 5 descrittore ENDPOINT9)Tabella 6 descrittore REPORT10) Tabella 7 vettore LANGID e descrittoriSTRINGQuesta suddivisione è leggermente modificatarispetto al firmware ufficiale per permettere atutti voi di capire bene come si susseguono ledefinizioni dei descrittori secondo quanto stabili-to dalle specifiche USB. Le strutture e le descri-zioni dei campi sono più chiare e rispecchianoproprio le definizioni di tali specifiche, in questomodo abbiamo creato una struttura conforme eallo stesso tempo riutilizzabile visto che riuscire-mo a identificare le sezioni da modificare per

che rendono il listato più chiaro e leggibile. Inparticolare sono ben evidenziati i punti in cui sidevono inserire i vari campi della struttura didescrittori rendendo le cose senz’altro più sem-plici per chi si avvicina per la prima volta allaprogrammazione firmware USB. Procedendonella lettura, consigliamo di stampare il listatoTermodsc.asm che troverete sul sito della rivista.In questo modo potrete apprezzare il significatod’ogni singolo campo che andremo a modificare.Per ciascun descrittore abbiamo creato uno sche-ma di riferimento attraverso il quale potrete capi-re il significato dei vari campi. Quindi scorrendola sequenza d’istruzioni e leggendo la riga con il

Tabella 2 - DDeessccrriittttoorree CCOONNFFIIGGUURRAATTIIOONN

retlw 0x09 ; bLengthLengthretlw 0x02 ; bDescriptorType retlw EndConfig1 - Config1 ; wTotalLength (low-b)retlw 0x00 ; wTotalLength (high-b)retlw 0x01 ; bNumInterfacesretlw 0x01 ; bConfigurationValueretlw 0x04 ; iConfigurationretlw 0xA0 ; bmAttributesretlw 0x32 ; MaxPower

L I S T A T O 2

ciascun dispositivo immediatamente. Nello spe-cifico vediamo di analizzare il listatoMousdesc.asm fornito assieme al compilatoreper vedere meglio le modifiche che sono stateeffettuate. Dopodiché per tutti i nostri esperi-menti ci riferiremo al sorgente modificato.Come si vede ci sono delle modifiche formali

nome campo corrispondente sullo schema avreteuna visione completa dello sviluppo. Per ovviiproblemi di spazio la descrizione di tutta la strut-tura e poi del codice basic è stata divisa in duepuntate. Tuttavia gli schemi che vedrete sarannofondamentali per capire gli esperimenti futuridove non si riprenderà la spiegazione di ciascun

Page 23: Corso PIC-USB

92 novembre 2004 - Elettronica In

campo ma si dettaglieranno gli aspetti funzionalidel firmware che costruiremo dando per assoda-ta la conoscenza del significato dei campi. Ci permettiamo di suggerirvi un metodo di lavo-ro: trasferite gli schemi su dei file Excel mante-nendo solo la descrizione dei relativi campi,avrete così a disposizione una sorta di check-listda valorizzare di volta in volta. Leggendo poi insequenza la colonna relativa ai valori riuscirete acodificare il descrittore senza paura di averdimenticato qualche campo o aver usato qualchevalore errato. Naturalmente dopo aver scritto unadecina di descrittori gli schemi non servirannopiù e potrete lavorare direttamente sugli asmsenza particolari problemi prendendo a riferi-mento i nomi di campo standard inseriti su cia-

CCoorrssoo PPIICC--UUSSBB

dove il valore è composto da due byte inseriamonella colonna di sinistra il low-order-byte e inquella di destra l’high-order-byte per avere subi-to i valori da inserire nel file TERMODSC.asm.Laddove mettiamo tra parentesi “assegnatodall’USB” bisogna riferirsi ad un valore stabilitoin un’apposita tabella delle specifiche USB odelle definizioni di classe HID (presentiamo ivalori più importanti ma in caso di configurazio-ni particolari è bene avere a mano i documenti diriferimento). Tutte le tabelle sono riferite alle strutture datidescritte nelle specifiche USB 1.1. Inoltre, larelativa sequenza d’istruzioni inserita dopo cia-scuna griglia deve essere allineata alla label d’in-gresso che è indicata tra parentesi all’inizio della

Tabella 3 - DDeessccrriittttoorree IINNTTEERRFFAACCEE

retlw 0x09 ; bLengthretlw INTERFACE ; bDescriptorTyperetlw 0x00 ; bInterfaceNumberretlw 0x00 ; bAlternateSettingretlw 0x01 ; bNumEndpointsretlw 0x03 ; bInterfaceClassretlw 0x01 ; bInterfaceSubClassretlw 0x02 ; bInterface Protocolretlw 0x05 ; iInterface

L I S T A T O 3

scuna riga. Andiamo, quindi, ad effettuare l’editing delletabelle creando il nostro primo insieme didescrittori. Una precisazione per l’utilizzo delle griglie: lad-

sequenza. Si capisce facilmente tenendo d’occhio il listatomentre si leggono gli schemi. Nel nostro file TERMODSC.ASM inseriremonella sezione TABELLA 1 - DESCRITTORE

Page 24: Corso PIC-USB

Elettronica In - novembre 2004 93

CCoorrssoo PPIICC--UUSSBB

DEVICE inseriremo le istruzioni (presenti nelListato 1) in corrispondenza della label di iniziodel descrittore (StartDevDescr).Passiamo ora a definire e valorizzare la tabellasuccessiva (Tabella 2).Nel nostro file TERMODSC.ASM inseriremonella sezione TABELLA 2 - DESCRITTORECONFIGURATION inseriremo le istruzioni(presenti nel Listato 2) in corrispondenza dellalabel di inizio del descrittore (Config1).Andiamo alla tabella 3.Nel nostro file TERMODSC.ASM inseriremonella sezione TABELLA 3 - DESCRITTOREINTERFACE le istruzioni (presenti nel Listato 3)

in corrispondenza della label di inizio deldescrittore (Interface1).Nella prossima puntata termineremo il nostroprimo descrittore ed analizzeremo l’eseguibilebasic necessario a far funzionare il tutto. Nelfrattempo consigliamo di dare un’occhiata allistato sia del descrittore che del .bas per averun’idea più precisa del nostro obiettivo. Anticipiamo fin da ora che useremo un report unpo’ singolare perché la classe HID non prevedealcuna definizione specifica di un termometro,pertanto inseriremo dei campi cosiddetti “VendorDefined”... Riprenderemo il discorso nella pros-sima puntata.

Il ssooffttwwaarree

Riportiamo le schermate deisoftware che potrete scarica-re dal sito della rivista.Utilizzando il programmaLeggi-HID avrete la possibil-tà di interrogare il dispositivoe verificare il funzionamentodi alcuni campi dei descrittori

(in particolare l'identificazio-ne device e le stringhe inseri-te). La schermata al terminedell'interrogazione appariràcome mostrato in questobox. Questo programmainterroga qualsiasi dispositi-vo collegato alla porta USB

restituendo il nome del ven-ditore, del prodotto e i relativiID, pertanto potrete verificarei dati, per esempio, del vostromouse o della vostra tastie-ra. Il software del TermoUSBverrà analizzato nel dettaglionella prossima puntata, mariportiamo come anticipazio-ne una breve descrizione.Il programma, scritto inDelphi, non fa altro che leg-gere il dato campionato dalPIC e rappresentarlo su unLCD virtuale. Il programmaricerca il dispositivo e poilegge via via i dati che glivengono messi a disposizio-ne dal microcontrollore chedovrà essere ovviamenteprogrammato col listato com-pilato TERMOUSB.BAS. Non appena collegate lademoboard il software siaccorge della connessionevalorizzando la lista disposi-tivi e i dati del device.Facendo click su "AvviaMonitoraggio" l'host rileverà idati visualizzando la tempe-ratura sul LCD. Si può bloc-care il campionamentofacendo click nuovamente su"Avvia Monitoraggio".Si noti che i dati ricevuti ven-gono visualizzati in temporeale sul pannello "Ultimi 4valori ricevuti".

Page 25: Corso PIC-USB

ella puntata precedente ci eravamo fermatiall'editing della tabella relativa al descritto-

re INTERFACE. Stiamo, infatti, definendo lastruttura per un dispositivo HID che avrà il com-pito di digitalizzare la caduta di tensione su unaresistenza NTC che renderà disponibile il valorerisultante sull'USB. Passiamo quindi a definire i

descrittori relativi agli endpoint che abbiamodeciso di utilizzare.Ricordiamo che stiamo sviluppando un disposi-tivo HID quindi ai descrittori standard dobbiamoaggiungere quelli specifici relativi a tali disposi-tivi. Andiamo dunque a modificare la tabellarelativa al descrittore HID (vedi tabella 4). Nel

Elettronica In - dicembre 2004 / gennaio 2005 99

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

3AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittàà UUSSBBiimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorriiddeellllaa MMiiccrroocchhiipp..UUnn aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittàà iinn ccoonnssiiddeerraazziioonnee ddeellllaa ccrreesscceenntteeiimmppoorrttaannzzaa ddii qquueessttaa aarrcchhiitteettttuurraa nneellllaaccoommuunniiccaazziioonnee ttrraa ccoommppuutteerr eeddiissppoossiittiivvii eesstteerrnnii.. IInn qquueessttaa tteerrzzaa ppuunnttaattaa ccoommpplleettiiaammoo llaa ssttrruuttttuurraa ppeerr uunn ddiissppoossiittiivvoo HHIIDD cchhee ppeerrmmeettttee iill mmoonniittoorraaggggiioo ddeellllaa tteemmppeerraattuurraaaammbbiieennttaallee aattttrraavveerrssoo uunn rreessiissttoorree NNTTCC..

a cura di Carlo Tauraso

Tabella 4 - DDeessccrriittttoorree HHIIDD

Page 26: Corso PIC-USB

100 dicembre 2004 / gennaio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

nostro file TERMODSC.ASM inseriremo nellasezione TABELLA 4 - DESCRITTORE HID leistruzioni (presenti all’interno del Listato 4) incorrispondenza della label d’inizio del descritto-re (HID_Descriptor). Ricordiamo che l’end-point0 risulta predefinito e che abbiamo deciso diutilizzare una comunicazione unidirezionaleverso l’host quindi EP1 IN. Si faccia molta atten-zione a questo descrittore perchè qui si definiscerealmente il modo in cui comunicheranno host edevice. Nel nostro file TERMODSC.ASM inse-

riremo nella sezione TABELLA 5 - DESCRIT-TORE ENDPOINT le istruzioni riportate nellistato 5 in corrispondenza della label di iniziodel descrittore (Endpoint1). Siamo arrivati ad unpunto cruciale: la definizione del descrittoreReport. Qui le cose si fanno leggermente piùcomplesse perchè non è possibile definire unagriglia di massima. Ogni dispositivo avrà unadefinizione a sé fortemente dipendente dal tipo dielaborazione che si vuol fare e dai dati che sidesidera scambiare. Se ricordiamo però lo sche-

retlw 0x09 ; bLengthretlw 0x21 ; bDescriptorType retlw 0x00 ; bcdHID (low-b)retlw 0x01 ; bcdHID (high-b)retlw 0x00 ; bCountryCoderetlw 0x01 ; bNumDescriptorsretlw 0x22 ; bDescriptorTyperetlw (end_ReportDescriptor - ReportDescriptor) ;wDescriptorLength (low-b)retlw 0x00 ; wDescriptorLength (high-b)

L I S T A T O 4

retlw 0x07 ; bLengthretlw ENDPOINT ; bDescriptorTyperetlw 0x81 ; bEndpointAddressretlw 0x03 ; bmAttributesretlw 0x01 ; wMaxPacketSize (low-b)retlw 0x00 ; wMaxPacketSize (high-b)retlw 0xFA ; bInterval

L I S T A T O 5

Tabella 5 - DDeessccrriittttoorree EENNDDPPOOIINNTT

Page 27: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - dicembre 2004 / gennaio 2005 101

>

ma relativo agli item obbligatori abbiamo giàun’idea da cui partire. Sono da considerarenecessari Input (Output o Feature), Usage, UsagePage, Logical Minimum, Logical Maximum,Report Size, Report Count. Inoltre si consideriche ogni item ha un byte di prefisso del tipobSize, bType, bTag (rivedere lo schema delle

pagine precedenti). Presentiamo tale byte su duerighe, una contenente il valore binario (con traparentesi quello decimale) che si determina attra-verso lo schema di riferimento, ed una contenen-te il valore esadecimale da inserire nel file deldescrittore. Quest’ultimo è sempre presentatocon il low-order-byte a sinistra ed il high-order-

Tabella 6 - DDeessccrriittttoorree RREEPPOORRTT

Page 28: Corso PIC-USB

102 dicembre 2004 / gennaio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

byte a destra per aver direttamente il valore inse-rito nel codice assembler. Le tabelle relative aicodici da assegnare per definire le Collection,Usage Page, Usage, Report Item si trovano nelladocumentazione HID (HID Usage Tables e HIDClass Definitions 1.1). Introduciamo anche duecollection anche se in realtà non sono obbligato-rie ma ci permettono di definire un report cheriutilizzeremo in altri esperimenti. Ora, infatti,utilizziamo un unico campo dati in uscita ma nelmomento in cui dovremo scambiare dati sia iningresso che in uscita le collection ci ritorneran-no molto utili. Possiamo quindi realizzare unastruttura del genere (vedi tabella 6). Abbiamoutilizzato i campi essenziali per definire ildescrittore report che ci serve. Vedremo, negliesempi più complessi, che dovendo scambiarepiù campi dati in maniera bidirezionale, oppurefar svolgere più funzioni diverse al nostro dispo-sitivo, sarà necessario ampliare tale strutturainglobando più item Input Output. Si noti, inoltre

che stiamo definendo un dispositivo sufficiente-mente generico, cioè non legato ad una defini-zione di classe specifica, per poter in futuro uti-lizzare gli stessi campi per dispositivi diversi. Seavessimo definito un mouse o una tastiera avrem-mo dovuto seguire le definizioni HID appropria-te precisando ad esempio gli usage x e y per lecoordinate del puntatore. Qui, invece, vogliamocreare un dispositivo completamente definito danoi ma che si comporta come un HID e quindifacilmente riconoscibile dal sistema operativo.Naturalmente la definizione del descrittorereport è fondamentalmente una questione di pra-tica, la Microchip fornisce dei technical brief diesempio anche se sono limitati a device specifici,nelle Usage Tables si trovano diversi casi ancheinteressanti. Sarà bene comunque tenere a mentequesto primo esempio perchè rappresenta uncaso semplice che si può duplicare ed integrareper creare strutture più complesse. Nel nostro fileTERMODSC.ASM inseriremo nella sezione

retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage Page (low-b) ("Vendor Defined Page 1")retlw 0xFF ; Usage Page (high-b) ("Vendor Defined Page 1")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage ("Vendor Defined Usage 1")retlw 0xA1 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Collection ("Application")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage ("Vendor Defined Usage 2")retlw 0xA1 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Collection ("Physical")retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage Page (low-b) ("Vendor Defined Page 2")retlw 0xFF ; Usage Page (high-b) ("Vendor Defined Page 2")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x03 ; Usage ("Vendor Defined Usage 3")retlw 0x15 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Logical Minimum (0)retlw 0x26 ; Byte di prefisso (bTag,bType,bSize)retlw 0xFF ; Logical Maximum (low-b) (255)retlw 0x00 ; Logical Maximum (high-b) retlw 0x75 ; Byte di prefisso (bTag,bType,bSize)retlw 0x08 ; Report Size (8 bits)retlw 0x95 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Report Count (1 campo dati)retlw 0x81 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Input (Data, Var, Abs)retlw 0xC0 ; End Collection ("Physical")retlw 0xC0 ; End Collection ("Application")

L I S T A T O 6

Tabella 7 - DDeessccrriittttoorree SSTTRRIINNGG

Page 29: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - dicembre 2004 / gennaio 2005 103

>

TABELLA 6 - DESCRITTORE REPORT leistruzioni riportate nel listato 6 in corrisponden-za della label di inizio del descrittore(ReportDescriptor).Ora dobbiamo definire i descrittori String perdescrivere tutti i campi che hanno un indice cherimanda a questa tabella (ad esempioiManufacturer, iProduct, iSerialNumber,iConfiguration). Possiamo definire stringhe inpiù lingue definendo un vettore di identificatoridel linguaggio (LANGID). La lista dei valoriammessi è riportata nella tabella A. Nel nostroesempio utilizziamo due lingue: italiano e ingle-se. Attenzione che per Microsoft ogni valore ècomposto in realtà da un identificatore di lin-guaggio primario ed uno secondario (vedi tabel-la 7); il codice relativo è riportato nel listato 7.Per ovvii problemi di spazio evitiamo di ripeterela griglia per tutte le 12 stringhe definite (6 initaliano e 6 in inglese) presentando solo la tabel-la relativa alla descrizione del prodotto

String0retlw low (String1_l1 - String0) ; bLength retlw 0x03 ; bDescriptorTyperetlw 0x10 ; LANGID0 (low-b)(Per Microsoft 0x0410=Italiano)retlw 0x04 ; LANGID0 (high-b)retlw 0x09 ; LANGID1 (low-b)(Per Microsoft 0x0409=Inglese)retlw 0x04 ; LANGID1 (high-b)

String0_end

L I S T A T O 7

(iProduct) in italiano. Il codice allegato riportatonel listato 8 è sufficientemente chiaro per utiliz-zare questa sezione (vedi anche tabella 8).Terminato l’editing delle tabelle dobbiamo far inmodo che il compilatore inserisca il nostro lavo-ro nel codice eseguibile. Per farlo e sufficienteinserire l’include “termodsc.asm” nel file USB-DESC.ASM. A questo punto non ci resta che rea-lizzare il file in PICBasic che costituirà l’appli-cazione principale del dispositivo. Diciamo che ilpiù è fatto in quanto il codice è piuttosto banalevisto che deve soltanto acquisire il byte dalmodulo A/D ed inviarlo sul bus. Quello che èinteressante è la struttura del file che utilizzere-mo anche in altri casi. In particolare si osservi laparte relativa al salvataggio di tutte le variabiliche potrebbero essere modificate da un operazio-ne interrupt USB. Poche istruzioni per evitare unbel pasticcio. Vengono richiamate due funzionidi base del firmware: USBInit per avviare il pro-cesso di enumerazione e portare il dispositivo

Tabella AIdentificatoredella lingua

Lingua Identificatoredella lingua

Lingua

0x0000 Linguaggio Neutrale 0x040d Ebreo0x0400 Linguaggio di processo o User default 0x0439 Windows 2000/XP: Hindi.0x0800 Linguaggio System Default 0x040e Ungherese0x0436 Africano 0x040f Islandese0x041c Albanese 0x0421 Indonesiano0x0401 Arabo (Arabia Saudita) 0x0410 Italiano (Standard)0x042b Windows 2000/XP: Armeno 0x0810 Italiano (Svizzera)0x042c Azero (Latino) 0x0411 Giapponese0x042d Basco 0x0412 Coreano0x0423 Bielorusso 0x0427 Lituano0x141a Bosniaco (Bosnia e Herzegovina) 0x0414 Norvegese0x0402 Bulgaro 0x0415 Polacco0x0403 Catalano 0x0416 Portughese (Brasile)0x0404 Cinese (Taiwan) 0x0816 Portoghese (Portogallo)0x0804 Cinese(PRC) 0x0418 Rumeno0x041a Croato 0x0419 Russo0x0405 Ceco 0x0c1a Serbo (Cirillico)0x0406 Danese 0x081a Serbo (Latino)0x0413 Olandese (Paesi Bassi) 0x0424 Sloveno0x0813 Olandese (Belgio) 0x0c0a Spagnolo0x0409 Inglese (USA) 0x041d Svedese0x0809 Inglese (Regno Unito) 0x041f Turco0x0425 Estone 0x0422 Ucraino0x040c Francese (Standard) 0x0443 Uzbeco (Latino)0x0437 Windows 2000/XP: Georgiano 0x0843 Uzbeco (Cirillico)0x0407 Tedesco (Standard) 0x042a Vietnamita0x0408 Greco 0x0452 Gallese (Regno Unito)

Page 30: Corso PIC-USB

104 dicembre 2004 / gennaio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

allo stato configurato e ServiceUSBInt che gesti-sce gli interrupt generati dai moduli USB.Analizzeremo nel dettaglio tali funzioni quandodescriveremo il funzionamento del firmwareMicrochip, per il momento si considerino comedelle black-box. In effetti, la conoscenza del lorofunzionamento può servire se si vogliono realiz-zare delle implementazioni particolari sostituen-do il firmware Microchip, pertanto affronteremol’argomento quando saremo sufficientementepreparati per farlo. Per quanto riguarda la con-versione analogico digitale il PIC16C745 utiliz-

za tre registri: ADRES, ADCON0, ADCON1.ADCON0 permette di controllare l’operazione diconversione analogico-digitale (canali usati,clock, stato), ADCON1 permette di stabilire lafunzione dei diversi pin (nel nostro caso siamolimitati solo a RA0 e RA1 a causa del modo concui è costruita la demoboard), infine ADRES checonterrà il valore convertito. La cosa interessan-te è che grazie alla demoboard è possibile simu-lare la presenza di una tensione di ingresso attra-verso il ponticello SK2 (per RA0) quindi si puòrealizzare l’esperimento senza dotarsi della

String2_l1 ; iProduct ("TermoUSB Corso PIC-USB")retlw String3_l1-String2_l1 ; bLengthretlw 0x03 ; bDescriptorTyperetlw 'T' ; bString retlw 0x00retlw 'e'retlw 0x00retlw 'r'retlw 0x00retlw 'm'retlw 0x00retlw 'o'retlw 0x00retlw 'U'retlw 0x00retlw 'S'retlw 0x00retlw 'B'retlw 0x00retlw ' 'retlw 0x00retlw 'C'retlw 0x00retlw 'o'retlw 0x00retlw 'r'retlw 0x00retlw 's'retlw 0x00retlw 'o'retlw 0x00retlw ' 'retlw 0x00retlw 'P'retlw 0x00retlw 'I'retlw 0x00retlw 'C'retlw 0x00retlw '-'retlw 0x00retlw 'U'retlw 0x00retlw 'S'retlw 0x00retlw 'B'retlw 0x00

L I S T A T O 8

Tabella 8

Page 31: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - dicembre 2004 / gennaio 2005 105

NTC, naturalmente i dati di temperatura riferitidall’applicazione host saranno fittizi. Passiamoquindi al codice riportato nel listato 9.Analizziamo alcuni punti importanti.Innanzitutto per l’utilizzo dell’istruzione BasicADCIN che ci permette di effettuare la conver-

sione analogico/digitale è necessario effettuarealcune definizioni. Precisare la lunghezza in bitsdel risultato (ADC_BITS) e determinare la sor-gente per il segnale di clock che controlla la con-versione (ADC_CLOCK). In questo caso sele-zioniamo l’oscillatore RC dedicato interno; si

' Programma TERMOMETRO USB' Esperimento n.1 Corso PIC-USB Elettronica-In

'******Dichiarazioni variabili necessarie per uso firmware USB******

wsave VAR BYTE $70 system ' permette di salvare Wssave VAR BYTE bank0 system ' permette di salvare STATUSpsave VAR BYTE bank0 system ' permette di salvare PCLATHfsave VAR BYTE bank0 system ' permette di salvare FSR

'******Dichiarazioni variabili applicazionetemper VAR BYTE 'variabile che conterra il valore proveniente dal modulo A/D

DEFINE OSC 24 ' Clock 24MhzDEFINE SHOW_ENUM_STATUS 1 ' Visualizza lo stato relativo al processo di enumerazione

' su PORTB

' Definizioni per l'utilizzo dell'istruzione ADCINDEFINE ADC_BITS 8 ' Numero di bit nel risultatoDEFINE ADC_CLOCK 3 ' Clock RC TAD=4uS/bit 9,5TAD/byteDEFINE ADC_SAMPLEUS 50 ' Frequenza Campionamento uS

PORTB = 0 ' 8 LED uscite digitali spentiTRISB = 0 ' PORTB definita in uscita

GoTo INIZIO ' Salta al main

' Il gestore Interrupt inizia dalla label BUSINTDEFINE INTHAND BUSINT

AsmBUSINT

movf FSR, W ; salvataggio di FSRmovwf fsavemovlw High ServiceUSBIntmovwf PCLATHbtfsc PIR1, USBIF ; Se non c'è' nessun interrupt da gestire vado a RIPREGCall ServiceUSBInt ; Richiama la routine firmware che gestisce tutti gli

; Interrupt dei moduli USB del PIC

RIPREG ; Ripristino registri salvaticlrf STATUSmovf fsave, Wmovwf FSRmovf psave, Wmovwf PCLATHswapf ssave, Wmovwf STATUSswapf wsave, Fswapf wsave, Wretfie ; Torno al pgm principale

EndAsm

INIZIO: USBInit ' Processo di enumerazione alla fine il device

' entra nello stato Configurato TRISA = %11111111 ' PORTA tutta in ingressoADCON1= 4 ' [DDDDADAA] RA0,RA1 analogici Vdd tensione di rifPause 500 ' Attesa

CONV:Pause 100ADCIN 0, temper ' Campiona segnale su RA0 e metti risultato in tempPause 150USBOut 1, temper, 1, CONV ' Invia risultato sul bus e torna a campionareGoTo CONV ' Continua all'infinito

L I S T A T O 9

>

Page 32: Corso PIC-USB

106 dicembre 2004 / gennaio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

ricordi che il tempo di conversione per ciascunbit (TAD) deve essere di almeno 1,6 µS e che uti-lizzando una frequenza di sistema di 24 MHzl’RC interno ha un TAD di circa 4 µS. Inoltre èbene utilizzare INT/32 o RC come fonte per evi-tare la perdita di precisione dovuta alle esigenzedei moduli USB. Infine si precisa la frequenza dicampionamento (ADC_SAMPLEUS).L’istruzione che opera la conversione è moltosemplice (ADCIN 0,temper), in pratica usa comeparametri il canale dal quale si ricava il segnaleanalogico (0=RA0) e il nome della variabiledove si vuol registrare il risultato (temper).

Tabella9

Attraverso la definizione diSHOW_ENUM_STATUS avremo la possibilitàdi vedere la progressione degli stati del processodi enumerazione sulla PORTB quindi potremocontrollare il funzionamento del dispositivoattraverso i led (Ld1..Ld8) della demoboardsecondo la tabella 9. Se colleghiamo la demoboard dopo aver sostituito il PIC originale conquello contenente il file termousb.hex vedremoche si avvierà la procedura di riconoscimentoPlug and Play di Windows che rileverà il nostrodispositivo come “ThermoUSB PIC-USBCourse” e ci chiederà di inserire il percorso deidriver relativi. Si noti che l’inglese, per il PnPMicrosoft, è il linguaggio predefinito pertanto

vengono visualizzate le stringhe del linguaggio 2del nostro firmware. Procedendo senza sceglierealcuna opzione il sistema si accorgerà che il dis-positivo è un HID e quindi presenterà la scher-mata di figura 1 (questa schermata non appare inwindows XP). Windows, quindi caricherà il dri-ver per periferiche HID. Noteremo che durantequesta procedura si saranno accesi i led 1,2,3 chestanno a significare che il dispositivo è entratonello stato “Indirizzato” ma non è ancora prontoper essere utilizzato. Terminata la procedura diinstallazione ci apparirà la schermata di figura 2(questa schermata non appare in Windows XP).

Fig. 1 Fig. 2

Facendo click su Fine sulla demoboard si accen-derà anche il led 4 e il dispositivo comincerà adinviare dati. Il corretto funzionamento verràsegnalato dall’accensione e dallo spegnimento adintervalli regolari del led 7 che segnala attivitàsull’endpoint 1 (EP1/IN). In pratica ad ogniaccensione il dispositivo rende disponibile ilvalore campionato sul bus eseguendo l’istruzioneUSBOUT. Se apriamo il pannello di controllo diWindows vedremo tra le periferiche il nostro dis-positivo (vedi fig. 3).Utilizzando la routine Leggi-HID che si può sca-ricare dal sito della rivista avrete la possibilità diinterrogare il dispositivo e verificare il funziona-mento di alcuni campi dei descrittori (in partico-

Page 33: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

Elettronica In - dicembre 2004 / gennaio 2005 107

>

Stato “Configurato”

Comunicazione su EP1

TermoUSB con NTC montata

lare l’identificazione device e le stringhe inseri-te). La schermata al termine dell’interrogazioneapparirà come in figura 4. Dopo aver installato ilnostro prototipo e verificato il suo funzionamen-to vediamo un attimo di spiegare un paio di istru-zioni chiave usate nel programma Basic. Nellistato ci sono due istruzioni fondamentali per ilfunzionamento su USB: USBINIT e USBOUT.Partiamo da quest’ultima. Essa permette alnostro dispositivo di rendere disponibile attraver-so l’endpoint1 il valore campionato. La sintassiPicBasic è:- USBOUT Endpoint, Buffer, Count, Label;dove Endpoint è il numero dell’endpoint utiliz-zato (ad es. 2 = EP2); Buffer è la variabile arraycontenente i valori che intendiamo rendere dis-ponibili sul bus; Count è il numero di byte dainviare; Label è l’etichetta alla quale proseguel’esecuzione del codice se il dispositivo nonriesce ad inviare i dati in quanto non risulta anco-ra terminata una trasmissione precedente, tipica-mente si fa ciclare l’istruzione su se stessa pertrasmetterla non appena possibile.Nel nostro caso usiamo un buffer array costituito

da un unico byte (un array povero ma efficace).L’istruzione nella realtà ha dei collegamentimolto stretti con il firmware Microchip perchè

Fig. 3

non fa nient’altro che richiamare la funzionePutEPn che abbiamo visto nel nostro modello astrati. Se analizziamo più da vicino questa fun-zione vedremo che utilizza gli stessi parametridella USBOUT quindi quest’ultima è solo un’in-terfaccia che ci permette un lavoro essenzial-mente più comodo. In particolare PutEpn usa ilregistro W del PIC per il numero di byte da invia-re, FSR e IRP per puntare al blocco di dati dainviare (il nostro buffer). Essa, inoltre, valorizzail Carry Flag per comunicare se la funzione èstata eseguita con successo (CF=1) oppure no(CF=0). Per quanto riguarda USBINIT la sua funzione èquella di avviare il processo di enumerazione eportare il dispositivo allo stato “Configurato”. Inogni sviluppo firmware USB è la prima funzioneche si dovrà chiamare, pena l’impossibilità dicomunicare con il device. Anche qui la situazio-ne non è tanto differente visto che l’istruzionePicBasic è essenzialmente un’interfaccia versol’istruzione firmware InitUSB. In realtà è unavera e propria call visto che non c'è alcun para-metro da passare. Prendiamo in considerazione ora il lato host. labreve routine scritta in Delphi non fa altro cheleggere il dato campionato dal PIC e rappresen-tarlo su una sorta di LCD. Il programma ricerca

Page 34: Corso PIC-USB

108 dicembre 2004 / gennaio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

Fig. 4

il dispositivo e poi legge via via i dati che glivengono messi a disposizione (vedi fig. 5). Utilizzando una NTC con R25=33 kOhm la tara-tura si può effettuare semplicemente ruotandocompletamente il trimmer ATT1 affinché essonon introduca alcuna attenuazione. Inserendo ilponticello SK2 ed avviando il monitoraggioattraverso l’apposito tasto dell’applicazione ilvalore letto è 255. Quindi, si può togliere il pon-ticello ed inserire la NTC. Nel caso si disponga di una NTC con caratteri-stiche differenti si può procedere valorizzando icampi del pannello “Parametri NTC”. In praticabisogna inserire il valore della temperaturamagari rilevato attraverso un termometro classi-co e quello del valore campionato che si puòricavare dalla lista degli ultimi 4 valori ricevuti.Chiaramente bisogna effettuare due rilievi a tem-peratura differente affinché il software possa cal-colare lo scarto per ciascun livello logico.Eventualmente si può agire sul trimmer dellademoboard per adattare i valori campionati.Il sistema è sufficiente dal punto di vista speri-

mentale, anche se non brilla per precisione e sen-sibilità. Se non avete una NTC a disposizionenon c'è’ problema, perchè potete testare il tuttocon ponticello SK2 inserito e ruotando il trimmerATT1, simulando le variazioni di temperatura.Non appena collegate la demoboard il software siaccorge della connessione valorizzando la listadispositivi e i dati del device. Facendo click su“Avvia Monitoraggio” l’host rileverà i dati visua-lizzando la temperatura sul LCD. Si può blocca-re il campionamento facendo click nuovamentesu “Avvia Monitoraggio”. Si noti che i dati rice-

Fig. 5

vuti vengono visualizzati in tempo reale sul pan-nello “Ultimi 4 valori ricevuti”. Analizzeremo illistato in maniera approfondita nella parte delCorso dedicata allo sviluppo lato Host. Bene,anche per questa puntata abbiamo fatto qualchepasso avanti. Nella prossima ritorneremo sulnostro termometro USB analizzando ancora lasua struttura assembler, ed iniziando a capirecome è possibile scambiare dati nella direzioneopposta (da Host a Device). Sfrutteremo la strut-tura delle collection ed introdurremo un altroprototipo con l’esperimento n.2. Alla prossima.

Page 35: Corso PIC-USB

ell’ultima puntata abbiamo descritto undispositivo che permette il monitoraggio

della temperatura ambientale attraverso una resi-stenza NTC. Riprendiamo il discorso sofferman-doci su alcuni importanti aspetti del firmware.

TermoUSB un’analisi più approfondita

Nel listato 1 sono state evidenziate le parti delsorgente che sono necessarie per la corretta inte-grazione con il firmware USB di Microchip.Tutte le modifiche per implementare i nostri pro-totipi verranno fatte mantenendo intatta questastruttura pena l’impossibilità di utilizzare le fun-zioni USBOUT, USBIN, USBINIT di PicBasic.Nella parte evidenziata c’è ancora un’istruzioneche avevamo lasciato da parte: ServiceUSBInt. Si tratta di una routine ISR (Interrupt ServiceRoutine) del firmware Microchip che gestiscetutti i segnali di interrupt provenienti dai moduliUSB. Si noti che essa viene richiamata solo dopoaver verificato la valorizzazione del flag USBIFdel registro PIR (Peripheral Interrupt Register).

Se vogliamo inserire una nostra routine di gestio-ne di un altro interrupt dovremo mettere il codi-ce relativo proprio in questo punto attraversoun’istruzione btfsc (bit test f, skip if clear) sulflag che ci interessa seguito dalla call alla proce-dura che abbiamo sviluppato. Dopo l’esecuzioneil programma continuerà con la label RipREGche non fa altro che ripristinare tutti quei valoriche possono essere stati influenzati dalla gestio-ne dell’interrupt. Una volta che il flag USBIF è a1, viene richiamata ServiceUSBInt. Se andiamoa vedere il suo codice che si trova inUSB_ch9.asm ci accorgiamo che essa effettuaun’ulteriore discriminazione andando ad analiz-zare un altro registro UIR (USB Interrupt FlagsRegister). Il “cuore” del firmware Microchip èpresentato nel listato 2.Al suo interno troviamo una serie di ulteriori flagper identificare il tipo di segnale interrupt USBgenerato. Ad esempio troviamo il bit USB_RST(bit 0 di UIR) che, se valorizzato, indica la pre-senza del segnale di reset sul bus. L’UIR vienecontrollato sulla base della configurazione di un

Elettronica In - febbraio 2005 83

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

4AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittàà UUSSBBiimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorriiddeellllaa MMiiccrroocchhiipp..UUnn aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittàà iinn ccoonnssiiddeerraazziioonnee ddeellllaa ccrreesscceenntteeiimmppoorrttaannzzaa ddii qquueessttaa aarrcchhiitteettttuurraa nneellllaaccoommuunniiccaazziioonnee ttrraa ccoommppuutteerr eeddiissppoossiittiivvii eesstteerrnnii.. IInn qquueessttoo qquuaarrttooaappppuunnttaammeennttoo aapppprrooffoonnddiiaammoo aallccuunniiaassppeettttii ddeell ffiirrmmwwaarree iimmpplleemmeennttaattoo nneellssiisstteemmaa ddii mmoonniittoorraaggggiioo ddii tteemmppeerraattuurraapprreesseennttaattoo nneellllee ppuunnttaattee pprreecceeddeennttii..

a cura di Carlo Tauraso

Page 36: Corso PIC-USB

CCoorrssoo PPIICC--UUSSBB

84 febbraio 2005 - Elettronica In

altro registro chiamato UIE (USB InterruptEnable Register). Questo registro ha un flag diabilitazione per ciascuno dei possibili segnali diinterrupt. Se il flag è valorizzato a 1, il relativosegnale verrà rilevato, altrimenti no (maschera-mento degli interrupt). Una volta controllato ilregistro UIR, la routine richiama l’esecuzionedel codice di gestione opportuno a seconda del-l’interrupt rilevato. Il file USB_ch9.asm permet-

te di analizzare l’implementazione delle funzio-nalità offerte dal firmware Microchip. Nel para-grafo che riguarderà la personalizzazione delfirmware agiremo direttamente su questo file pervenire incontro alle nostre esigenze. Se, invece,qualcuno ha la curiosità di vedere come sianoimplementate in assembler le operazioni BasicUSBOUT e USBIN deve riferirsi al fileusb_defs.inc. Prendiamo ad esempio l’istruzione

' Programma TERMOMETRO USB' Esperimento n.1 Corso PIC-USB Elettronica-In

'******Dichiarazioni variabili necessarie per uso firmware USB******

wsave VAR BYTE $70 system 'permette di salvare Wssave VAR BYTE bank0 system 'permette di salvare STATUSpsave VAR BYTE bank0 system 'permette di salvare PCLATHfsave VAR BYTE bank0 system 'permette di salvare FSR

'******Dichiarazioni variabili applicazionetemper VAR BYTE 'variabile che conterra il valore proveniente dal modulo A/D

DEFINE OSC 24 ' Clock 24MhzDEFINE SHOW_ENUM_STATUS 1 ' Visualizza lo stato relativo al processo di enumerazione

' su PORTB' Definizioni per l'utilizzo dell'istruzione ADCINDEFINE ADC_BITS 8 ' Numero di bit nel risultatoDEFINE ADC_CLOCK 3 ' Clock RC TAD=4uS/bit 9,5TAD/byteDEFINE ADC_SAMPLEUS 50 ' Frequenza Campionamento uS

PORTB = 0 ' 8 LED uscite digitali spentiTRISB = 0 ' PORTB definita in uscita

GoTo INIZIO ' Salta al main

' Il gestore Interrupt inizia dalla label BUSINTDEFINE INTHAND BUSINT

AsmBUSINT

movf FSR, W ;salvataggio di FSRmovwf fsavemovlw High ServiceUSBIntmovwf PCLATHbtfsc PIR1, USBIF ;Se non c'e' alcun interrupt da gestire vado a RIPREGCall ServiceUSBInt ;Richiama la routine firmware che gestisce tutti gli

;Interrupt dei moduli USB del PIC

RIPREG ;Ripristino registri salvaticlrf STATUSmovf fsave, Wmovwf FSRmovf psave, Wmovwf PCLATHswapf ssave, Wmovwf STATUSswapf wsave, Fswapf wsave, Wretfie ; Torno al pgm principale

EndAsm

INIZIO: USBInit ' Processo di enumerazione alla fine il device

' entra nello stato Configurato TRISA = %11111111 ' PORTA tutta in ingressoADCON1= 4 ' [DDDDADAA] RA0,RA1 analogici Vdd tensione di rifPause 500 ' Attesa

CONV:Pause 100ADCIN 0, temper 'Campiona segnale su RA0 e metti risultato in tempPause 150USBOut 1, temper, 1, CONV 'Invia risultato sul bus e torna a campionareGoTo CONV ' Continua all'infinito

L I S T A T O 1

Page 37: Corso PIC-USB

PutUSB1movwf GPtemp ; save Bytecount temporarily in common RAM

movf STATUS,w ; save bank bits before we trash thembanksel RP_save ; switch to bank 2movwf RP_save

movf GPtemp,wandlw 0x0F ; extract byte count.movwf counter

movf FSR,wmovwf source_ptr

movf counter,w ; prepare to copy the byte countbanksel BD1IST ; bank 3pagesel nobufferputep1btfsc BD1IST,UOWN ; is the buffer already full?goto nobufferputep1 ; yes - don't write over it

movwf BD1IBC ; set byte count in BDpagesel exitputloopbtfsc STATUS,Z ; is it a zero length buffer?goto exitputloop ; yes, bail out now and avoid the rushmovf BD1IAL,w ; get address pointerbcf STATUS,RP0 ; back to bank 2movwf dest_ptr

..............

..............Loop scaricamento dati nel buffer puntato

..............

exitputloopbsf STATUS,RP0 ; back to bank 3movf BD1IST,w

L I S T A T O 4

Elettronica In - febbraio 2005 85

>

CCoorrssoo PPIICC--UUSSBB

USBOUT che abbiamo utilizzato in questoprimo esperimento. Nel file USB_ch9.asm vienecreata un’istanza per le funzioni PUTEP1 ePUTEP2 che non sono altro che delle macrodefinite nel file usb_defs.inc. (vedi listato 3 e 4).

Per capirne il funzionamento bisogna considera-re che il PIC16C745 per gestire al meglio lacomunicazione sugli endpoints utilizza unatabella chiamata BDT (Buffer Descriptor Table)che riserva a ciascuno di essi 4 bytes. Ciascun

ServiceUSBIntbanksel UIRmovf UIR,w ; get the USB interrupt registerandwf UIE,w ; mask off the disabled interruptsbcf STATUS, RP0 ; BANK 2pagesel ExitServiceUSBIntbtfsc STATUS,Z ; is there any unmasked interrupts?goto ExitServiceUSBInt; no, bail out...............Lista di Interrupt con le Call relative.......

ExitServiceUSBIntbanksel PIR1bcf PIR1,USBIFreturn

L I S T A T O 2 USB Interrupt Flag Register

USB Interrupt Enable Register

; **********************************************************************PUTEP1 ; create instance of PUTEP1PUTEP2 ; create instance of PUTEP2

; *********************************************************************

L I S T A T O 3

Questa funzione ha in ingresso uncounter per il numero di byte dainviare in w e un puntatore all'areacontenente i dati da trasmettere inFSR+IRP.

Verifica se il buffer descriptorstatus register per l'endpoint 1 IN,risulta libero, vedi sistema asemafori nelle righe di spiegazioneseguenti.

Ecco il buffer descriptor bytecounter per l'endpoint 1 IN, qui il firmware mette il numero dibyte da inviare.

Ogni record della Buffer DescriptorTable punta attraverso il bufferdescriptor address low ad un buffernella memoria del PIC che contienei dati da inviare. Questa funzioneprende tale valore proprio da questo registro, sempre per l'endpoint 1 IN, e lo gira a w.

Peripheral Interrupt Register

Aprendo quest’ultimo file troviamo le istruzioni relative dopo la label PutUSB1.

Page 38: Corso PIC-USB

86 febbraio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

record è condiviso tra l’MCU (processore+firm-ware) e l’USB (SIE: Serial Interface Engine)pertanto si utilizza un ingegnoso sistema a sema-fori. In pratica la tabella contiene un bit dettoUOWN (deriva da owned) che stabilisce chidetiene il diritto di accedere ai record. Si dice cheil record è posseduto (owned by) dall’interfacciaUSB quando il bit è a 1. Quando è 0 soltanto ilprocessore e quindi il relativo firmware possonoaccedervi. Naturalmente quando il record è pos-seduto da uno dei due contendenti, l’altro deveaspettare il suo turno. I 4 byte sono composti dadue registri di stato (BDndST), un contatore deibyte da inviare (BDndBC), ed infine un registroche contiene l’indirizzo di base del buffer dovesono conservati i dati da inviare (BDndAL).Nei nomi “nd” sta per number e direction quindiBD1IST è il registro di stato per l’endpoint 1 inINPUT. Si ricordi che ogni endpoint è caratteriz-zato sempre da un numero e una direzione. Ognirecord punta attraverso BDndAL ad un’areanello spazio di indirizzamento del processore(precisamente sul banco 3 nel range 1B8h -1DFh). Nel momento in cui si chiama laPUTEP1 viene verificato il bit OWN per il regi-stro di stato BD1IST. Se è a 0 viene valorizzatoil BD1IBC, con il counter passato in w vieneletto il BD1IAL per puntare al buffer di destina-zione e si avvia un ciclo che porta i dati puntatida FSR+IRP all’area puntata dal BD1IAL.Terminato il ciclo viene messo il bit OWN a 1per rilasciare il lock del buffer in maniera che ilcontroller USB possa accedervi (in particolare lofarà l’applicazione host). Infine viene valorizza-to il bit di Carry come valore in uscita: 1=tuttoOK, il buffer è disponibile, 0=il buffer è occupa-to, bisogna riprovare in un secondo momento. A questo punto il listato del nostro termometroUSB ha svelato quasi ogni suo segreto. Vediamoquindi di passare al nostro secondo esperimentonel quale sfrutteremo le potenzialità di pilotaggio

PWM del PIC16C745. Costruiremo, in particola-re, un controller PWM per piccoli motori DCgestito tramite interfaccia USB. In questo modopotremo affrontare una nuova parte di sviluppofirmware che riguarda la ricezione di dati di con-trollo del nostro device. Credo sia chiaro l’inten-to didattico. Mentre con la prima esperienzaabbiamo inviato dati verso l’host ora dobbiamocapire anche come si puo’ fare l’operazioneinversa. In particolare, in questo caso, utilizzere-mo una coppia di dati che ci permetteranno diprecisare la velocità di rotazione e l’intervallo ditempo di accensione.

Esperimento n.2 PWM-USB.

Sulla nostra demoboard abbiamo già disponibilidue belle uscite PWM (connettori PWM1 ePWM2) in grado di erogare però una correntemassima di 100mA / 40V. Ciò comporta unalimitazione nella scelta del carico da utilizzare.Per questa esperienza utilizzeremo un piccolomotore a 12V/100mA che può essere tranquilla-

andlw 0x40 ; save only the data 0/1 bitxorlw 0x40 ; toggle the data o/1 bitiorlw 0x88 ; set owns bit and DTS bitmovwf BD1ISTbanksel RP_savemovf RP_save,w ; restore bank bits the way we found themmovwf STATUSbsf STATUS,C ; set carry to show successreturn

nobufferputep1bcf STATUS,Creturnendm

(continuazione del listato 4)Dopo aver caricato il buffer mette ilbit OWN a 1 in maniera da rendere ilbuffer disponibile al controller USB.

Valori di uscita di questa funzione ilbit di Carry viene messo a 1 se tuttele operazioni sono andate a buonfine ed il buffer è pronto per essereletto dall'USB. Altrimenti è a 0.

Fig. 1

Page 39: Corso PIC-USB

Elettronica In - febbraio 2005 87

>

CCoorrssoo PPIICC--UUSSBB mente controllato dai transistor driver (BC337)

della nostra demoboard. Dovendo alimentaremotori con esigenze più elevate si possono inse-rire dei MOSFET come l’IRZ44 (www.irf.com)che arrivano a veicolare correnti decisamentemaggiori (senza particolari accorgimenti si rag-giungono i 7-8A con tensioni max di 60V). Nelnostro caso abbiamo voluto ridurre al minimol’intervento “hardware” per poterci concentraresulle problematiche software, vero obiettivo diquesto corso.E’ doveroso iniziare con una breve premessa sulpilotaggio PWM (Pulse Width Modulation).Dovendo controllare la velocità di rotazione diun motore in continua si può variare la tensioneapplicata collegando in serie una resistenza. Ma,se il carico del motore aumenta, aumenterà anchela richiesta di corrente che comporterà un ulte-riore caduta di tensione sulla resistenza e quindiminor tensione ai terminali del motore.Quest’ultimo tenterà di assorbire ancor più cor-rente e alla fine si fermerà. Attraverso il PWM,invece, si simula una sorgente di tensione varia-bile inviando degli impulsi al motore e variando-ne la lunghezza per modificarne la velocità dirotazione. In pratica quanto più gli impulsi sono“lunghi” tanto più veloce girerà il nostro motoree viceversa. Lo si vede chiaramente in figura 1dove la larghezza degli impulsi va a decrescere.Si consideri che il nostro motore non riesce adaccorgersi del fatto che noi furbescamente glistacchiamo l’alimentazione anche perchè siamodecisamente rapidi nel farlo, il nostro PIC infattiè in grado di generare segnali dell’ordine dei20KHz. Il carico “crederà” quindi di essere ali-

mentato da una sorgente di tensione variabile.C’è però un altro problema dovuto all’induttan-za. L’avvolgimento del motore è in pratica uninduttore, cioè qualcosa che tende a mantenerecostante la corrente che vi scorre. Quando ilnostro impulso è in discesa la corrente è costret-ta a variare repentinamente verso il basso mal’induttore fa si che ciò non avvenga tendendo afar salire la tensione sul collettore del transistordriver. Si crea cioè un picco chiamato “Fly-Back” che può danneggiare seriamente il driver.Inserendo in parallelo all’avvolgimento delmotore un diodo di ricircolo si offre una viaalternativa alla corrente che anzichè passare peril prezioso transistor fluisce attraverso il piùrobusto diodo. Il circuito risultante è immediatoe lo si può vedere in figura 2.Il funzionamento è presto detto. Il segnale PWMproveniente dal pin RC2 viene trasferito alla basedel transistor T1 attraverso la resistenza R15. Adogni impulso proveniente dal PIC, il transistor siporta in conduzione agendo come un vero e pro-prio interruttore.Attraverso il software host invieremo al devicedue valori: uno relativo alla percentuale di “duty-cycle” e l’altro pari al numero di impulsi dainviare.Il device modulerà la larghezza degli impulsi aseconda del primo valore e farà variare il nume-ro di giri del motore, in secondo luogo creerà deitreni di impulsi lunghi quanto il secondo valoremodificando il tempo di accensione.A questo punto non ci resta che connettere ilnostro motore alla demoboard e alla sorgente dialimentazione stabilizzata come nello schema.

Fig. 2

Terminale + Motore —> +12 v alimentatore est.Terminale - Motore —> PWM1 DemoboardTerminale - Alimentatore —> GND Demoboard

Passiamo quindi allo sviluppo software. Questavolta non andremo a ripercorrere la formazionedi tutti i descrittori ma prendendo ad esempio illistato precedente ci soffermeremo sulle modifi-che necessarie. Inanzitutto analizziamo l’utilizzodegli endpoint.

Analisi degli endpoints

In questo caso dovremo realizzare un dispositivoche principalmente agisce come ricettore dicomandi, pertanto questa volta aggiungeremo unaltro endpoint 1 con direzione OUT. Si ricordi,

Page 40: Corso PIC-USB

88 febbraio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

>

che le direzioni sono sempre rispetto all’host inquanto ci troviamo in un sistema centrato su que-st’ultimo. Per quanto riguarda invece i campi iningresso (vedi descrittore report) sarà necessariopredisporne due: un byte servirà per stabilire il“duty cicle” dell’impulso PWM e l’altro invecestabilirà il numero di “cicli” da effettuare quindile ripetizioni che formano il treno di impulsi. Ilprimo ci permetterà di regolare la velocità dirotazione con 256 possibili valori (0=0%-255=100%). Il secondo, invece, ci permetterà distabilire l’intervallo di accensione del motore.Bisogna tener presente che la durata del ciclodipende dalla frequenza dell’oscillatore utilizza-to dal PIC, in generale utilizzando una frequenzadi 24MHz la durata di ciascun ciclo si attestaintorno ad 1ms (0,83 ms). Noi utilizzeremo comeintervallo minimo 5 sec e max 255*5 sec cioè 21

minuti. Naturalmente possiamo anche pensare diutilizzare più byte (uno low e uno high) perimpostare intervalli più elevati. Per i nostri scopiperò credo che sia sufficiente così.

Descrittore Endpoint

Questa volta partiremo direttamente dalle modi-fiche necessarie al listato senza soffermarci sulledefinizioni di ciascun descrittore. Innanzituttonel descrittore Interface dobbiamo modificare ilvalore bNumEndpoints da 1 a 2 visto che utiliz-zeremo EP1IN e EP1OUT. I descrittori device,configuration e hid si possono tranquillamentemantenere identici visto che stiamo definendo undispositivo hid con una sola configurazione edinterfaccia. Vediamo nel concreto quali sono lemodifiche da effettuare nella tabella del descrit-tore Endpoint:Nel file PWMDSC.ASM inseriremo nella sezio-ne TABELLA 1 - DESCRITTORE ENDPOINTle istruzioni riportate nel listato 5 in corrispon-denza della label di inizio del secondo descritto-re (Endpoint2). Si faccia attenzione al fatto chein questo caso abbiamo definito due endpoint didimensioni diverse. Uno in uscita di 1 byte eduno in entrata di 2 byte. Il valorewMaxPacketSize è piuttosto importante perchèstabilisce la quantità di dati che possiamo scam-

Tabella 1 - DDeessccrriittttoorree EENNDDPPOOIINNTT

retlw 0x07 ; bLengthretlw ENDPOINT ; bDescriptorTyperetlw 0x01 ; bEndpointAddressretlw 0x03 ; bmAttributesretlw 0x02 ; wMaxPacketSize (low-b)retlw 0x00 ; wMaxPacketSize (high-b)retlw 0x0A ; bInterval

L I S T A T O 5

Page 41: Corso PIC-USB

Elettronica In - febbraio 2005 89

CCoorrssoo PPIICC--UUSSBB Tabella 2 - DDeessccrriittttoorree RREEPPOORRTT

retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage Page (low-b) ("Vendor Defined Page 1")retlw 0xFF ; Usage Page (high-b) ("Vendor Defined Page 1")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage ("Vendor Defined Usage 1")retlw 0xA1 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Collection ("Application")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage ("Vendor Defined Usage 2")retlw 0xA1 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Collection ("Physical")retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage Page (low-b) ("Vendor Defined Page 2")retlw 0xFF ; Usage Page (high-b) ("Vendor Defined Page 2")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x03 ; Usage ("Vendor Defined Usage 3")retlw 0x15 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Logical Minimum (0)retlw 0x26 ; Byte di prefisso (bTag,bType,bSize)retlw 0xFF ; Logical Maximum (low-b) (255)retlw 0x00 ; Logical Maximum (high-b) retlw 0x75 ; Byte di prefisso (bTag,bType,bSize)retlw 0x08 ; Report Size (8 bits)retlw 0x95 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Report Count (1 campo dati)retlw 0x81 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Input (Data, Var, Abs)retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x04 ; Usage ("Vendor Defined Usage 4")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x05 ; Usage ("Vendor Defined Usage 5")retlw 0x15 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Logical Minimum (0)retlw 0x26 ; Byte di prefisso (bTag,bType,bSize)retlw 0xFF ; Logical Maximum (low-b) (255)retlw 0x00 ; Logical Maximum (high-b) retlw 0x75 ; Byte di prefisso (bTag,bType,bSize)retlw 0x08 ; Report Size (8 bits)retlw 0x95 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Report Count (2 campo dati)retlw 0x91 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Output (Data, Var, Abs)retlw 0xC0 ; End Collection ("Physical")retlw 0xC0 ; End Collection ("Application")

L I S T A T O 6

Evidenziate in rosso le modificherispetto al descrittore report usatoper il termoUSB.

Page 42: Corso PIC-USB

90 febbraio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

biare con l’host attraverso l’istruzione USBIn. Sequi avessimo utilizzato il valore di 1 byte sarem-mo stati costretti a richiamare due volte la stessaistruzione per reperire i due campi dati. In questomodo, invece, possiamo lavorare direttamentecon un buffer lungo 2 byte che registrerà entram-bi i valori attraverso un’unica istruzione.

Descrittore Report

Passiamo quindi al descrittore report. Se consi-deriamo la struttura dell’altra volta possiamosfruttare le collection create inserendo diretta-mente prima della end collection Physical ladefinizione relativa a due ulteriori usage che ser-viranno per i due byte relativi al controllo delmotore da parte dell’host (velocità e durata). Siha quello riportato in tabella 2. Il descrittorereport completo diventerà come riportato nellistato 6.

Come si vede l’utilizzo delle collection rendel’integrazione del report decisamente semplice.Si noti come in questo caso abbiamo realizzatouna struttura che descrive una comunicazione sutre campi, uno in ingresso e due in uscita.

Descrittore String

Per quanto riguarda la parte string le modifichesono immediate. Le lingue utilizzate sono sem-pre due: Italiano e Inglese. Dobbiamo solo inse-rire la descrizione relativa al prodotto “PWM-USB Corso PIC-USB”, il suo numero seriale“EXP.2” e l’interfaccia “EP1/INOUT” nella ver-sione italiana ed inglese. Nel listato 7 è riportatoil codice relativo al solo nome del prodotto ita-liano. Arrivati a questo punto il nostro nuovo descritto-re è creato. Ci si ricordi di effettuare la solitamodifica nel file USBDESC.ASM inserendo

String2_l1 ; iProduct ("PWM-USB Corso PIC-USB")retlw String3_l1-String2_l1 ; bLengthretlw 0x03 ; bDescriptorTyperetlw 'P' ; bString retlw 0x00retlw 'W'retlw 0x00retlw 'M'retlw 0x00retlw '-'retlw 0x00retlw 'U'retlw 0x00retlw 'S'retlw 0x00retlw 'B'retlw 0x00retlw ' 'retlw 0x00retlw 'C'retlw 0x00retlw 'o'retlw 0x00retlw 'r'retlw 0x00retlw 's'retlw 0x00retlw 'o'retlw 0x00retlw ' 'retlw 0x00retlw 'P'retlw 0x00retlw 'I'retlw 0x00retlw 'C'retlw 0x00retlw '-'retlw 0x00retlw 'U'retlw 0x00retlw 'S'retlw 0x00retlw 'B'retlw 0x00

L I S T A T O 7

Page 43: Corso PIC-USB

Elettronica In - febbraio 2005 91

>

CCoorrssoo PPIICC--UUSSBB

l’include relativa al file appena creato. Per ren-dere le cose più agevoli si commenti la riga delprecedente esperimento aggiungendone un’altraper quello attuale. In questo modo sarà sufficien-te eliminare il “;” per scegliere quale include fareseguire. Il file diventa come descritto nel listato8. Il descrittore appena creato si può testare conla routine Leggi-HID, naturalmente bisognaprima scrivere un .bas fittizio cioè che non faassolutamente niente se non richiamare USBInitper realizzare il processo di enumerazione. Se lecose vanno per il verso giusto la form dell’appli-cativo dovrebbe presentarsi come in figura 3.

PWM-USB Codice Basic

sari al funzionamento del motore cioè velocità etempo di accensione, una variabile word (tempo)che permetterà il calcolo del tempo in millise-condi ed infine una variabile per il conteggio deibyte ricevuti dal device. Nella comunicazionecon l’host il parametro relativo al tempo diaccensione è codificato secondo intervalli di 5secondi. In pratica se si decide di mantenereacceso il motore per 15 sec, l’host invierà perquesto parametro un valore pari a 3. In secondoluogo sul form dell’applicazione PWMhost.exe(scaricabile dal sito della rivista...) si potrà sce-gliere il duty-cycle facendo riferimento ad unapercentuale (da 0 a 100%), mentre i dati inviatisaranno codificati secondo 255 livelli discreti. Inpratica il 10% corrisponde al livello 26 (precisa-mente sarebbe pari a 25,5 c’è un arrotondamentoper eccesso). Per capire bene il funzionamentodel codice dobbiamo analizzare le due istruzionichiave: PWM e USBIN.La sintassi dell’istruzione PWM è la seguente:PWM Pin,Duty,CycleIl Pin è quello dal quale prendiamo l’impulsoPWM risultante e si può precisare sia attraversouna costante (0-15), sia attraverso una variabilecontenente un valore compreso tra 0 e 15, oppu-re utilizzando il nome di un pin appartenente ad

; include "termodsc.asm" ; Descrittori TermoUSB-Esperimento 1include "PWMdsc.asm" ; Descrittori PWM-USB-Esperimento 2

L I S T A T O 8

Nel listato basic, in pratica, viene creata unasorta di interfaccia della funzione Basic PWM.L’host, infatti invierà sull’endpoint 1 OUT duebyte che corrispondono esattamente a due deiparametri necessari all’utilizzo di tale funzione.L’ultimo parametro da valorizzare è quello delpin della porta utilizzata dal PIC per inviare l’im-pulso. Utilizziamo il connettore PWM1 dellademoboard quindi sfrutteremo l’RC2 cioè il pin2 della PORTC. Per questa esperienza non utiliz-zeremo l’endpoint 1 IN, che invece riprenderemonel prossimo esperimento che ci permetterà diapprezzare la potenzialità della comunicazionebidirezionale su USB. Vediamo nel concreto illistato Basic risultante (listato 9).Se lo confrontiamo con il listato del termoUSBvediamo che viene mantenuta la struttura neces-saria all’integrazione con il firmware diMicrochip. Definiamo una variabile buffer di duebyte (param) che conterrà i due parametri neces-

Fig. 3

Page 44: Corso PIC-USB

92 febbraio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

una delle porte del PIC. Noi abbiamo scelto pro-prio quest’ultima possibilità precisando il pinrelativo al morsetto PWM1, se avessimo volutoutilizzare PWM2, avremmo dovuto precisareRC1 cioè PORTC.1. Il Duty-Cycle è selezionabi-le attraverso un valore compreso tra 0 (0%) e 255(100%). Nel nostro caso utilizziamo il valoreregistrato nella prima cella del buffer “param”che corrisponde al primo valore passato nellasequenza proveniente dall’host. Infine, Cycledetermina la lunghezza del treno di impulsiovvero rappresenta il numero di volte per cui ilciclo PWM viene ripetuto. Considerando che conun oscillatore di 4MHz ogni ciclo dura circa5ms, e che sulla demoboard utilizziamo una fre-quenza di 24MHz vediamo che il nostro cicloavrà una durata di poco inferiore ad 1 ms (0,83).Pertanto, il valore trasmesso dall’host (numero di

intervalli di 5sec) viene moltiplicato per 5460 percalcolare il numero di cicli da circa 1 ms neces-sari a far accendere il motore per il tempo preci-sato. Naturalmente si commette un errore nonproprio trascurabile (si perde 1 sec ogni 10), peròsiamo giustificati dal fatto che stiamo solo facen-do un po’ di esperienza. Per quanto riguarda l’i-struzione che utilizziamo per comunicare attra-verso l’interfaccia USB la sua sintassi è:USBIN Endpoint,Buffer,Countvar,LabelIl parametro Endpoint permette di stabilire qualeEndpoint si vuole utilizzare per la comunicazio-ne. Nel nostro caso si utilizza l’endpoint 1 OUT.Il buffer è l’array che dovrà contenere i dati pro-venienti dall’host e quindi deve essere dimensio-nato a seconda di quanto abbiamo stabilito neidescrittori. Noi utilizziamo una lunghezza di 2byte sufficiente a registrare la velocità di rotazio-

' Programma CONTROLLER PWM-USB' Esperimento n.2 Corso PIC-USB Elettronica-In'******Dichiarazioni variabili necessarie per uso firmware USB******wsave VAR BYTE $70 system 'permette di salvare Wssave VAR BYTE bank0 system 'permette di salvare STATUSpsave VAR BYTE bank0 system 'permette di salvare PCLATHfsave VAR BYTE bank0 system 'permette di salvare FSR'******Dichiarazioni variabili applicazioneparam VAR BYTE[2] 'velocità di rotazione + tempo di accensioneconta VAR BYTE 'contatore byte ricevutitempo VAR WORD 'variabile per calcolo tempo di accensioneDEFINE OSC 24 ' Clock 24MhzDEFINE SHOW_ENUM_STATUS 1 ' Visualizza lo stato relativo al processo di enumerazione

' su PORTBPORTB = 0 ' 8 LED uscite digitali spentiTRISB = 0 ' PORTB definita in uscita

GoTo INIZIO ' Salta al main' Il gestore Interrupt inizia dalla label BUSINTDEFINE INTHAND BUSINTAsmBUSINT

movf FSR, W ;salvataggio di FSRmovwf fsavemovlw High ServiceUSBIntmovwf PCLATHbtfsc PIR1, USBIF ;Se non c'e' nessun interrupt da gestire vado a RIPREGCall ServiceUSBInt ;Richiama la routine firmware che gestisce tutti gli

;Interrupt dei moduli USB del PIC RIPREG ;Ripristino registri salvati

clrf STATUSmovf fsave, Wmovwf FSRmovf psave, Wmovwf PCLATHswapf ssave, Wmovwf STATUSswapf wsave, Fswapf wsave, W

retfie ; Torno al pgm principaleEndAsmINIZIO:

USBInit ' Processo di enumerazione alla fine il device' entra nello stato Configurato

Pause 200 ' AttesaASCOLTA:

USBIN 1,param,conta,ASCOLTA 'Ricezione parametri da hosttempo = param[1]*5460 'ogni livello di param[1]=5secPWM PORTC.2,param[0],tempo 'Inviamo l'impulso PWMGoTo ASCOLTA 'Continua all'infinito

L I S T A T O 9

Page 45: Corso PIC-USB

Elettronica In - febbraio 2005 93

ne e il tempo di accensione. Countvar è unavariabile contatore da 1 byte che permette di con-servare il numero di byte ricevuti dall’host.Infine, la label finale è l’etichetta dove l’esecu-zione si sposta quando i dati in ricezione nonsono ancora disponibili. Noi, in pratica, cicliamosull’istruzione principale finchè tutti i dati che ciservono non sono arrivati sul device. Appena idati sono stati ricevuti il PIC esegue l’istruzionePWM dopo aver ricalcolato il numero di cicli.Anche questa volta abbiamo utilizzato la defineSHOW_ENUM_STATUS per poter monitorareattraverso i leds della demoboard il funziona-mento del nostro prototipo. Noteremo che quan-

do inviamo i due byte ci sarà una rapida accen-sione del led7 che ci avverte dell’attività del-l’endpoint1 OUT. Subito dopo vedremo il ledPWM1 che si accenderà con un’intensità propor-zionale al duty-cycle definito. Anche in questocaso non siamo costretti a disporre di componen-

ti aggiuntivi per vedere se il nostro sistema fun-ziona. Per chi ha voluto invece realizzare com-pletamente questo esperimento, vedrà che all’au-mentare del duty-cycle il motore aumenterà lavelocità di rotazione. Un progetto di unione tra idue esperimenti può essere quello di fare inmodo che il dispositivo esegua il monitoraggiodella temperatura e, raggiunto un valore disoglia, attivi il motore (sul quale avremo posizio-

CCoorrssoo PPIICC--UUSSBB

Fig. 3

Fig. 4

Fig. 5

Accensione tramite PWM1

nato una piccola ventola per la dissipazione) eriporti quindi la temperatura al di sotto dellasoglia definita. In particolare si potrebbe regola-re la velocità di rotazione a seconda della diffe-renza di temperatura da compensare. Un sistemadel genere è stato realizzato su alcuni PC portati-li per regolare il flusso d’aria sul dissipatore delprocessore. Per quanto riguarda il software lato host, abbia-mo realizzato un’applicazione in Delphi (scari-cabile dal sito della rivista) che permette di sce-gliere i valori da inviare al dispositivo attraversopochi clic. La form principale - inviando unimpulso al 65% per 5 secondi - si presenta comein figura 5. L’utilizzo è decisamente semplice. Siimpostano i valori relativi alla velocità ed altempo d’accensione attraverso il pannello“Controllo Motore” per poi inviarli all’host attra-verso il pulsante “Invia Dati”. Si può controllareuna rappresentazione dell’impulso nel diagram-ma di destra. Durante il periodo di accensione ilbottone “Invia Dati” viene disabilitato per evita-re ulteriori trasmissioni. Sul pannello “Ultimivalori” si vedranno i valori immessi sul bus. Inquesto caso 166 è il livello logico corrisponden-te al 65% (65*2,55) mentre 1 è il numero diintervalli di 5 sec per il tempo d’accensione.Anche in questo caso il sistema è pienamentehot-swap in quanto si può connettere e discon-nettere il dispositivo a run-time: il pannello “ID-Dispositivo” verrà aggiornato automaticamente. Anche per questo mese siamo giunti al termine;nella prossima puntata analizzeremo in dettaglioil firmware del PWM-USB così come abbiamofatto per il Termo-USB. Introdurremo anche unaltro esperimento che sfrutterà un sistema dicomunicazione bidirezionale. Appuntamentodunque al fascicolo di marzo.

Page 46: Corso PIC-USB

ella precedente puntata abbiamo presentatoun dispositivo in grado di controllare un

piccolo motore attraverso impulsi PWM.

PWM-USB: il "dietro le quinte"

Analizziamo ora il codice che sta dietro

l'istruzione Basic USBIN, che abbiamo utilizza-to per ricevere i dati relativi alla velocità e altempo d'accensione. Dobbiamo riferirci, come alsolito, al file USB_ch9.asm, all'interno del qualeviene creata un'istanza per le funzioni GETEP1 eGETEP2; altro non sono che delle macro (diseguito riportate) definite nel file “usb_defs.inc”.

Elettronica In - marzo 2005 83

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

5AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittàà UUSSBBiimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorriiddeellllaa MMiiccrroocchhiipp.. UUnn aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittàà iinn ccoonnssiiddeerraazziioonneeddeellllaa ccrreesscceennttee iimmppoorrttaannzzaa ddii qquueessttaa aarrcchhiitteettttuurraa nneellllaa ccoommuunniiccaazziioonnee ttrraaccoommppuutteerr ee ddiissppoossiittiivvii eesstteerrnnii..IInn qquueessttoo qquuiinnttoo aappppuunnttaammeennttoo aannaalliizzzziiaammoo llaa ccoommuunniiccaazziioonnee bbiiddiirreezziioonnaallee ttrraa PPCC ee uunn ddeevviiccee UUSSBBpprrooppoonneennddoo uunn ssiisstteemmaa cchhee ppeerrmmeettttaa ddiicciiffrraarree uunn tteessttoo ssccrriittttoo ssuu PPCC,, ssffrruuttttaannddoollee ccaappaacciittàà ddii ccaallccoolloo ddeell nnoossttrroo PPIICC..

a cura di Carlo Tauraso

; **********************************************************************GETEP1 ; create instance of GETEP1 ; create instance of GETEP1GETEP2 ; create instance of GETEP2 ; create instance of GETEP2

; *********************************************************************

GetUSB1movf STATUS,w ; save bank bits before we trash thembanksel RP_save ; switch to bank 2movwf RP_save

movf FSR,wmovwf dest_ptr ; save the buffer destination pointer

banksel BD1OST ; bank 3pagesel nobufferbtfsc BD1OST,UOWN ; Has the buffer been filled?

L I S T A T O 1

M A C R O D E L F I L E U S B _ D E F S . I N C

La funzione prende in ingressoFSR+IPR come puntatore al bufferdove verranno registrati i dati ricevuti.

Verifica bit OWN per il registroBD1OST (Buffer Descriptor Statusendpoint1 OUT).

Page 47: Corso PIC-USB

84 marzo 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

Aprendo questo file, troviamo le istruzioni relati-ve alla label GetUSB1 (vedi listato 1).Vediamo ora cosa accade quando si richiama laGETEP1. Innanzitutto viene verificato il flagOWN di BD1OST (registro di stato endpoint 1OUT). Quando è 1, il registro è occupato dal SIE,quindi, l'esecuzione continua dall'etichetta"nobuffer" che pone il Carry Flag a 0 permetten-do di uscire dalla funzione; anche questa routinecosì come la PUTEP1 usa il Carry Flag percomunicare se l'operazione è andata a buon fine(CF=1) oppure no (CF=0). Nel caso invece il bit OWN sia a zero, vienevalorizzato il registro w attraverso BD1OBC(Byte Counter dell'endpoint1 OUT). La routineutilizza le due variabili counter e bytecounter persalvare tale valore durante il ciclo di ricezione. Iningresso la funzione usa FSR+IRP come punta-tore al buffer dove verranno registrati i dati rice-

vuti. Durante il ciclo di ricezione i dati vengonospostati dall'indirizzo puntato da BD1OAL, albuffer di destinazione assegnato dalla funzione.Al termine dell’operazione, il bit OWN vienemesso a 1, così come il bit DTS (Data ToggleSynchronization) per evitare la sovrascrittura deiregistri con pacchetti errati. Anche CF è messo a1 per comunicare che l'operazione è andata abuon fine e la variabile bytecounter passa al regi-stro w (parametro di uscita) il numero di byteinviati. All’etichetta GetUSB1 segue un’altra definitaGetUSB2 che rappresenta la macro per GetEP2.Le istruzioni sono uguali, l'unica variazione deri-va dal fatto che vengono utilizzati i bufferdescriptor dell'endpoint2 anzichè dell'endpoint1.Si può concludere anche alla luce di quantoabbiamo visto per PutEP1 che la BDT rappre-senta una struttura versatile ed efficace per gesti-

goto nobuffer ; nope, OWN = 1 ==> SIE owns the buffer; Yep: OWN = 0 ==> PIC owns the buffer

movf BD1OBC,w ; get byte countbanksel counter ; bank 2movwf countermovwf bytecounter ; # of bytes that will be movedpagesel exitgetloopbtfsc STATUS,Z ; is it a zero length buffer?goto exitgetloop ; yes, bail out now and avoid the rushbanksel BD1OAL ; bank 3movf BD1OAL,w ; get address pointerbanksel source_ptr ; bank 2movwf source_ptr

; This loop operates with the direct bank bits set to bank 2, while IRP; gets switched as needed to for the buffer copygetEPloop

............

............Loop di Trasmissione

............

exitgetloopbsf STATUS,RP0 ; bank 3movf BD1OST,wandlw 0x40 ; save only the data 0/1 bitxorlw 0x40 ; toggle the data o/1 bitiorlw 0x88 ; set owns bit and DTS bitmovwf BD1OST

movlw 0x08 ; reset byte countermovwf BD1OBCbcf STATUS,RP0 ; bank 2movf bytecounter,w ; return # of bytes moved in W regmovwf GPtemp ; move byte counter to temporary rammovf RP_save,w ; restore bank bitsmovwf STATUSmovf GPtemp,w ; load W with the byte countbsf STATUS,C ; signal successreturn

nobufferbanksel RP_save ; restore the bank bitsmovf RP_save,wmovwf STATUSbcf STATUS,Creturnendm

(Continuazione del listato 1)

Caricamento del numero di byte daricevere nelle 2 variabili counter ebytecounter. Il valore deriva daBD1OBC (Buffer Descriptor ByteCounter endpoint1 OUT).

Si utilizza BD1OAL (Buffer DescriptorAddress Low endpoint1 OUT) per pre-cisare l'indirizzo del buffer da cui sileggeranno i dati.

Il ciclo di trasmissione viene iteratodecrementando la variabile counter inmaniera che quando arriva a zero ilciclo termina.

Il bit OWN è messo a 1 cioè si libera dallock la BDT per permettere l'accessoall'USB.

Parametri in uscita: w per il numero dibyte inviati e Carry Flag per indicareche l'operazione è andata a buon fine.

Page 48: Corso PIC-USB

Elettronica In - marzo 2005 85

>

CCoorrssoo PPIICC--UUSSBB re il passaggio dati sugli endpoint sia in entrata

che in uscita. Siamo pronti, quindi, per introdur-re il terzo esperimento che vuole fare da unionerispetto agli altri due implementando un sistemabidirezionale di comunicazione.

Esperimento n.3 Cifrario-USB.

Questa volta, per analizzare la comunicazionebidirezionale tra PC e device, proponiamo la rea-lizzazione di un sistema che permetta di cifrareun testo, scritto sul proprio PC, utilizzando lecapacità di calcolo del nostro PIC. Si tratta, chiaramente, di un esempio didattico dicomunicazione bidirezionale su USB e niente dipiù, che ci consente di capire più a fondo in chemodo debba essere gestita la comunicazione. Pereffettuare il nostro esperimento utilizzeremoprincìpi che sono alla base della crittografiamoderna; per comprenderli facciamo un salto nelpassato.Sul finire della Prima Guerra Mondiale si anda-vano diffondendo le prime telescriventi meccani-

che che utilizzavano un alfabeto di 32 caratteri(chiamato "codice Baudot") rappresentati inmaniera binaria mediante la foratura di un nastrocartaceo (5 fori per ciascun carattere). Nel 1917,un giovane impiegato della compagnia america-na AT&T, Gilbert Vernam, inventò un sistema diprotezione dei testi scritti in Baudot costruendouna macchina che era in grado di leggere duenastri contemporaneamente generando, in uscita,un ulteriore nastro che essenzialmente era ilrisultato dell'OR esclusivo degli altri due. In pra-tica, inserendo nella macchina un nastro sulquale era incisa una sequenza casuale di caratte-ri (A), lunga quanto il testo da cifrare, e quellocontenente il testo in chiaro (B), se ne producevauno cifrato (C). Per risalire al testo in chiaro erasufficiente inserire nella macchina i nastri A e Cricevendo in uscita l'originale. Si trattava di unsistema crittografico simmetrico che ancor oggi èconosciuto con il nome di "Nastri di Vernam".Esso rappresenta un sistema in cui la sicurezzadipende, in maniera esclusiva, dalla segretezzadella chiave e non da quella del metodo secondo

Tabella 1a- DDeessccrriittttoorree EENNDDPPOOIINNTT [[EEPP11IINN]] eettiicchheettttaa EEnnddooppooiinntt11

Tabella 1b - DDeessccrriittttoorree EENNDDPPOOIINNTT [[EEPP11OOUUTT]] eettiicchheettttaa EEnnddooppooiinntt22

Page 49: Corso PIC-USB

86 marzo 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBBil noto principio di Kerckhoffs che è alla base di

tutta la crittografia moderna. Ma la cosa che lorende ancor più interessante è che si tratta di unmetodo teoricamente perfetto cioè un cifrario"indecrittabile". Sommando un testo casuale conun testo in chiaro, infatti, si annulla l'informazio-ne del testo stesso rendendolo anch'esso casuale.

Il cifrato, almeno in linea di principio, può rap-presentare qualsiasi testo in chiaro di uguale lun-ghezza e quindi il malintenzionato che vorrebbeleggerlo non ha alcun indizio da utilizzare perdecifrarlo. Ma cosa c'entra il nostro PIC con tuttoquesto? In effetti noi realizzeremo un cifratore diVernam che, ricevuto un testo in chiaro, genere-

Endpoint1retlw 0x07 ; bLengthretlw ENDPOINT ; bDescriptorTyperetlw 0x81 ; bEndpointAddressretlw 0x03 ; bmAttributesretlw 0x02 ; wMaxPacketSize (low-b)retlw 0x00 ; wMaxPacketSize (high-b)retlw 0x0A ; bInterval

Endpoint2retlw 0x07 ; bLengthretlw ENDPOINT ; bDescriptorTyperetlw 0x01 ; bEndpointAddressretlw 0x03 ; bmAttributesretlw 0x01 ; wMaxPacketSize (low-b)retlw 0x00 ; wMaxPacketSize (high-b)retlw 0x0A ; bInterval

L I S T A T O 2

retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage Page (low-b) ("Vendor Defined Page 1")retlw 0xFF ; Usage Page (high-b) ("Vendor Defined Page 1")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage ("Vendor Defined Usage 1")retlw 0xA1 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Collection ("Application")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage ("Vendor Defined Usage 2")retlw 0xA1 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Collection ("Physical")retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage Page (low-b) ("Vendor Defined Page 2")retlw 0xFF ; Usage Page (high-b) ("Vendor Defined Page 2")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x03 ; Usage ("Vendor Defined Usage 3")retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x04 ; Usage ("Vendor Defined Usage 4")retlw 0x15 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Logical Minimum (0)retlw 0x26 ; Byte di prefisso (bTag,bType,bSize)retlw 0xFF ; Logical Maximum (low-b) (255)retlw 0x00 ; Logical Maximum (high-b) retlw 0x75 ; Byte di prefisso (bTag,bType,bSize)retlw 0x08 ; Report Size (8 bits)retlw 0x95 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Report Count (2 campi dati)retlw 0x81 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Input (Data, Var, Abs)retlw 0x09 ; Byte di prefisso (bTag,bType,bSize)retlw 0x05 ; Usage ("Vendor Defined Usage 5")retlw 0x15 ; Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Logical Minimum (0)retlw 0x26 ; Byte di prefisso (bTag,bType,bSize)retlw 0xFF ; Logical Maximum (low-b) (255)retlw 0x00 ; Logical Maximum (high-b) retlw 0x75 ; Byte di prefisso (bTag,bType,bSize)retlw 0x08 ; Report Size (8 bits)retlw 0x95 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Report Count (1 campo dati)retlw 0x91 ; Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Output (Data, Var, Abs)retlw 0xC0 ; End Collection ("Physical")retlw 0xC0 ; End Collection ("Application")

L I S T A T O 3

Page 50: Corso PIC-USB

Elettronica In - marzo 2005 87

>

CCoorrssoo PPIICC--UUSSBB rà la chiave casuale e quindi il testo cifrato in

tempo reale, rendendoli disponibili su due pan-nelli nell'applicazione host sfruttando una comu-nicazione bidirezionale. Purtroppo la demoboardnon può essere interfacciata con una EEPROMtradizionale ad accesso parallelo (nella qualesono disponibili solo linee in entrata o in uscita),perchè per dialogare con un bus I²C è necessarioun pin bidirezionale, altrimenti avremmo potutosalvare la chiave su quest'ultima creando unachiave "fisica" vera e propria. In pratica soltantoil legittimo possessore della EEPROM avrebbepotuto leggere il testo cifrato, inserendo la stessasulla schedina del PIC.

Il nostro prototipo, inoltre, sarà programmato inmaniera tale da poter essere attivato solo dopoaver premuto una precisa combinazione dei tastiInp1-Inp5 inseriti sulla demoboard. In questomodo vedremo come far partire l'enumerazionesoltanto in determinate condizioni ed introdurre-mo due funzioni di base del Firmware Microchipche non sono interpretate dal Basic: DeinitUSB eConfiguredUSB. Vediamo quindi di procederecon ordine analizzando questo nuovo progetto.

Analisi degli endpoints

Dobbiamo realizzare un dispositivo che comuni-

String2_l1 ; iProduct ("Cifrario-USB Corso PIC-USB")retlw String3_l1-String2_l1 ; bLengthretlw 0x03 ; bDescriptorTyperetlw 'C' ; bString retlw 0x00retlw 'i'retlw 0x00retlw 'f'retlw 0x00retlw 'r'retlw 0x00retlw 'a'retlw 0x00retlw 'r'retlw 0x00retlw 'i'retlw 0x00retlw 'o'retlw 0x00retlw '-'retlw 0x00retlw 'U'retlw 0x00retlw 'S'retlw 0x00retlw 'B'retlw 0x00retlw ' 'retlw 0x00retlw 'C'retlw 0x00retlw 'o'retlw 0x00retlw 'r'retlw 0x00retlw 's'retlw 0x00retlw 'o'retlw 0x00retlw ' 'retlw 0x00retlw 'P'retlw 0x00retlw 'I'retlw 0x00retlw 'C'retlw 0x00retlw '-'retlw 0x00retlw 'U'retlw 0x00retlw 'S'retlw 0x00retlw 'B'retlw 0x00

L I S T A T O 4 A

Page 51: Corso PIC-USB

88 marzo 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

ca con l'host ricevendo un byte del testo in chia-ro e risponde con due byte: uno relativo alla chia-ve ed uno riferito al testo cifrato. Predisporremoquindi l'endpoint1 IN e OUT specificando neldescrittore report che il primo avrà due campi edil secondo uno solo ricordando che la direzione èsempre stabilita rispetto all’host. Ci troviamo, praticamente in una situazione esat-

tamente opposta rispetto all'esperimento 2. Perquanto riguarda la codifica utilizzeremo l'intra-montabile ASCII ad 8bit.Un esercizio di approfondimento potrebbe esse-re quello di realizzare un sistema che funzionicon il nuovo UNICODE a 16 bit.In pratica, il sistema leggerà il byte del testo inchiaro, genererà il byte casuale della chiave e

' Programma Cifrario-USB' Esperimento n.3 Corso PIC-USB Elettronica-In

'******Dichiarazioni variabili necessarie per uso firmware USB******wsave VAR BYTE $70 system 'permette di salvare Wssave VAR BYTE bank0 system 'permette di salvare STATUSpsave VAR BYTE bank0 system 'permette di salvare PCLATHfsave VAR BYTE bank0 system 'permette di salvare FSR

'******Dichiarazioni variabili applicazionecifra VAR BYTE[2] 'carattere cifrato + randomconta VAR BYTE 'contatore byte ricevutitesto VAR BYTE 'carattere testo in chiaroseme VAR WORD 'seme per funzione RANDOM

DEFINE OSC 24 ' Clock 24Mhz

PORTB = 0 ' 8 LED uscite digitali spentiTRISB = 0 ' PORTB definita in uscitaTRISA = %00111111 ' PORTA RA1..RA5 in ingressoTRISC = %11000001 ' PORTC RC0-RC6-RC7 in ingressoPORTC = 0 ' Reset sequenza attivazione

.........T1CON.1= 0 ' Seleziona clock interno per TIMER1 TMR1CS=0

.........T1CON.0= 1 ' Avvia TIMER1 TMR1ON=1

GoTo INIZIO ' Salta al main

' Il gestore Interrupt inizia dalla label BUSINTDEFINE INTHAND BUSINTAsmBUSINTmovf FSR, W ;salvataggio di FSRmovwf fsavemovlw High ServiceUSBIntmovwf PCLATHbtfsc PIR1, USBIF ;Se non c'è nessun interrupt da gestire vado a RIPREGCall ServiceUSBInt ;Richiama la routine firmware che gestisce tutti gli

;Interrupt dei moduli USB del PICRIPREG ;Ripristino registri salvati

clrf STATUSmovf fsave, Wmovwf FSRmovf psave, Wmovwf PCLATHswapf ssave, Wmovwf STATUSswapf wsave, Fswapf wsave, W

retfie ; Torno al pgm principale

EndAsm

INIZIO:if PORTC=%10000001 then goto USBINIGoTo INIZIO ' Cicla su se stesso fino alla sequenza

L I S T A T O 5

Definizione pin IN e OUT delle porteA,B,C del PIC. Sono necessarie inparticolare quelle di RC0 e RC7 perrilevare la sequenza di attivazione.

Ciclo per rilevare quando vengonopremuti i tasti Inp3 e Inp5 dellademoboard.

; include "termodsc.asm" ; Descrittori TermoUSB-Esperimento 1; include "PWMdsc.asm" ; Descrittori PWM-USB-Esperimento 2include "CIFRAdsc.asm" ; Descrittori Cifratore-USB-Esperimento 3

L I S T A T O 4 B

Page 52: Corso PIC-USB

Elettronica In - marzo 2005 89

CCoorrssoo PPIICC--UUSSBB

realizzerà un XOR tra i due creando il byte cifra-to. Al termine, invierà i due byte risultanti all'host.

Descrittore Endpoint

Anche in questo caso, nel descrittore Interface,bNumEndpoints sarà pari a 2 visto che utilizze-remo EP1IN e EP1OUT. I descrittori device,configuration e hid rimarranno gli stessi dell'e-sperimento 2. Questa volta dobbiamo intervenirenel codice presente sia dopo l'etichettaEndpoint1 (EP1IN) che Endpoint2 (EP1OUT). In particolare è necessario prestare attenzione aivalori dei campi wMaxPacketSize, ebEndpointAddress, come mostrato in tabella1a/b. Le istruzioni risultanti sono le stesse ripor-tate nel listato 2.

Descrittore Report

Se ci ricordiamo come abbiamo creato il descrit-tore report dell'ultimo esperimento vedremo chein questo caso possiamo inserire due usage inizia-li e limitare la seconda ad un solo campo. Graziealla definizione della collection Physical la modi-fica è abbastanza semplice. La struttura gerarchi-ca risultante si può sintetizzare in questo modo:

USAGE_PAGE (Vendor Defined 1)USAGE (Vendor Usage 1)

COLLECTION (Application) USAGE (Vendor Usage 2)

COLLECTION (Physical) USAGE_PAGE (Vendor Defined 2)

USAGE (Vendor Usage 3)USAGE (Vendor Usage 4)LOGICAL_MINIMUM (0)

LOGICAL_MAXIMUM (255) REPORT_SIZE (8) REPORT_COUNT (2) INPUT (Data,Var,Abs)

USAGE (Vendor Usage 5)LOGICAL_MINIMUM (0)LOGICAL_MAXIMUM (255) REPORT_SIZE (8) REPORT_COUNT (1) OUTPUT (Data,Var,Abs)

END_COLLECTIONEND_COLLECTION

Il descrittore report completo risulta come nellistato 3.

Descrittore String

Il descrittore String è immediato. Utilizziamo sem-pre due lingue e quindi dobbiamo inserire la descri-zione relativa al prodotto "Cifrario-USB Corso PIC-USB", il suo numero seriale "EXP.3" e l'interfaccia"EP1/INOUT" nelle due versioni. Riportiamo sola-mente il codice prodotto in lingua italiana (vedilistato 4a). Terminato il descrittore bisogna effettua-re la solita modifica nel file USBDESC.ASM inse-rendo l’include relativa al file appena creato. Il filediventa come riportato nel listato 4b. Veniamo quin-di al codice basic che questa volta sarà un pò piùlungo ma abbastanza semplice.

PWM-USB Codice Basic

Il nostro dispositivo viene riconosciuto dal PCsoltanto dopo aver premuto contemporaneamen-te i tasti Inp3 e Inp5 della demoboard. Come sivede nel listato 5 (in Basic) abbiamo soltanto

' di attivazione esatta USBINI:

PORTB=%11111111 ' Tutti i led accesi sequenza OK PAUSE 500PORTB=0

USBInit ' Processo di enumerazione alla fine il device' entra nello stato Configurato

Pause 200 ' Attesa

RICEVI:USBIN 1,testo,conta,RICEVI 'ricevi carattere testo in chiaroPORTB=testo 'portB rappresenta il carattere ricevutohigh seme=TMR1l 'valorizzo il seme con swaplow seme=TMR1hrandom seme 'randomizzo il semecifra[0]= seme 'carattere casualecifra[1]= testo ^ cifra[0] 'XOR tra chiaro e casuale

INVIA:USBOUT 1, cifra,2,INVIA 'invia carattere casuale + cifratoGoTo RICEVI 'Continua all'infinito

>

Accensione dei led della demoboard eavvio enumerazione.

Ricezione carattere dall'host.

Elaborazione carattere ricevutodall'host.

Invio caratteri elaborati.

Page 53: Corso PIC-USB

90 marzo 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

introdotto un ciclo prima di richiamare la funzio-ne InitUSB che si occupa del processo di enume-razione. Nel ciclo non facciamo altro che con-trollare lo stato della porta C, in particolare deipin RC0 e RC7 corrispondenti ai tasti Inp3 eInp5. Non appena questi ultimi vengono premu-ti, e quindi i relativi bit vanno a 1, il programmascrive sulla porta B il valore 255 accendendo tuttii led (LD1-LD8) della demoboard per far vedereche la sequenza è stata accettata quindi richiamaInitUSB avviando il processo di enumerazionefinchè il dispositivo non si porta nello stato con-figurato. A quel punto iniziano i due cicli di rice-zione ed invio dei dati. Per quanto riguarda lagenerazione del carattere casuale sfruttiamo lafunzione Basic Random che utilizza un algorit-mo pseudo-casuale su una variabile a 16-bitpresa come seme.Per valorizzare quest'ultima, utilizziamo uno deimoduli timer del nostro PIC, precisamente ilTimer1 che viene sincronizzato sul clock internoe avviato attraverso la valorizzazione di due flagdel registro T1CON (Timer1 Control Register):TMR1CS (Timer1 Clock Source Select Bit),TMR1ON (Timer1 On bit). Il Timer1 valorizzadue registri da 8 bit TMR1L e TMR1H incre-mentando il valore a 16 bit risultante sulla basedella sorgente di clock selezionata. In questocaso, non potendo connettere ad RC1 e RC0 unoscillatore esterno per come è configurata lademoboard, è stato scelto il clock interno.L'assegnazione alla variabile seme avviene attra-verso lo swap dei due byte, dopodiché si effettual'operazione di OR esclusivo con il carattere deltesto in chiaro.Al termine i due risultati dell'elaborazione ven-gono restituiti all'host attraverso l'endpoint1.Utilizzando l'applicativo (scaricabile dal sitodella rivista) cifraUSB.exe possiamo provare lacomunicazione bidirezionale con il nostro proto-tipo cifratore. L'utilizzo è molto semplice: dopoaver collegato la demoboard al PC, è necessariopremere contemporaneamente i pulsanti Inp3 eInp5 ottenendo come risultato l’accensione

immediata dei led LD1÷LD8.A questo punto compaiono, sul pannello didestra dell'applicativo, i dati identificativi deldispositivo e lo stato "Connesso". Spostiamociora sul primo memo dove dobbiamo digitare iltesto che vogliamo cifrare. Facendo click sul pul-sante "Invia", i singoli caratteri vengono tra-smessi alla demoboard che risponde con la chia-ve e il cifrato.I caratteri ricevuti dall'host vengono inseriti neidue memo rimanenti. Per entrambi abbiamo pre-visto la possibilità di salvare il risultato in duefile testo. Osserviamo ora la figura 1. Prendiamoi primi due numeri della chiave e del testo cifra-to espressi in esadecimale cioè AC (=10101100)e E9 (=11101001). Calcolando l'XOR otteniamoil numero esadecimale 45 (=01000101) che indecimale è 69 cioè il valore ASCII della E maiu-scola. Quindi, riotteniamo il testo di partenza in

chiaro, così come avveniva nella macchina diVernam leggendo contemporaneamente i duenastri creati. Abbiamo realizzato un cifratore chesfrutta la comunicazione bidirezionale in manie-ra abbastanza efficiente. Se variate il campobInterval del descrittore Endpoint potete rallenta-re la velocità di esecuzione del dispositivo pervedere come i due pannelli vengono popolati viavia che i dati vengono trasmessi al dispositivo.Per rendere la cosa più accattivante, ogni caratte-re ricevuto viene trasferito alla PORTB accen-dendo i relativi Led (effetto "Albero diNatale"...). In questo esperimento abbiamo vistocome sia possibile controllare le condizioni nellequali avviare il processo di enumerazione deldispositivo. Dopo aver fatto un po’ di prove pos-siamo passare a considerare le due ultime fun-zionalità di base del firmware Microchip:ConfiguredUSB e DeinitUSB. Prima di richiamare la InitUSB il "device" è pra-

Fig. 1

Page 54: Corso PIC-USB

Elettronica In - marzo 2005 91

>

CCoorrssoo PPIICC--UUSSBB

ticamente inesistente per l'host, pur sfruttandol'alimentazione del bus. In Basic abbiamo a dis-posizione soltanto tre istruzioni per lavorare condispositivi USB, una determina l'enumerazione,mentre le altre due ci permettono di controllare lacomunicazione tramite gli endpoint. Nelle altrepuntate abbiamo visto come, in effetti, questeistruzioni siano in realtà delle interfacce verso

trollare il valore di questo registro restituendo un1 nel Zero Flag, se il dispositivo è configurato, euno 0 in tutti gli altri casi. Tale funzionalità èstata sviluppata principalmente per verificare arun-time se è possibile avviare una comunicazio-ne con il dispositivo attraverso gli endpoints.Essa viene richiamata successivamente allaInitUSB per controllare che il processo di enu-

altrettante funzionalità messe a disposizione dalfirmware Microchip. Ebbene, nella realtà, que-st'ultimo espone altre funzioni che possono esse-re richiamate attraverso l'assembler e possonorisultare decisamente utili. La prima che andia-mo ad analizzare si chiama ConfiguredUSB.All'indirizzo 197h del nostro PIC c'è un registrodi utilizzo esclusivo chiamato USWSTAT(USBSoftware Status Register) del quale, i primi duebit vengono utilizzati dal firmware Microchipper conservare lo stato del dispositivo durante ilprocesso di enumerazione. In particolare vengo-no utilizzati i seguenti valori:

00=Alimentato01=Default10=Indirizzato11=Configurato

La macro ConfiguredUSB non fa altro che con-

ConfiguredUSB macrolocal enumloopbanksel USWSTATpagesel enumloop

enumloopclrwdt ; clear the watch dog timer.movlw 0x03andwf USWSTAT,w ; save lower 2 bits of USWSTATxorlw CONFIG_STATE ; compare with configured statebtfss STATUS,Z ; are we configured?goto enumloop ; nope, keep waiting ...endm

L I S T A T O 6

Estrazione degli ultimi 2 bit dal regi-stro di stato e verifica del valore conCONFIG_STATE=11 per vedere se ildispositivo ha terminato l'enumera-zione.

DeInitUSBbanksel UCTRLbcf UCTRL,DEV_ATT ; D+/D- go high Zbsf UCTRL,SUSPND ; Place USB module in low power mode.

clrf USWSTAT ; set device state to powered.

bcf STATUS,RP1 ; select bank 1bcf PIE1,USBIE ; clear USB interrupt enable

ifdef SHOW_ENUM_STATUSbcf STATUS,RP0movlw 0x01movwf PORTB ; clear all lights except poweredbsf STATUS,RP0

endifreturn

L I S T A T O 7

Dispositivo posto in stand-byattraverso l'USB Control Register(UCTRL).

Disabilitazione di tutti gli InterruptUSB.

Gestione led di controllo su PORTB.

merazione sia stato concluso con successo.Non è possibile, infatti, utilizzare PutEPn eGetEPn senza aver passato tale controllo. Unapiccola avvertenza: il registro USWSTAT è riser-vato all'utilizzo esclusivo del firmwareMicrochip ma non è protetto in scrittura quindi losi può sovrascrivere erroneamente causando deimalfunzionamenti. Se entriamo nel fileUSB_defs.inc troviamo le istruzioni descritte nellistato 6. Come si vede chiaramente la routineestrae i bit 0 e 1 del registro USWSTAT per veri-ficarne il valore. Il ciclo continua a girare finchénon viene raggiunto lo stato "configurato".Da notare che l'utilizzo dell'istruzione xorlw per-mette di valorizzare direttamente il Zero Flagcon il risultato del confronto. Il ciclo si concludeattraverso una btfss (Bit Test f, Skip if Set) chesalta il goto successivo se il risultato del con-fronto è pari a 0 cioè i due bit di USWSTAT sonouguali a CONFIG_STATE (cioè '11' in binario).

Page 55: Corso PIC-USB

92 marzo 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

La seconda macro che andiamo ad analizzare sichiama DeinitUSB. Già dal nome avrete capitoche si tratta di una funzionalità esattamenteopposta ad InitUSB. In effetti grazie a questamacro è possibile fare in modo che il dispositivo

venga ignorato dall'host. La SIE (USB SerialInterface) viene posta in uno stato di stand-by egli interrupt USB vengono completamente igno-rati. Se apriamo il file USB_ch9.asm troviamo leistruzioni riportate nel listato 7. La routine acce-

; ******************************************************************; DeInit USB; Shuts down the USB peripheral, clears the interrupt enable.; ******************************************************************DeInitUSB

DIVENTA

; ******************************************************************; DeInit USB; Shuts down the USB peripheral, clears the interrupt enable.; ******************************************************************_DeInitUSB

L I S T A T O 8

' Programma InitUSB-DeInitUSB' Controllare completamente il processo di enumerazione' Corso PIC-USB Elettronica-In

'******Dichiarazioni variabili necessarie per uso firmware USB******wsave VAR BYTE $70 system 'permette di salvare Wssave VAR BYTE bank0 system 'permette di salvare STATUSpsave VAR BYTE bank0 system 'permette di salvare PCLATHfsave VAR BYTE bank0 system 'permette di salvare FSR'******Dichiarazioni variabili applicazioneDEFINE OSC 24 ' Clock 24MhzDEFINE SHOW_ENUM_STATUS 1 ' Visualizza lo stato del dispositivo

PORTB = 0 ' 8 LED uscite digitali spentiTRISB = 0 ' PORTB definita in uscitaTRISC = %11000001PORTC = 0GoTo INIZIO ' Salta al main

' Il gestore Interrupt inizia dalla label BUSINTDEFINE INTHAND BUSINT

AsmBUSINT

movf FSR, W ;salvataggio di FSRmovwf fsavemovlw High ServiceUSBIntmovwf PCLATHbtfsc PIR1, USBIFCall ServiceUSBInt ;Richiama la routine firmware che gestisce tutti gli

;Interrupt dei moduli USB del PICRIPREG ;Ripristino registri salvati

clrf STATUSmovf fsave, Wmovwf FSRmovf psave, Wmovwf PCLATHswapf ssave, Wmovwf STATUSswapf wsave, Fswapf wsave, Wretfie ; Torno al pgm principale

EndAsmINIZIO:

USBInit ' Avvio Enumerazione PORTC = 0

ATTESA1:if PORTC = %00000001 then goto SOSPgoto ATTESA1 ' Ciclo fino a INP3

SOSP:call DeInitUSB

ATTESA2:goto ATTESA2 ' Ciclo infinito

L I S T A T O 9

Il dispositivo entra nello stato"Configurato" al termine del processodi enumerazione.

Il dispositivo viene sospeso regre-dendo allo stato "Alimentato" nelmomento in cui si preme il tasto Inp3.

Page 56: Corso PIC-USB

Elettronica In - marzo 2005 93

de ad un altro registro fondamentale per il firm-ware Microchip: UCTRL (USB ControlRegister). Prima mette a zero il bit 3 chiamatoDEV_ATT (Device Attach) per porre le linee datidel bus ad alta impedenza, successivamente valo-rizza a 1 il bit 1 chiamato SUSPND (Suspend) permettere il modulo USB del PIC in uno stato disospensione (in pratica viene completamente iso-lato). Vengono valorizzati a '00' i bit 0 e 1 del regi-stro USWSTAT.In questo modo il dispositivo passa allo stato"Alimentato". Infine, viene modificato anche ilregistro PIE1 (Peripheral Interrupt Enable1Register), precisamente al bit 3 (USBIE: USBInterrupt Enable Bit) per disabilitare tutti i segna-li di interrupt relativi al modulo USB. La seconda

CCoorrssoo PPIICC--UUSSBB (_) prima di tale etichetta come mostrato nel

listato 8 e salviamo il file così modificato.Per capire bene il funzionamento speculare diInitUSB e DeinitUSB realizziamo un piccoloprogramma che permette di controllare il proces-so di enumerazione e la sospensione attraverso iltasto Inp3. Faremo avviare l'enumerazione, poiporremo il dispositivo in sospensione attraversoil tasto Inp3. Utilizzeremo come descrittore quel-lo del cifrario; dato che non dobbiamo comuni-care con il device, Endpoint e Report sono inin-fluenti (vedi listato 9). Abbiamo creato un dispositivo che nel momentoin cui premiamo Inp3 regredisce allo stato"Alimentato"; ciò è mostrato dai led della demo-board. Dopo l'enumerazione, vengono accesi i

Fig. 2

parte della routine viene eseguita solo se, nelnostro sorgente, abbiamo utilizzato la defineSHOW_ENUM_STATUS e serve esclusivamentea valorizzare opportunamente la PORTB affinchéi led rispecchino lo stato del dispositivo. Tutti iled vengono spenti mantenendo acceso solo ilprimo, quello relativo allo stato alimentato. Perrichiamare la funzione descritta dovremo fare inmodo che il nostro compilatore PBP riesca adaccedere alla routine assembler del firmwareMicrochip. In pratica per utilizzare una call diret-tamente dal nostro codice Basic dovremo far unapiccolissima modifica al file USB_ch9.asm. Alla riga 286 di questo file troviamo la labelDeInitUSB che contrassegna l'inizio della routi-ne che ci interessa. Inseriamo un "underscore"

primi 4 led segno che il dispositivo è configuratoe quindi pienamente visibile all'host; premendo iltasto Inp3, 3 led si spengono e rimane accesosolo LD1 per cui il dispositivo viene ignorato.Utilizzando il software host del cifrario, poteteosservare che, dopo aver premuto il tasto Inp3, ildevice scompare dalla lista dei dispositivi com-portandosi come se fosse fisicamente disconnes-so dal bus. La figura 2 permette di apprezzare lasituazione prima e dopo la pressione del tastoInp3 della demoboard.Nella prossima puntata analizzeremo le funzioniavanzate rese disponibili dal firmware Microchipe le possibili modifiche allo stesso. Entreremo,quindi, nell'ultima fase di questo corso quellarelativa allo sviluppo lato host. Non perdetevela.

Prima e... ...dopo la pressione del tasto Inp3

Page 57: Corso PIC-USB

el corso delle precedenti puntate abbiamovisto che le funzioni di base del firmware

Microchip vengono interfacciate direttamentedal PICBasic attraverso le istruzioni USBIN,USBOUT, INITUSB. Esistono tuttavia alcunealtre funzioni che svolgono operazioni di parti-colare rilievo e che possono tornare utili nellosviluppo di nuovi dispositivi; per esempio, nellascorsa puntata abbiamo analizzato e utilizzato la

DeInitUSB, che permette un comportamentospeculare rispetto alla InitUSB: riutilizzeremoora quanto già visto per chiarire le funzionalitàSoftDetachUSB, RemoteWakeUp, StallUSBEP.

SoftDetachUSB

Questa routine permette di reinizializzare il pro-cesso di enumerazione. In altre parole, fa in

Elettronica In - aprile 2005 81

>

CCoorrssoo PPIICC-UUSSBB Corso ddi

programmazione pper PPIC:l�innterrfaccia UUSSB

6AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittàà UUSSBBiimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorriiMMiiccrroocchhiipp..UUnn aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittàà,,vviissttaa llaa ccrreesscceennttee iimmppoorrttaannzzaa ddii qquueessttoopprroottooccoolllloo nneellllaa ccoommuunniiccaazziioonneettrraa ccoommppuutteerr ee ddiissppoossiittiivvii eesstteerrnnii..IInn qquueessttaa ppuunnttaattaa pprroosseegguuiiaammooll��eessaammee ddii aallccuunnee ffuunnzziioonnii ppeerr llaaccoommuunniiccaazziioonnee,, ddeell rriiccoonnoosscciimmeennttooddeellllaa pprreesseennzzaa ddii ppeerriiffeerriicchhee ,, eecccc..SSeessttaa ppuunnttaattaa..

a cura di Carlo Tauraso

SoftDetachUSBbanksel UCTRLbcf UCTRL,DEV_ATT ; clear attach bit

bcf STATUS, RP0 ; bank 2

clrf outerclrf innerpagesel SoftDetachLoop

SoftDetachLoopincfsz inner,fgoto SoftDetachLoopincfsz outer,fgoto SoftDetachLoop

pagesel InitUSBcall InitUSB ; reinitialize the USB peripheralreturn

L I S TA TO 1

Mettendo a zero il flag DEV_ATT siprovoca la disconnessione fisica deldispositivo dal bus.

I contatori Outer e Inner vengonousati per creare un ritardo di circa50ms affinché l'host si accorga delladisconnessione.

Viene riavviato il processo dienumerazione attraverso una call allaormai nota InitUSB.

Page 58: Corso PIC-USB

82 aprile 2005 - Elettronica In

CCoorrssoo PPIICC-UUSSBB

modo che il dispositivo venga disconnesso ericonnesso al bus in maniera tale che l'host facciaripartire il processo di enumerazione, così comefarebbe per l'inserimento di un nuovo device.L'operazione diventa particolarmente interessan-te perché rende possibile modificare "al volo" ilfunzionamento di un dispositivo, senza material-mente disconnetterlo. Naturalmente questa fun-zionalità è utile nel momento in cui creiamo deidispositivi con due descrittori Configuration. Adesempio, rende possibile creare un device checontiene due configurazioni: una per Mouse eduna per Tastiera. Il device sceglierebbe di esserevisto dall'host nell'uno o nell'altro modo a secon-da del traffico che dovrebbe svolgere. Un casoanalogo è stato descritto in un Technical Briefing(TB058) apparso sul sito della Microchip(www.microchip.com).In un approccio standard avremmo dovuto crea-re un device driver lato host in grado di ricono-

scere il tipo di dispositivo ed inviare un'istruzio-ne di SetConfiguration (vedi riferimento nellaprima puntata) affinché il dispositivo funzionas-se in un determinato modo. Attraverso la funzio-ne SoftDetachUSB tutto questo non è necessario,perché possiamo spostare il controllo verso ilPIC; in altre parole è quest'ultimo a deciderequale dispositivo deve essere, cambiando "fac-cia" nel momento in cui farà riavviare esplicita-mente il processo di enumerazione.Ma come funziona tutto ciò? Per capirlo dobbia-mo riferirci al solito file USB_ch9.asm, all'inter-no del quale troviamo il listato della routine; pro-viamo ad analizzarlo (vedi Listato 1).Ritroviamo il registro UCTRL(USB ControlRegister) che avevamo visto nella scorsa puntataa proposito della DeInitUSB. In questo caso siutilizza solo il flag DEV_ATT: valorizzandolo azero, si fa in modo che le linee dati D+/D- sianoforzate in uno stato ad alta impedenza, così come

; *********************************************************************; USB Soft Detach; *********************************************************************SoftDetachUSB

DIVENTA

; *********************************************************************; USB Soft Detach; *********************************************************************_SoftDetachUSB

MOD I F I C A F I L E USB- ch9.asm

' Programma SoftDetach' Utillizzo della funzione SoftDetach' Corso PIC-USB Elettronica-In'******Dichiarazioni variabili necessarie per uso firmware USB******

wsave VAR BYTE $70 system 'permette di salvare Wssave VAR BYTE bank0 system 'permette di salvare STATUSpsave VAR BYTE bank0 system 'permette di salvare PCLATHfsave VAR BYTE bank0 system 'permette di salvare FSR

'******Dichiarazioni variabili applicazioneDEFINE OSC 24 ' Clock 24MhzDEFINE SHOW_ENUM_STATUS 1 ' Visualizza lo stato del dispositivo

PORTB = 0 ' 8 LED uscite digitali spentiTRISB = 0 ' PORTB definita in uscitaTRISC = %11000001 ' PORTC definizione IN/OUTPORTC = 0 ' PORTC resetGoTo INIZIO ' Salta al main

' Il gestore Interrupt inizia dalla label BUSINTDEFINE INTHAND BUSINTAsmBUSINT

movf FSR, W ;salvataggio di FSRmovwf fsavemovlw High ServiceUSBIntmovwf PCLATH

L I S TA TO 2

RC0, RC6, RC7 in input sono collegatirispettivamente a Inp3, Inp4 Inp5.Il resto in output RC1 e RC2comandano le uscite PWM1 e PWM2.

Il listato della nostra routine di prova è:

Page 59: Corso PIC-USB

Elettronica In - aprile 2005 83

>

CCoorrssoo PPIICC-UUSSBB

avviene nel momento in cui disconnettiamo fisi-camente il dispositivo. Successivamente si avviaun ciclo (SoftDetachLoop) nel quale, attraversodue contatori (inner e outer) si realizza un ritardodi circa 50ms, necessario affinché l'host si accor-ga che il dispositivo è stato disconnesso. Al ter-mine si fa una call alla InitUSB, che riavvia ilprocesso di enumerazione.Per rendere la cosa più interessante, realizziamoun piccolo programma che permette di riavviareil processo di enumerazione attraverso la pres-sione del solito tasto Inp3. Questa volta utilizzia-mo un descrittore generico (firmdsc.asm) con unsolo byte di input ed uno di output; inoltre elimi-niamo il secondo linguaggio mantenendo comelangID quello inglese, ma inserendo le descrizio-ni in Italiano: così facendo, il driver Microsoftcrede di parlare in Inglese e non si accorge chesta parlando in Italiano.Useremo nuovamente questa struttura per tuttigli esempi che faremo sulle funzionalità avanza-te. Ritenendo quest'ultima sufficientementechiara, anche sulla base delle analisi fatte nelleprecedenti puntate, possiamo passare a presenta-re il listato PicBasic, nel quale, lo vedete, abbia-mo voluto utilizzare una call diretta, ragion percui è necessario effettuare la solita modifica alfile USB_ch9.asm, anteponendo alla labelSoftDetachUSB il carattere di underscore, comesi vede nello schema della pagina precedente(Modifica file). Il codice è piuttosto semplice ericorda la prova che abbiamo fatto con la routine

DeInitUSB. La differenza sostanziale è che inquesto caso forziamo il processo di enumerazio-ne ogni volta che premiamo il tasto Inp3, mentrenel precedente portavamo il device in uno statodi sospensione, rendendolo invisibile all'host. Alla pressione del tasto Inp3 il dispositivo ripas-sa nei vari stati che contraddistinguono l'enume-razione: Alimentato, Default, Indirizzato,Configurato. Contemporaneamente, sul PC ilcursore diventerà una clessidra, segno che ilsistema operativo sta nuovamente identificandoil dispositivo. Il processo è piuttosto rapido, percui non si possono apprezzare cambiamenti neiled di stato della demoboard.Grazie a SoftDetach, InitUSB, DeInitUSB, pos-siamo controllare con una certa precisione il pro-cesso di enumerazione fondamentale per un cor-retto funzionamento di qualsiasi dispositivo coninterfaccia USB. Nel caso si voglia creare un di-

btfsc PIR1, USBIF ;Se non c'e' nessun interrupt da gestire vado a RIPREGCall ServiceUSBInt ;Richiama la routine firmware che gestisce tutti gli

;Interrupt dei moduli USB del PICRIPREG ;Ripristino registri salvati

clrf STATUSmovf fsave, Wmovwf FSRmovf psave, Wmovwf PCLATHswapf ssave, Wmovwf STATUSswapf wsave, Fswapf wsave, Wretfie ; Torno al pgm principale

EndAsm

INIZIO:USBInit ' Processo di enumerazione inizialePORTC = 0 ' Reset PORTC

ATTESA1:if PORTC = %00000001 then goto SOFTDETgoto ATTESA1 ' Cicla fino a INP3

SOFTDET:call SoftDetachUSB

ATTESA2:PORTC = 0 ' Reset PORTCgoto ATTESA1 ' Torna a controllare se si preme INP3

(Continuazione del listato 2)

Enumerazione appena il device vienecollegato.

Ciclo che permette di rilevare se iltasto INP3 è stato premuto

Il device viene disconnesso e si forzail processo di enumerazione.Ritornando al controllo di INP3.

Fig. 1

Page 60: Corso PIC-USB

84 aprile 2005 - Elettronica In

CCoorrssoo PPIICC-UUSSBB

spositivo con più configurazioni, è necessariopredisporre gli appositi descrittori e riscriverealcune parti del file usb_ch9.asm. Come antici-pato, è infatti indispensabile dare un significatoalla routine Get_Configuration_Descriptor e

KYBD_ATT, che stabilisce se caricare la confi-gurazione per la tastiera o quella per il mouse. Ilflusso si può rappresentare come in Fig. 1.Apriamo il file usb_ch9.asm e vediamo comecambia essenzialmente la routine di

Get_Config_Descriptor ; starts in bank2pagesel Descriptions ; set up PCLATH for call belowmovlw GET_DESCRIPTORmovwf USB_dev_req ; currently processing a get descriptor request

banksel TYPEmovlw low Config1btfsc KYBD_ATTmovlw low Config11banksel EP0_startmovwf EP0_startbanksel TYPEmovlw high Config1btfsc KYBD_ATTmovlw high Config11banksel EP0_startmovwf EP0_start+1

movlw 2 ; bump pointer by 2 to get the complete descriptor addwf EP0_start,f ; length, not just config descriptorbtfsc STATUS,Cincf EP0_start+1,fcall Descriptions ; get length of the config descriptor

L I S TA TO 3

Nel file contenente i descrittori sonostati predisposti due descrittoriCONFIGURATION (uno tastiera e unomouse) che iniziano rispettivamentecon le etichette Config1 e Config11.

A seconda del valore del flagKYBD_ATT viene caricato comeindirizzo iniziale (2byte) quellodell'etichetta Config1 o Config11.

modificare sia Get_Device_Descriptor cheGet_Report_Descriptor. Tutte queste routinehanno come funzione principale quella di calco-lare l'indirizzo iniziale di ciascun descrittore.Successivamente viene richiamata la proceduraDescriptions, che ritroviamo in ognuno deidescrittori che abbiamo costruito per inviare leinformazioni relative all'host. Pertanto, in ognu-na di queste routine dovremo aggiungere le istru-zioni che ci permetteranno di scegliere qualedescrittore caricare, a seconda delle varie confi-gurazioni predisposte. Ad esempio, nel TechnicalBriefing n. 58 di Microchip viene definito un flag

Get_Config_Descriptor (vedi Listato 3). Nellaroutine si utilizza l'istruzione btfsc KYBD_ATT(Bit Test f, skip if clear) che, qualora il flag siazero, salta l'istruzione successiva. In questomodo EP0_start conterrà il valore dell'indirizzoiniziale da cui caricare il descrittore configura-tion; più esattamente, caricherà quello che partedalla label Config1 se KYBD_ATT=0, o quelloche parte dalla label Config11 se KYBD=1.Analogamente, vanno modificate anche le routi-ne che caricano i descrittori Report e Device.Per rendere le cose più semplici, a partire dallaversione 1.25 del firmware sono state introdotte

CDI_start retlw low Config1 retlw high Config1

;*********************************************;PUNTO DI INSERIMENTO ULTERIORI CONFIGURAZIONI;*********************************************; retlw low Config2; retlw high Config2; ecc....

�������..RDI_start

retlw low ReportDescriptorLen retlw high ReportDescriptorLen ;*********************************************;PUNTO DI INSERIMENTO ULTERIORI REPORT;*********************************************; retlw low ReportDescriptorLen2; retlw high ReportDescriptorLen2; etc....

���������.

L I S TA TO 4

Page 61: Corso PIC-USB

Elettronica In - aprile 2005 85

>

CCoorrssoo PPIICC-UUSSBB le funzioni Config_descr_index e

Report_descr_index. Quindi, per aggiungere unaconfigurazione è sufficiente inserire, nei puntid'ingresso evidenziati del descrittore, la label ini-ziale (vedi Listato 4).Il sistema è stato derivato da quello relativo aidescrittori string in cui ogni descrizione è con-traddistinta da un'indice numerico. Pertanto, peri dispositivi "multifunzione" sarà sufficienteinserire indici differenti per i ciascun device: ilfirmware caricherà le descrizioni corrette nonappena verrà scelta la configurazione voluta.Chi volesse approfondire l'argomento potrà sca-ricare i file sorgente contenuti nell'archivioTB058.zip disponibile nel sito Microchip.Adesso, passiamo, invece, ad un'altra funzione.

CheckSleep

Nel caso in cui sul bus venga rilevata assenza ditraffico per un periodo di almeno 3ms, il PICvalorizza un flag nel registro UIR(USB InterruptFlags Register) chiamato UIDLE (bit5). Si può

UIR posizionato sul bit2). Durante questa fase,l’assorbimento del dispositivo passa da un mas-simo di 20 mA (normale esercizio, ossia presen-za di traffico) a 140µA (low power mode).Ma vediamo più da vicino il corrispondente lista-to (Listato 5): è molto lineare e gira tutto attornoal significato di due flag e dei relativi segnali diinterrupt. Il primo è UIDLE, che permette di sta-bilire se il bus si trova in uno stato di "idle" e se,quindi, possiamo passare al low power mode.L'altro è ACTIVITY, che, invece, rileva qualsiasitraffico presente sulle linee dati.Nella routine iniziale si verifica lo stato di "idle":se è presente, viene disattivato UIDLE e attivatoACTIVITY, e il dispositivo viene messo inSLEEP. Non appena si rileva attività sul bus, si fail percorso inverso, ossia si disattiva ACTIVITYe si attiva UIDLE per rilevare il prossimo stato di"idle". Infine, il passaggio allo stato di SLEEPviene segnalato attraverso il bit SUSPND delregistro UCTRL (USB Control Register).Si noti che, per poter utilizzare la call diretta-mente da PicBasic, nel file USB_ch9.asm ante-

CheckSleepbanksel IS_IDLEbtfss IS_IDLE,0 ; test the bus idle bitreturn

ifdef SHOW_ENUM_STATUSbanksel PORTBbsf PORTB,4 ; turn on LED 4 to indicate we've gone to sleepbanksel UIR

endifbsf STATUS,RP0 ; point to bank 3bcf UIR,ACTIVITYbsf UIE,ACTIVITY ; enable the USB activity interruptbsf UCTRL,SUSPND ; put USB regulator and transciever in low power statesleep ; and go to sleepnopbcf UCTRL,SUSPNDbcf UIR,UIDLEbsf UIE,UIDLEbcf UIR,ACTIVITYbcf UIE,ACTIVITY

ifdef SHOW_ENUM_STATUSbanksel PORTBbcf PORTB,4 ; turn off LED 4 to indicate we're back.

endifreturn

L I S TA TO 5

quindi trasformare lo stato del dispositivo in"Sospeso", attivando una modalità a risparmioenergetico: il cosiddetto low power mode.Tutte le operazioni sul bus vengono sospese, fin-chè non si rileva una qualsiasi attività sulle lineedati D+/D-, attività che corrisponde ad un segna-le di interrupt di tipo Activity (analogo flag del

poniamo sempre alla label CheckSleep il caratte-re di underscore.Notate altresì che il dispositivo entra in stato disleep esclusivamente se il controllo del flagUIDLE va a buon fine, altrimenti l'esecuzionedella procedura termina passando all'istruzioneimmediatamente successiva alla call.

Viene attivato l'interrupt ACTIVITY cherileva il traffico sulle linee dati attraversoil registro UIE (USB Interrupt EnableRegister) e azzerato il flag relativo nelregistro UIR.

Il flag UIDLE è rimappato sulla variabileIS_IDLE definita in pbpusb14.ramappartenente alle librerie del compilatore.Nel caso il bit=0 l'esecuzione tornaimmediatamente al programma principale.

Il sistema entra in low power mode; sinoti che nel caso sia stata inserita la defi-ne SHOW_ENUM_STATUS il led5 dellademoboard (corrispondente al pin4PORTB) viene acceso.

Non appena viene rilevata attività sul bussi ritorna dallo stato di sleep, facendoesattamente le operazioni opposte, cioèdisattivando l'interrupt ACTIVITYed attivando UIDLE per rilevare la prossima mancanza di traffico.Inoltre il led4 viene spento.

Page 62: Corso PIC-USB

86 aprile 2005 - Elettronica In

CCoorrssoo PPIICC-UUSSBB

RemoteWakeUp

Questa routine presente nel firmware Microchippermette di informare l'host che, dopo uno statodi sospensione, il dispositivo è di nuovo prontoper comunicare. In pratica, nell'entrare in unostato di sospensione il dispositivo chiede all'hostdi bloccare tutto il traffico sul bus, inclusi isegnali SOF; successivamente, ad esempio alverificarsi di un preciso evento, il device rientradallo stato di sospensione e avverte l'host che iltraffico può ricominciare. La capacità di un di-spositivo di gestire il segnale di "resume" deveessere autorizzata dall'host secondo le specificheUSB1.1. e rappresenta una caratteristica opzio-nale che deve essere pienamente controllabile

dall'host, tant'è che se un dispositivo supporta ilremote wakeup deve anche supportare la possibi-lità di abilitare o disabilitare tale capacità attra-verso delle richieste USB standard come set_fea-ture e clear_feature. In particolare, il remotewakeup deve essere predisposto attraverso ildescrittore Configuration.Nel campo bmAttributes di quest'ultimo, al bit5abbiamo un flag che stabilisce se il device sup-porta il remote wakeup (bit5=1) oppure no(bit5=0). In tutti i descrittori che abbiamocostruito avevamo già abilitato questa feature,per utilizzare la quale bisogna effettuare la solitamodifica nel file USB_ch9.asm, anteponendoall'etichetta RemoteWakeUp il carattere under-score. Ma vediamo nel Listato 6 come si presen-ta il codice di questa funzione. Anche in questo

di entrare in uno stato di sospensione e di prepa-rarsi al processo di propagazione del segnale diresume. Ciò perché ogni hub che si trova in stato disospensione funziona da ripetitore e non appenariceve tale segnale lo propaga sia alla porta diupstream che a tutte quelle di downstream; cosìfacendo, il segnale viene ripetuto verso tutti glihub della rete fino ad arrivare all'host, o ad unhub non sospeso che prende il controllo di talesegnale: questo processo viene detto rebroadcast.Nel nostro caso la procedura risulta relativamen-te più semplice, in quanto abbiamo supposto dilavorare in un sistema con due soli livelli esclu-dendo la presenza di hub intermedi, pertanto ilsegnale di "resume" viene preso in carico imme-diatamente dall'host attraverso il RootHub.

caso il codice è piuttosto chiaro. Nella primaparte viene verificato il flag per stabilire se il dis-positivo è abilitato all'operazione. Poi c'è unasezione, praticamente identica a quella finaledella CheckSleep, dove viene abilitato l'UIDL edisabilitato il segnale di ACTIVITY; in questomodo, quando sul bus non si rileva traffico perpiù di 3ms, viene generato un nuovo interrupt.Infine c'è il ciclo per l'invio del segnale di "resu-me", attraverso il quale il dispositivo informal'host che è nuovamente pronto a comunicare.Secondo le specifiche USB 1.1, un dispositivoabilitato al remote wakeup non può inviare talesegnale se prima non c'è stata un'assenza di traf-fico per almeno 5ms. Questo perché in tal modo si dà il tempo all'Hub

RemoteWakeupBanksel USB_status_device;btfss USB_status_device, 1return

bsf STATUS, RP0 ; BANK 3bcf UCTRL, SUSPNDbsf UIE,UIDLEbcf UIR,UIDLEbcf UIE,ACTIVITYbcf UIR,ACTIVITYbsf UCTRL, 2 ; RESUME SIGNALINGbcf STATUS, RP0 ; BANK 2clrf innermovlw 0x80movwf outerpagesel RemoteLoop

RemoteLoopdecfsz inner, fgoto RemoteLoopdecfsz outer, fgoto RemoteLoopbsf STATUS, RP0 ; BANK 3bcf UCTRL, 2 ; Clear Resume bitreturn

L I S TA TO 6Viene verificato l'USB_status_device, una variabileche viene valorizzata quando si carica il descrittoreconfiguration. Contiene lo stesso valore del bit5 delcampo bmAttributes, quindi 1 se il device è abilitatoal Remote Wakeup. Nel caso sia 0 il controllo ripassaal programma principale.

Viene abilitato il segnale di UIDLE per rilevareil prossimo stato di "idle" del bus mentre si disattivail segnale di ACTIVITY.

Dopo il RemoteLoop necessario a far sì cheil segnale di "resume" sia presente sul bus per unintervallo di tempo sufficiente, il bit2 viene riportato a0 per continuare con le normali operazioni.

Se il bit2 del registro UCTRL viene posto a 1 si abilitail modulo USB ad inviare il segnale di "resume".Secondo le specifiche USB, esso deve durare tra1ms e 15ms. Ecco perché nelle successive istruzionivengono utilizzati i 2 soliti contatori inner e outer perattendere il tempo necessario.

Page 63: Corso PIC-USB

Elettronica In - aprile 2005 87

CCoorrssoo PPIICC-UUSSBB

StallUSBEP/UnstallUSBEP

A volte può essere necessario bloccare la comu-nicazione sugli endpoint fino al verificarsi di undeterminato evento. Si pensi ad esempio almomento in cui si rileva che nella stampante nonc'è più carta e si deve attendere fino a che non siè concluso l'intervento da parte dell'utente.Ebbene, attraverso StallUSBEP si informa l'hostche la comunicazione su un determinato end-point viene bloccata, mentre con UnstallUSBEPsi riapre la comunicazione. Il numero relativoall'endpoint viene passato alla funzione tramite ilregistro W. La funzionalità viene sviluppataattraverso un flag chiamato EP_STALL apparte-nente al registro UEPn (USB Endpoint ControlRegister). Quando viene valorizzato a 1 il relati-vo Endpoint viene bloccato (si porta in una posi-

>

STALLO:@ movlw 0x01call StallUSBEP ' Comunicazione disattivata Pause 2000 ' Attesa@ movlw 0x01call UnstallUSBEP ' Comunicazione riattivata

L I S TA TO 7

StallUSBEPbsf STATUS,IRP ; select banks 2/3andlw 0x03addlw low UEP0movwf FSRbsf INDF,EP_STALL ; set stall bitreturn

L I S TA TO 8Indirizzamento del flag di stallo aggiungendoall'indirizzo base UEP0 il valore degli ultimi 2 bitpassati nel registro w.

Vediamo di analizzare anche in questo caso il listato delle due funzioni:

memoria RAM del PIC. In pratica, accedendo aINDF possiamo accedere alla locazione il cuiindirizzo è contenuto in FSR (leggendo INDFquando FSR=0Ch si legge il valore contenutonella cella 0Ch della RAM). Quindi nella routi-ne, a seconda del valore passato in W, viene cal-colata la locazione di memoria che controlla ilrelativo endpoint. Nella memoria del PIC esisto-no tre SFR(Special Function Register) chiamatiUEP0 (198h), UEP1 (199h), UEP2 (19Ah) checontengono i flag di controllo per ciascun end-point secondo la struttura di Figura 2.Focalizziamo la nostra attenzione sul bit0. Nellaroutine viene operato un AND logico tra W e ilvalore 3, così da estrarre gli ultimi 2 bit del regi-stro (non avrebbe scopo leggere gli altri visto chegli endpoint disponibili sono 0,1,2).Successivamente viene aggiunto l'indirizzo della

Fig. 2

zione di stallo). Per utilizzare questa funzionepossiamo fare la solita modifica dell'underscore,avendo l'accortezza di valorizzare il registro Wprima di fare la call alla funzione. Ad esempio, sedobbiamo bloccare la comunicazionesull'Endpoint1 useremo le istruzioni dei Listati 7e 8. Per capire come funziona bisogna tenere pre-sente che INDF e FSR ci permettono di realizza-re l'indirizzamento indiretto all'interno della

locazione UEP0, in modo da posizionarci esatta-mente sul registro che vogliamo modificare.Supponendo che W sia 1, la routine calcola198+1=199: esattamente la locazione contenenteil registro UEP1. Valorizzato FSR attraverso unbsf (Bit Set f) su INDF viene posto a 1 il flagEP_STALL, che corrisponde al bit0 del registro.Così si blocca la comunicazione sul Endpoint1.Se andiamo a vedere come è fatta la

bit7-4: Riservati e letti a 0.bit3-1: Stabiliscono se un endpoint è abilitato, oltre alla sua direzione.bit0: E� il bit di stallo che blocca o sblocca la comunicazione sull'endpoint.

Page 64: Corso PIC-USB

88 aprile 2005 - Elettronica In

CCoorrssoo PPIICC-UUSSBB

UnstallUSBEP vedremo un comportamento spe-culare come nel Listato 9. Infatti si accede al bitdi stallo valorizzando FSR, azzerandolo invece diporlo a 1. La comunicazione sul relativo endpointpuò quindi riprendere. Si tenga ben presente lastruttura degli UEPn (USB Endpoint ControlRegister) perché la approfondiremo nel prossimoparagrafo.

Firmware Microchip:ottimizzazioni e modifiche

Ottimizzare spazio

Tutte le funzioni che abbiamo visto fino ad orasono senz'altro utili e ci permettono di realizzareprogrammi capaci di soddisfare buona parte dellenostre esigenze; le routine possono comunqueessere "alleggerite", ad esempio per cambiare ilfunzionamento dei dispositivi nel caso si debba-

mente cancellato per rendere il programma piùbreve e risparmiare nell'utilizzo delle limitaterisorse del PIC. Ad esempio, lo stato del disposi-tivo viene segnalato attraverso la PORTB; talefunzionalità, sicuramente utile in fase di testingma non necessaria in un prodotto finito, puòessere rimossa semplicemente eliminando ladefine SHOW_ENUM_STATUS che abbiamoinserito nel programma PicBasic (risparmio 209byte). Ancora, il firmware prevede una defineCOUNTERERRORS per il conteggio delle varietipologie di errore attraverso i segnali di interruptgestiti dal registro UEIE (USB Error InterruptEnable Register); rinunciando a tale definizionerisparmieremo un po' di codice (315 byte) con 14byte di RAM che servono per i 7 contatori da 16bit. Infine, in tutti i casi in cui una determinatafunzione non viene utilizzata è bene eliminarne ilrelativo codice. Prendiamo ad esempio il nostroprimo esperimento: il TermoUSB; in esso abbia-

UnstallUSBEPbsf STATUS,IRP ; select banks 2/3andlw 0x03addlw low UEP0movwf FSRbcf INDF,EP_STALL ; clear stall bitreturn

L I S TA TO 9

Indirizzamento del flag di stallo aggiungendoall'indirizzo base UEP0 il valore degli ultimi 2 bit passati nel registro w.

Fig. 3

Fig. 4

La complilazione prima e dopo i tagli:

no realizzare particolari progetti. Nella maggiorparte dei casi all'interno di un sistema non ven-gono utilizzate tutte le funzioni del firmware,pertanto il relativo codice può essere tranquilla-

mo utilizzato soltanto l'endpoint1 IN, quindi pos-siamo tranquillamente eliminare la PutEP2, laGetEP1, e la GetEP2 dal file usb_defs.inc, com-mentando le relative istanze nel file

Page 65: Corso PIC-USB

Elettronica In - aprile 2005 89

>

CCoorrssoo PPIICC-UUSSBB usb_ch9.asm. Le Fig. 3 e 4 mostrano la compila-

zione prima e dopo i tagli operati: il compilato è1153 byte più piccolo. Se poi eliminiamo anchetutte le funzionalità avanzate che non ci interes-sano (CheckSleep, RemoteWakeUp ecc.) si arri-va a risparmiare altri 400 byte circa.Usando IC-PROG, caricando i due hex rispetti-

vamente sul buffer 1 e 2 è possibile metterli aconfronto: appare chiaro come ci sia un discretorisparmio di locazioni nella pagina 3 (1800h -1FFFh); infatti il primo hex occupa le locazionidall'indirizzo 1800h al 1EB7h, mentre il secondova dal 1800h al 1DA2h, con una differenza di277 words. Si consideri che il compilatore segna-la un'occupazione di 142 words, riferendosiesclusivamente alla sezione di codice iniziale cheva in entrambe i casi da 00h a 8Dh terminandonella pagina 0. Per maggior chiarezza si veda loschema. di Fig. 5, che riassume l'organizzazionedella "program memory" nel PIC16C745.Quanto detto va tenuto ben presente quando sidevono creare progetti complessi, che richiedonola maggior quantità possibile di locazioni liberedi memoria.

Modificare la configurazione degli endpoint

In tutti i nostri progetti abbiamo utilizzato la con-figurazione di default degli endpoints, agendosoltanto sui descrittori per informare l'host sulmodo con cui intendevamo comunicare. Si prestiperò attenzione al fatto che, per modificare ilmodo in cui il PIC fisicamente invia e riceve idati, non basta manipolare i descrittori. Nel pre-cedente paragrafo abbiamo visto che esiste una

TERMOUSB.HEX Vers. 1 sezione 1DA0h - 1EB7h TERMOUSB.HEX Vers. 2 sezione 1DA0h - 1EB7h

Fig. 5

1DA0: 23B3 0008 2CD3 1683 0826 0084 1283 1783 ³.Ó�&"��1DA8: 0852 0080 1683 3001 00A5 30C8 00A4 0008 R��.¥È¤.1DB0: 0822 3C01 1C03 2CD3 0822 00D2 1903 2DBE "..Ó"Ò.¾1DB8: 1683 3003 0097 1283 1303 1586 23B3 1683 �.-�.�³�1DC0: 1703 30C8 00AA 3008 00A9 3088 00A8 3008 .Ȫ.©�¨.1DC8: 00AD 30D0 00AE 3048 00AC 30D8 00B2 3008 ЮHز.1DD0: 00B1 3088 00B0 3008 00B5 30D8 00B6 3048 ±�°.µØH1DD8: 00B4 300E 0099 300E 009A 0008 1683 0817 ´.�.�.�.1DE0: 3A03 1D03 2CD3 1283 0824 3C00 1C03 2CD3 ..Ó�$..Ó1DE8: 0824 3E2B 0084 1783 0800 00F1 1683 0826 $+"�.ñ�&1DF0: 0084 0871 0080 3001 00A5 30C8 00A4 0008 "q�.¥È¤.1DF8: 1683 0817 1283 3903 3A03 1D03 2CD3 0824 �.�...Ó$1E00: 3E2B 0084 1783 0822 0080 23B3 0008 1683 +"�"�³.�1E08: 1703 1783 0826 0084 1283 1703 01C0 0840 .�&"�.À@1E10: 0245 1903 2E1F 0BC4 2E16 2E1E 2014 0080 E..Ä...�1E18: 0AC0 0A84 0FAE 2E0F 0AAF 2E0F 01D3 0840 À"®.¯.Ó@1E20: 1683 00A5 3040 0624 3940 3888 00A4 0008 �¥@$@�¤.1E28: 0008 0008 0820 3A21 1903 2E43 0820 3A22 ...!.C."1E30: 1903 2EB2 0820 3A23 1903 2EB2 0820 3AA1 .².#.².¡1E38: 1903 2EB2 0820 3AA2 1903 2EB2 0820 3AA3 .².¢.².£1E40: 1903 2EB2 2CD3 0821 3A01 1903 2EB2 0821 .²Ó!..²!1E48: 3A02 1903 2EB2 0821 3A03 1903 2EB2 0821 ..²!..²!1E50: 3A06 1903 2E60 0821 3A09 1903 2EB3 0821 ..`!..³!1E58: 3A0A 1903 2EB2 0821 3A0B 1903 2EB2 2CD3 ..²!..²Ó1E60: 1283 1703 3006 00D3 3008 00C5 0823 3A01 �..Ó.Å#.1E68: 1903 2E77 1003 0D24 200A 00AE 1003 0D24 .w.$.®.$1E70: 3E01 200A 00AF 2014 00C4 0AAE 2E8D 0823 ..¯.Ä®�#1E78: 3A02 1903 2E88 1003 0D24 200A 00AE 1003 ..�.$.®.1E80: 0D24 3E01 200A 00AF 2014 00C4 0AAE 2E8D $..¯.Ä®�1E88: 0823 3A03 1903 2CD3 0008 0827 1D03 2E95 #..Ó.'.o1E90: 0826 0244 0826 1803 00C4 0AC4 2607 0008 &D&.ÄÄ..1E98: 3006 00D3 3008 00C5 303E 00AE 3018 00AF .Ó.Å>®.¯1EA0: 2014 00C4 08A7 1D03 2EA9 0226 0826 1C03 .ħ.©&&.1EA8: 00C4 0AC4 2607 0008 0008 0853 3A06 1903 ÄÄ...S..1EB0: 2607 0008 2CD3 3021 00D3 1683 1703 0008 ..Ó!Ó�..

1DA0: 1683 1703 0008 3FFF 3FFF 3FFF 3FFF 3FFF �..ÿÿÿÿÿ1DA8: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DB0: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DB8: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DC0: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DC8: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DD0: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DD8: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DE0: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DE8: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DF0: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1DF8: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E00: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E08: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E10: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E18: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E20: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E28: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E30: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E38: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E40: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E48: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E50: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E58: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E60: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E68: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E70: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E78: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E80: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E88: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E90: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1E98: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1EA0: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1EA8: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ1EB0: 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF ÿÿÿÿÿÿÿÿ

Page 66: Corso PIC-USB

90 aprile 2005 - Elettronica In

CCoorrssoo PPIICC-UUSSBB

struttura a registri specifica che controlla l'abili-tazione e la direzione degli endpoint. Se andiamoa vedere come si compongono i registri UEP0,UEP1, UEP2 scopriamo che EP_CTL_DIS (bit3), EP_OUT_EN (bit2), EP_IN_EN (bit1) sonoriservati proprio a tale scopo; la Tabella 1 illustrala valorizzazione di questi 3 bit.Nel momento in cui utilizziamo il firmwareMicrochip, viene definita una configurazione didefault che prevede EP0 abilitato IN/OUT e pac-chetti di controllo, EP1 abilitato IN/OUT ed EP2abilitato IN/OUT. Ricordiamo che, per definizio-ne, i dispositivi low-speed utilizzano esclusiva-mente EP0 per veicolare informazioni di control-lo. Come avevamo già visto, vengono riservati

Set_Configuration per gli altri. Entrambe si tro-vano nel file USB_ch9.asm, pertanto se volessi-mo modificare tale configurazione dovremmocambiare la lista di istruzioni linea 1661 diusb_ch9 (vedi Listato 10).Per ogni Endpoint vengono valorizzati i relativiBC (Byte Counter), AL(Address Low) eST(Descriptor Status); al termine si modificano iregistri UEPn. Nei nostri precedenti esperimentinon abbiamo avuto alcuna necessità di modifica-re tale struttura perché risultava più che sufficien-te; ci siamo limitati a precisare dei descrittori cheformalmente definivano la sezione di comunica-zione che avremmo utilizzato. Ben consci cheavremmo utilizzato una configurazione fisica pre-

Tabella 1

banksel BD1OALmovlw USB_Buffer+0x10 ; Endpoint 1 OUT gets a buffermovwf BD1OAL ; set up buffer addressmovlw 8movwf BD1OBC ; set byte countmovlw 0x88 ; set own bit of EP1 (SIE can write)movwf BD1OSTmovlw 8movwf BD1IBC ; set byte countmovlw USB_Buffer+0x18 ; Endpoint 1 IN gets a buffermovwf BD1IAL ; set up buffer addressmovlw 0x48 ; set own bit of EP1 (PIC can write)movwf BD1ISTmovlw USB_Buffer+0x20 ; Endpoint 2 OUT gets a buffermovwf BD2OAL ; set up buffer addressmovlw 8movwf BD2OBC ; set byte countmovlw 0x88 ; set own bit of EP2 (SIE can write)movwf BD2OSTmovlw 8movwf BD2IBC ; set byte countmovlw USB_Buffer+0x20 ; EP1 In and EP2 In share a buffermovwf BD2IAL ; set up buffer addressmovlw 0x48 ; set own bit of EP2 (PIC can write)movwf BD2IST

; ENDPT_CONTROL - Supports IN, OUT and CONTROL transactions - Only use with EP0; ENDPT_NON_CONTROL - Supports both IN and OUT transactions

movlw ENDPT_NON_CONTROLmovwf UEP1 ; enable EP's 1 and 2 for In and Outs...movlw ENDPT_NON_CONTROLmovwf UEP2

L I S TA TO 10BD1O = Buffer Descriptor Endpoint 1 OUTVengono precisati indirizzo del buffer (AL), lunghezza in byte (BC), status (ST) valorizzandoopportunamente il bit owner.

BD1I = Buffer Descriptor Endpoint 1 INVengono precisati indirizzo del buffer (AL),lunghezza in byte (BC), status (ST) valorizzandoopportunamente il bit owner.

BD2O = Buffer Descriptor Endpoint 2 OUTVengono precisati indirizzo del buffer (AL),lunghezza in byte (BC), status (ST) valorizzandoopportunamente il bit owner.

BD2I = Buffer Descriptor Endpoint 2 INVengono precisati indirizzo del buffer (AL),lunghezza in byte (BC), status (ST) valorizzandoopportunamente il bit owner.

EP1 e EP2 vengono configurati in maniera daessere abilitatati sia IN che OUT. EP2 peròcondivide il buffer tra IN e OUT. EP0 inveceviene definito nella routine USB_Reset

degli appositi buffer attraverso la struttura BDT(Buffer Descriptor Table) e, a causa del numerodi byte disponibili un buffer, viene condiviso traEP2 IN e EP2 OUT. Tutto ciò viene stabilitonella routine USB_Reset per EP0 e

stabilita. In generale, possiamo dire che una simi-le struttura riesce a soddisfare buona parte delleesigenze perché permette di abilitare comunica-zioni sia unidirezionali che bidirezionali.Nello specifico, se dobbiamo realizzare una

Page 67: Corso PIC-USB

Elettronica In - aprile 2005 91

comunicazione diretta da Device a Host possiamotranquillamente utilizzare EP1IN e EP2IN, rag-giungendo un data rate di 1600 byte/sec, diciamo,più che sufficiente. Ma se, per qualche motivo,dobbiamo abilitare EP2 IN e EP2 OUT (unicaconfigurazione impossibile vista la condivisionedel buffer) ora sappiamo dove andare ad inserirele nostre istruzioni. Se poi abbiamo la necessità diaumentare ancora il data rate, possiamo sfruttaredue funzioni che sono ridefinibili dall'utente e chevedremo nel prossimo paragrafo.

Personalizzare HIDGetReport e HIDSetReport

Per i dispositivi HID il firmware mette a disposi-zione due funzioni ridefinibili dall'utente, chepermettono di veicolare dati anche attraversoEP0; così facendo si può "astutamente" aumenta-re il data rate, visto che in un trasferimento inter-rupt il limite massimo di polling su EP1 e EP2 è10ms (lo si stabilisce nel descrittore ENDPOINTsecondo quanto stabilito dalle specificheUSB1.1) mentre EP0 lavora con interrogazioni

CCoorrssoo PPIICC-UUSSBB cadenzate a 1ms. Pertanto, abbiamo la possibili-

tà di moltiplicare per 10 volte in ciascuna dire-zione il data rate di base, passando da800byte/sec a 8000byte/sec. Allo scopo si utiliz-za HIDGetReport per inviare dati all'host eHIDSetReport per il percorso inverso; in partico-lare, nel firmware fornito da Microchip (fileusb_ch9.asm) c'è una routine d'esempio, allalabel HIDSetReport, che risulta commentata mache ci permette di sviluppare immediatamente uncanale di comunicazione su EP0 in maniera chefunzioni come EP1OUT. Analogamente, nel filehidclass.asm si trova un riferimento allaHIDGetReport.La manipolazione di tali routine va condotta conuna certa attenzione (non dobbiamo dimenticareche EP0 viene utilizzato in maniera esclusiva peril trasferimento dei dati di controllo: un errore sutale canale può determinare il malfunzionamentodell'intero dispositivo) e solo quando strettamen-te necessario; nella pratica, ciò si limita a casisporadici, perché il data rate base di1600byte/sec è più che sufficiente nella maggior>

STARTUP codepagesel Maingoto Mainnop

InterruptServiceVectormovwf W_save ; save Wmovf STATUS,Wclrf STATUS ; force to page 0movwf Status_save ; save STATUSmovf PCLATH,wmovwf PCLATH_save ; save PCLATH

movf FSR,wmovwf FSR_save ; save FSRpagesel TMR0TEST

; **************************; Interrupt Service Routine; **************************Process_ISRTMR0TEST

btfsc INTCON,T0IEbtfss INTCON,T0IFgoto INTTESTnop

INTTESTbtfsc INTCON,INTEbtfss INTCON,INTFgoto RBTESTnop

RBTESTbtfsc INTCON,RBIEbtfss INTCON,RBIFgoto PERIPHERALTESTnop

PERIPHERALTESTbtfss INTCON,PEIE ; peripheral interrupt?goto EndISR ; all done....

TEST_PIR1banksel PIR1movf PIR1,wbanksel PIE1andwf PIE1,w ; mask the enables with the flagsbanksel PIRmaskedmovwf PIRmaskedpagesel ServiceUSBIntbtfsc PIRmasked,USBIF ; USB interrupt flagcall ServiceUSBInt ; Service USB interrupt

STARTUP codepagesel Maingoto Mainnop

InterruptServiceVectormovwf W_save ; save Wmovf STATUS,Wclrf STATUS ; force to page 0movwf Status_save ; save STATUSmovf PCLATH,wmovwf PCLATH_save ; save PCLATH

movf FSR,wmovwf FSR_save ; save FSR

; *********************; Interrupt Service Routine; *********************;Process_ISRPERIPHERALTEST

pagesel EndISRbtfss INTCON,PEIE ;a peripheral

interrupt?goto EndISR ; all done....

TEST_PIR1bsf STATUS, RP0 ; Bank1movf PIE1,wbcf STATUS, RP0 ; Bank0andwf PIR1,w ; mask the enables with the

flagsmovwf PIRmaskedpagesel TryADIFbtfss PIRmasked,USBIF ; USB interrupt

flaggoto TryADIFbcf PIR1,USBIFbanksel UIRmovf UIR,wandwf UIE,wbanksel USBMaskedInterruptsmovwf USBMaskedInterruptspagesel USBActivitybtfsc USBMaskedInterrupts,ACTIVITY ; Is

there activity on the bus?call USBActivitypagesel USBReset

L I S TA TO 1 1 L I S TA TO 12

Punti di inserimento istruzionidi gestione dei diversi tipi diinterrupt: TMR0, RB0, PORTBChange

Page 68: Corso PIC-USB

92 aprile 2005 - Elettronica In

CCoorrssoo PPIICC-UUSSBB

btfsc PIRmasked,ADIF ; AD Done?nopbtfsc PIRmasked,RCIFnopbtfsc PIRmasked,TXIFnopbtfsc PIRmasked,CCP1IFnopbtfsc PIRmasked,TMR2IFnopbtfsc PIRmasked,TMR1IFnop

TEST_PIR2banksel PIR2movf PIR2,wbanksel PIE2andwf PIE2,wbanksel PIRmaskedmovwf PIRmaskedbtfsc PIRmasked,CCP2IFnop

; ************; End ISR, restore context and return to the Main program; ************EndISR

clrf STATUS ; select bank 0movf FSR_save,w ; restore the FSRmovwf FSRmovf PCLATH_save,w ; restore PCLATHmovwf PCLATHmovf Status_save,w ; restore Statusmovwf STATUSswapf W_save,f ; restore W without corrup-

ting STATUSswapf W_save,wretfiecode

Mainmovlw .30 ; delay 16 uS to wait for USB to resetmovwf W_save ; SIE before initializing

registersdecfsz W_save,fgoto $-1

clrf PORTBclrf PORTAbanksel TRISA ; Bank 1clrf TRISB ; Set PORTB as all outputsmovlw 0x10movwf TRISA ; Set RA4 as inputpagesel InitUSB ;call InitUSB ; initialize the USBConfiguredUSB ; bcf STATUS,RP0 bcf STATUS,RP1

;***********;CursorDemo;***********CursorDemo ->Istruzioni di rotazione del cursore del mouse

btfsc USBMaskedInterrupts,USB_RST ; is it a reset?call USBReset ; yes, reset the SIEpagesel TryADIFbtfss USBMaskedInterrupts,TOK_DNE ; is it a

Token Done?goto TryADIF ; no, skip the queueing process

CheckFinishSetAddrbanksel UIRbcf UIR, TOK_DNE ; clear Token Donebcf STATUS,RP0 ; bank 2movf USB_dev_req,w ; yes: waiting for the In xorlw SET_ADDRESS ; transaction ack-ing the

end of the set address?btfss STATUS,Zgoto TryADIF ; no - skip the rest.. just

queue the USTAT registerpagesel finish_set_addresscall finish_set_addressclrf STATUS ; bank 0

TryADIF���-> Istruzioni commentateTEST_PIR2���-> Istruzioni commentate; *************; End ISR, restore context and return to the Main pro-gram; *************EndISR

clrf STATUS ; select bank 0movf FSR_save,w ; restore the FSRmovwf FSRmovf PCLATH_save,w ; restore PCLATHmovwf PCLATHmovf Status_save,w ; restore Statusmovwf STATUSswapf W_save,f ; restore W without corrup-

ting STATUSswapf W_save,wretfiecode

ServiceUSBbanksel UIRmovf UIR,wbanksel USBMaskedInterruptsmovwf USBMaskedInterruptspagesel USBErrorbtfsc USBMaskedInterrupts,UERRcall USBErrorpagesel USBSleepbtfsc USBMaskedInterrupts,UIDLEcall USBSleeppagesel USBStallbtfsc USBMaskedInterrupts,STALLcall USBStallpagesel TokenDonebtfsc USBMaskedInterrupts,TOK_DNE call TokenDonereturn

Mainmovlw .30 ; delay 16 uS to wait for USB to resetmovwf W_save ; SIE before initializing registersdecfsz W_save,fgoto $-1

clrf STATUS ; Bank0clrf Button_RA4clrf PORTBclrf PORTAbanksel TRISA ; Bank 1clrf TRISB ; Set PORTB as all outputsmovlw 0x10movwf TRISA ; Set RA4 as inputmovlw 0x07movwf OPTION_REG pagesel InitUSBcall InitUSB ; initialize the USB

;***********; CursorDemo;***********CursorDemo

pagesel CursorDemobanksel INTCONbtfss INTCON,T0IFgoto CursorDemobcf INTCON,T0IFpagesel ServiceUSBcall ServiceUSB ;any USB tokens to process?

->Istruzioni di rotazione del cursore��.

Osservando le parti evidenziate sivede come la routine che gestiva leoperazioni dei moduli USB sia stataestratta dall'ISR, diventando unafunzione che viene richiamata almomento opportuno all'interno delprogramma principale.

Page 69: Corso PIC-USB

Elettronica In - aprile 2005 93

parte delle applicazioni. Abbandoniamo dunquequesto argomento e andiamo invece a vederequali sono le novità introdotte nella versione2.00 del firmware, resa disponibile sul sitoMicrochip.

Firmware versione 2.00

Microchip ha recentemente reso disponibile unanuova versione del firmware USB, scaricabiledal sito sotto forma di archivio compresso deno-minato USB200as (versione assembler); rispettoalle versioni 1.xx, è stata introdotta una sostan-ziale modifica nell'architettura: mentre prima leoperazioni USB venivano gestite esclusivamenteattraverso una routine (ServiceUSB) inserita nelgestore degli interrupt (ISR=Interrupt ServiceRoutine), ora tutto viene trattato direttamente dauna call all'interno del programma principale.Ciò comporta una notevole differenza nell'usodelle risorse del PIC: innanzitutto c'è una minoreoccupazione dello stack (che ha solo 8 possibililivelli) in quanto si libera la parte che primadoveva essere riservata all'ISR. In secondo luogo, quest'ultima risulta esseredecisamente più breve, il che rappresenta unbuon esempio di programmazione, visto che, perdefinizione, le procedure che gestiscono i segnali di interrupt devono restituire il più rapidamente possibile il controllo al programmaprincipale. Infine, l'utilizzo di una call permette

di mantenere totalmente il controllo sulla gestione delle operazioni USB, cosa utile quandosi devono creare progetti in cui il tempo di esecuzione è un parametro determinante.; infatti,l'esecuzione del codice necessario a gestire uninterrupt USB potrebbe creare un ritardo nonammissibile dall'applicazione. Con il nuovo firmware questo problema vienecompletamente superato, visto che è il program-matore a decidere quando avviare la ServiceUSBe quindi gestire il segnale in arrivo. Se mettiamoa confronto il main dei due pacchetti, ci accor-giamo della differenza (Listato 11 e 12).Dopo aver chiarito anche questa evoluzione delfirmware Microchip, non ci resta che iniziare adaffrontare l'ultima parte di questo corso, quellarelativa alla programmazione lato host.Infatti, se da una parte abbiamo capito come farcomunicare il nostro PIC attraverso l'interfacciaUSB, ora dobbiamo analizzare in che modo darvita all'altro interlocutore.Nella prossima puntata vedremo come il sistemaoperativo del nostro PC è in grado di comunicare con un dispositivo USB e quali funzionalità rende disponibili. Infine, analizzeremo un componente molto interessante per lo sviluppo di front-end USB inDelphi e faremo una panoramica sullo stato dell'arte in questo campo. Non mancheranno iriferimenti ai software host utilizzati nei nostriesperimenti.

CCoorrssoo PPIICC-UUSSBB

Page 70: Corso PIC-USB

n questa puntata affrontiamo un argomentopiuttosto vasto, cercando di farlo nella

maniera più chiara e sintetica possibile: lo svi-luppo di procedure per la gestione dei dispositiviad interfaccia USB; focalizzeremo la nostraattenzione sui device HID, un po’ per ridurre ilcarico di lavoro, un po' perché lo sviluppo di undispositivo HID risulta la soluzione più rapida eversatile in buona parte delle applicazioni. Ciriferiremo ai sistemi operativi Win9X e Win2Kdi Microsoft, che rappresentano la piattaformapiù diffusa. Quanto agli ambienti di sviluppo,avremo un occhio di riguardo per Delphi, vista lapresenza in rete di un ottimo componente opensource e la rapidità di sviluppo del suo IDE, cherende possibile realizzare un front-end USB inpochi minuti. Presenteremo naturalmente anchealcune altre soluzioni presenti sul mercato.

Il modello HID di Microsoft

Microsoft fornisce un framework completo perlo sviluppo di driver WDM (Windows Driver

Model) per la gestione di dispositivi HID, rap-presentato dal class driver chiamato HID-CLASS.SYS, che si trova nella directory system-dir\system32\drivers (premettiamo che persystemdir intendiamo C:\WINDOWS per Win9xe C:\WINNT per Win2K). Inoltre, fornisce undriver generico HIDUSB.SYS in grado di gestiretutti i dispositivi costruiti secondo le specificheHID. Si ricordi che tale caratteristica si stabilisceall’interno del descrittore INTERFACE (campiInterfaceClass e InterfaceSubClass); proprio lapresenza di questo file, ci permette di realizzaredei dispositivi USB facendoli funzionare senzala necessità di sviluppare uno specifico driver.Nella realtà HIDUSB si appoggia anche ad unterzo file chiamato HIDPARSE.SYS, che si trovanella medesima directory ed è un parser che per-mette la lettura dei contenuti gerarchici deidescrittori REPORT.La coppia HIDCLASS e HIDUSB implementatutte le funzionalità necessarie stabilite nelle spe-cifiche USB. Il sistema risulta sufficientementemodulare in quanto permette anche la realizza-

Elettronica In - maggio 2005 81

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

7AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittàà UUSSBBiimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorriiMMiiccrroocchhiipp..UUnn aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittàà,,vviissttaa llaa ccrreesscceennttee iimmppoorrttaannzzaa ddii qquueessttoopprroottooccoolllloo nneellllaa ccoommuunniiccaazziioonneettrraa ccoommppuutteerr ee ddiissppoossiittiivvii eesstteerrnnii..IInn qquueessttaa sseettttiimmaa ppuunnttaattaa vveeddiiaammoo lloossvviilluuppppoo ddii pprroocceedduurree ppeerr llaa ggeessttiioonnee ddiiddiissppoossiittiivvii UUSSBB mmeeddiiaannttee iill mmooddeelllloo HHIIDDddii MMiiccrroossoofftt..

a cura di Carlo Tauraso

Page 71: Corso PIC-USB

82 maggio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

zione di dispositivi compositi che presentano piùinterfacce, il che rende possibile fare in modoche il sistema operativo carichi il driver HID soloal momento opportuno.Microsoft fornisce anche una serie di altri driverper i dispositivi HID più diffusi come tastiere emouse, costituenti altrettante interfacce per com-ponenti di sviluppo di livello elevato. In genera-le, i class driver come hidclass.sys realizzano lefunzionalità comuni a un’intera classe di disposi-tivi e il produttore di un determinato dispositivorealizza per esso un driver che ne fornisca le fun-zioni specifiche. Possiamo quindi scegliere seutilizzare il driver generico hidusb oppure imple-mentarne uno che lo sostituisca. La seconda stra-da è percorribile utilizzando il DDK (DeviceDriver Kit) fornito gratuitamente da Microsoft.La cosa è piuttosto complessa in quanto stiamoparlando di un kernel-mode driver (ne esistono ditre tipi: VxD, NT legacy e WDM) cioè di uninsieme di routine in grado di accedere diretta-

spositivo USB attraverso delle funzionalità resedisponibili tramite una libreria a collegamentodinamico (DLL) dal class driver e, nello specifi-co, da hidusb.sys.In questo modo possiamo concentrarci sulla logi-ca del nostro front-end senza dover conoscere ilfunzionamento a basso livello del sistema opera-tivo sul quale lo facciamo girare.

La libreria HID.dll

Windows rende disponibile tutta una serie di APIche si trovano (raccolte in una libreria chiamataHID.dll) nella directory systemdir\SYSTEM e chepermettono la comunicazione attraverso i drivervisti nel precedente paragrafo. Analizzandole, adesempio attraverso PE-Explorer, vediamo nellerisorse una serie di stringhe che le descrivono(Listato 1).Si osservino i campi Language e Translation;1033 non è nient’altro che la trasformazione in

Language/Code Page: 1033/1252CompanyName: Microsoft CorporationFileDescription: Hid User LibraryFileVersion: 4.10.2222InternalName: hid.dllLegalCopyright: Copyright (C) Microsoft Corp. 1981-1999OriginalFilename: hid.dllProductName: Microsoft(R) Windows(R) Operating SystemProductVersion: 4.10.2222Translation: 1033/1252

L I S T A T O 1

mente all’hardware, modificare le strutture datiappartenenti al sistema operativo, eseguire istru-zioni privilegiate della CPU, quindi di codice cheviene eseguito a livello Ring0 (a riguardo, siveda l’architettura dei microprocessori Intel).Inoltre, un kernel-driver è un componente "tru-sted" del sistema operativo, pertanto può essereinstallato solo dall’account che possiede i dirittidi amministratore del computer.Il driver in questione è inoltre del tipo WDM;supporta il Pnp (Plug & Play) in modalità nativae l’interfaccia WMI (Windows ManagementInstrumentation) che permette ad una applicazio-ne di leggere, in modo standard, parametri carat-teristici di funzionamento del driver, oltre che discegliere la sua configurazione. In pratica, intra-prendere la seconda strada significherebbe doveracquisire una serie di nozioni tali che probabil-mente non basterebbero le pagine del nostro inte-ro corso sui PIC per esporle; pertanto ve lerisparmiamo e sintetizziamo la situazione dicen-do che il nostro applicativo dialogherà con il di-

decimale del LANGID 0409h che abbiamo uti-lizzato per i descrittori STRINGA del nostro di-spositivo. Per impostazione predefinita, questalibreria va a leggere le stringhe scritte in inglese.Se poi andiamo alla pagina degli Export vediamoun elenco di ben 41 funzioni, che sono fonda-mentali per dialogare attraverso l’USB (vediListato 2, nella pagina seguente).Tutti i componenti deputati allo sviluppo diapplicazioni per HID che si trovano sul mercatocreano delle interfacce più o meno semplici eadattabili a queste funzioni. Per completezzariportiamo anche le proprietà degli altri file men-zionati (vedi Listato 3).

Il progetto Jedi: un po’ di storia

JEDI è l’acronimo di "Joint Endeavour of DelphiInnovators"; si tratta di una comunità internazio-nale composta da migliaia di sviluppatori Delphi,scopo della quale è diffondere l’utilizzo di taleambiente di sviluppo e del suo fratello minore

Page 72: Corso PIC-USB

Elettronica In - maggio 2005 83

>

CCoorrssoo PPIICC--UUSSBB

Kylix. L’idea nacque un venerdì pomeriggio conla pubblicazione sulla "COBB DelphiDevelopers mailing list" di un messaggio nelquale ci si chiedeva cosa si potesse fare per ren-dere disponibili le nuove API (ApplicationProgram Interfaces) nell’ambiente Borland. Unpaio di settimane dopo nacque il sito ufficialecon una prima traduzione degli header C in unità,classi e componenti direttamente disponibili perlo sviluppo Delphi.Nel corso degli anni la cosa si è evoluta semprepiù grazie al contributo di sviluppatori in tutto ilmondo, tant’è che oggi risultano disponibilimolti componenti ed esempi di programmazione

utili per lo sviluppo di applicativi che richiama-no direttamente le funzionalità API.

Il package Hidcontroller.dpk

Se facciamo una ricerca nel codice reso disponi-bile alla pagina www.jedi-delphi.org, troviamoun interessante componente chiamatoHidController: è stato sviluppato da RobertMarquardt, un programmatore tedesco che perdiverso tempo ha ricoperto il ruolo di direttoredel progetto; può facilmente essere integratonella VCL di Delphi attraverso il file package(.dpk) incluso nell’archivio scaricato. Per instal-

HidD_FlushQueue; 1;HidD_FreePreparsedData; 2;HidD_GetAttributes; 3;HidD_GetConfiguration; 4;HidD_GetFeature; 5;HidD_GetHidGuid; 6;HidD_GetedString; 7;HidD_GetManufacturerString; 8;HidD_GetNumInputBuffers; 9;HidD_GetPhysicalDescriptor; 10;HidD_GetPreparsedData; 11;HidD_GetProductString; 12;HidD_GetSerialNumberString; 13;HidD_Hello; 14;HidD_SetConfiguration; 15;HidD_SetFeature; 16;HidD_SetNumInputBuffers; 17;HidP_GetButtonCaps; 18;HidP_GetCaps; 19;HidP_GetData; 20;HidP_GetExtendedAttributes; 21;

HidP_GetLinkCollectionNodes; 22;HidP_GetScaledUsageValue; 23;HidP_GetSpecificButtonCaps; 24;HidP_GetSpecificValueCaps; 25;HidP_GetUsageValue; 26;HidP_GetUsageValueArray; 27;HidP_GetUsages; 28;HidP_GetUsagesEx; 29;HidP_GetValueCaps; 30;HidP_InitializeReportForID; 31;HidP_MaxDataListLength; 32;HidP_MaxUsageListLength; 33;HidP_SetData; 34;HidP_SetScaledUsageValue; 35;HidP_SetUsageValue; 36;HidP_SetUsageValueArray; 37;HidP_SetUsages; 38;HidP_TranslateUsagesToI8042ScanCodes; 39;HidP_UnsetUsages; 40;HidP_UsageListDifference; 41;

L I S T A T O 2

Language/Code Page: 1033/1252CompanyName: Microsoft CorporationFileDescription: HID Class DriverFileVersion: 4.10.2222InternalName: HIDCLASS.SYSLegalCopyright: Copyright © Microsoft Corp. 1981-1999OriginalFilename: HIDCLASS.SYSProductName: Microsoft(R) Windows(R)Operating SystemProductVersion: 4.10.2222Translation: 1033/1252----------------------------------------Language/Code Page: 1033/1252CompanyName: Microsoft CorporationFileDescription: MINI NT HID PARSERFileVersion: 4.10.2222InternalName: HIDPARSE.SYSLegalCopyright: Copyright © Microsoft Corp. 1981-1999OriginalFilename: HIDPARSE.SYSProductName: Microsoft(R) Windows(R) Operating SystemProductVersion: 4.10.2222Translation: 1033/1252-----------------------------------------Language/Code Page: 1033/1252CompanyName: Microsoft CorporationFileDescription: USB Miniport Driver for Input DevicesFileVersion: 4.10.2222InternalName: HIDUSB.SYSLegalCopyright: Copyright (C) Microsoft Corp. 1981-1999OriginalFilename: HIDUSB.SYSProductName: Microsoft(R) Windows(R) Operating SystemProductVersion: 4.10.2222Translation: 1033/1252

L I S T A T O 3

Page 73: Corso PIC-USB

84 maggio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

larlo basta fare doppio clic sull’icona e, una voltaavviato l’ambiente, fare clic su Install (Fig. 1).Nella "Component Palette" appare la scheda"Project Jedi" nella quale troverete il TJvHidDe-viceController (Fig. 2) che, una volta installato, èpronto all’uso e possiamo rilasciarlo nella form

L’oggetto TJvHidDeviceController

Gestisce un insieme di altri oggetti chiamatiTjvHidDevice, ognuno dei quali rappresenta undispositivo HID presente sul nostro PC. In prati-ca per ogni HID che viene collegato alle porteUSB del sistema il controller crea un oggettoTjvHidDevice. La rete di dispositivi viene gesti-ta attraverso una lista nella quale per ciascuno èindicato lo stato: nel momento in cui scolleghia-mo un dispositivo il rispettivo oggetto non vienerimosso ma se ne aggiorna lo stato, che passa da

Fig. 1

Fig. 2

Fig. 3

del nostro progetto. Prima di vedere come usar-lo, analizziamone la struttura e le proprietà e glieventi che rende disponibili, come si usa nellaprogrammazione orientata agli oggetti.

Tabella 1 - PPRROOPPRRIIEETTAA’’

Page 74: Corso PIC-USB

Elettronica In - maggio 2005 85

>

CCoorrssoo PPIICC--UUSSBB

collegato a scollegato. In questo modo si ha uncontrollo completo su tutte le periferiche chedovranno comunicare sul bus USB. Non è quin-di necessario utilizzare più oggetti controller

nello stesso progetto: anzi, se si tenta di rilascia-re due componenti sullo stesso form si ha lasegnalazione di errore riportata in Fig. 3, che lovieta. Ma vediamo di elencare e dare una breve

Tabella 2 - MMEETTOODDII

Page 75: Corso PIC-USB

86 maggio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

spiegazione delle proprietà di questo oggetto chesovraintende al funzionamento di tutti i disposi-tivi collegati. Nel proseguire si consideri che leproprietà Public sono accessibili da qualunqueparte del programma, sia in lettura che in scrittu-ra, mentre le Read-only possono essere solo lette(Tabella 1).Vediamo ora di spiegare in sintesi i metodi del-l’oggetto TjvHidDeviceController (Tabella 2).Nella funzione CheckOutByClass abbiamo vistoche, nel registry di Windows, viene effettuata unaricerca della chiave Class; infatti durante la proce-dura di enumerazione il sistema operativo crea in

HKEY_LOCAL_MACHINE\Enum\HID\ un’appo-sita struttura descrittiva per ciascun dispositivo. Laregistrazione per il nostro cifrario di Vernam è visi-bile in Fig. 4. Ora vediamo quali sono gli eventiconnessi all’oggetto controller (Tabella 3).Attraverso le relative tabelle potete già comincia-re a delineare quali saranno le operazioni dasvolgere nello sviluppo di un’applicazione host.Molto importanti nel processo, saranno gli even-ti OnDeviceChange, OnEnumerate, OnDevice-Data, perché ci permetteranno di gestire l’interociclo vitale dell’oggetto device. Tale ciclo partedalla connessione, prosegue nell’enumerazione,

Fig. 4

Tabella 3

Page 76: Corso PIC-USB

Elettronica In - maggio 2005 87

CCoorrssoo PPIICC--UUSSBB si concretizza con la comunicazione ed infine

termina con la disconnessione.

L’uovo di Pasqua

All’interno della libreria HID.dll c’è una funzio-ne non documentata e piuttosto curiosa.

>

L’oggetto TJvHidDevice

Vediamo ora quali sono le caratteristiche piùimportanti dell’oggetto device che viene creatodal controller e che ci permette di gestire i detta-gli di ogni singolo dispositivo HID fisico colle-gato alle porte USB del nostro PC. Ci soffermia-

Probabilmente uno scherzo (sono i famosi EasterEggs) di qualche programmatore buontemponedi Microsoft.La funzione si chiama HidD_Hello e la trovatenell’elenco che abbiamo estratto tramite PE-Explorer. Essa è stata comunque resa disponibilenel componente di Marquardt ed ha la seguentedichiarazione:

function HidD_Hello (Buffer: PChar;BufferLength: ULONG): ULONG; stdcall;

Non fa altro che riempire il Buffer con la seguen-te stringa ‘Hello\nI hate Jello\n’ che tradotta initaliano suona come ‘’Salve Io Odio Jello’’.Dopodichè ritorna la lunghezza della stringa +1(=20). La cosa strana è che ritorna 20 anche se ilbuffer è più piccolo. Quando è stata scoperta, aprima vista sembrava un buon sistema per gene-rare un buffer overflow, cosa che avrebbe potutoaprire una falla di sicurezza nel sistema operati-vo; ma con buona pace degli amministratori disistema Windows, non è stato così.

mo sugli aspetti più utili per le applicazionicomuni nel settore HID e quelli che abbiamo uti-lizzato nelle applicazioni host degli esperimenti(Tabella 4).Per quanto riguarda i metodi e gli eventi disponi-bili, analizziamo soltanto quelli necessari e suffi-cienti alla realizzazione di una comunicazionebidirezionale su USB, premettendo che i disposi-tivi vengono trattati come se fossero dei filesequenziali, il che rende le cose evidentementemolto semplici.Per inviare dati al dispositivo utilizziamo laseguente funzione:

function WriteFile(var Report; ToWrite:DWORD; var BytesWritten: DWORD):Boolean;

Specificando un buffer per i valori (Report), ilnumero di bytes da inviare (ToWrite), ed unavariabile contatore per i bytes inviati(BytesWritten) è possibile realizzare una comu-nicazione diretta da host a device senza partico-

Tabella 4 - PPRROOPPRRIIEETTAA’’

Page 77: Corso PIC-USB

88 maggio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBBlari problemi. Naturalmente è necessario dimen-

sionare buffer e byte da inviare a seconda deldescrittore REPORT che abbiamo definito nelnostro firmware. È anche possibile reperire taliinformazioni leggendo una proprietà specificadell’oggetto TjvHIDDevice chiamata Caps(Capacities) la quale rende disponibile la struttu-ra visibile nel Listato 4. Propriamente, utilizza lafunzione HidP_GetCaps della libreria HID.dll diWindows. Naturalmente, se abbiamo sviluppatoil firmware del dispositivo non abbiamo alcunanecessità di richiamarla, visto che conosciamobene il dimensionamento del device. Può essereutile per controllare che non abbiamo commessoerrori. La funzione restituisce un valore booleano

procedure(const HidDev: TJvHidDevice;ReportID: Byte; const Data: Pointer; Size:Word);

Questo evento avvia automaticamente un threadche gestisce la lettura dei dati dal dispositivo erimane attivo finchè il dispositivo stesso restanello stato CheckOut. Pertanto i dispositiviCheckedIn non hanno alcun Thread avviato. Inpratica ogni volta che il dispositivo invia dei datil’evento viene attivato ed il thread carica il bufferpuntato da Data, agiornando la variabile Size conil numero di byte ricevuti. ‘’HidDev’’ è l’oggettoTJvHidDevice da cui vengono letti i dati.‘’ReportID’’ è il numero identificativo del report

a true se la scrittura va a buon fine, mentre ritor-na false nel caso contrario. Nel cifratore diVernam utilizziamo l’istruzione del Listato 5.Dispos è l’oggetto TjvHIDDevice creato dopo laconnessione e il processo di enumerazione.‘’Buf’’ è un array di byte con due elementi checontengono rispettivamente l’identificativo delreport e il carattere da cifrare. Nel nostro caso ilprimo elemento viene sempre posto a 0, visto chei nostri dispositivi possono inviare solo un report.‘’Inviati’’ invece è una variabile intera che con-terrà i bytes scritti. Sfruttiamo il valore booleanoritornato dalla funzione per scrivere nel pannelloErrori della form la stringa contenente la descri-zione dell’errore di sistema. Per quanto riguardala lettura utilizziamo l’evento OnData dell’og-getto TjvHIDDevice così definito:

inviato e nel nostro caso è sempre 0. Il puntatoreData si riferisce ad un’area di memoria che vieneriscritta ad ogni report arrivato. L’evento puòessere assegnato a ciascun dispositivo a runtimeo direttamente per tutti durante la progettazionedell’applicativo attraverso l’OnDeviceData delcontroller.Dopo aver fatto una panoramica teorica sui dueoggetti base non ci resta che passare a un po’ dipratica, analizzando il codice host degli esperi-menti che abbiamo realizzato durante il corso.

TERMOUSB - Il software

In questo esperimento dobbiamo leggere un bytecontenente il valore di temperatura campionatodal PIC sulla base delle variazioni di tensione ai

THIDPCaps = recordUsage: TUsage;UsagePage: TUsage;InputReportByteLength: Word;OutputReportByteLength: Word;FeatureReportByteLength: Word;Reserved: array [0..16] of Word;NumberLinkCollectionNodes: Word;NumberInputButtonCaps: Word;NumberInputValueCaps: Word;NumberInputDataIndices: Word;NumberOutputButtonCaps: Word;NumberOutputValueCaps: Word;NumberOutputDataIndices: Word;NumberFeatureButtonCaps: Word;NumberFeatureValueCaps: Word;NumberFeatureDataIndices: Word;

end;

L I S T A T O 4

Campi che permettono di dimensionare semplicementei buffers dell'host a seconda di quanto stabilito neldescrittore REPORT inserito nel firmware.

if not Dispos.WriteFile(Buf, 3, Inviati) thenbeginErr := GetLastError;log.ItemIndex := log.Items.Add(Format('Errore Scrittura: %s --->[%x]', [SysErrorMessage(Err), Err]));end

L I S T A T O 5

Page 78: Corso PIC-USB

Elettronica In - maggio 2005 89

>

CCoorrssoo PPIICC--UUSSBB

capi di una resistenza NTC. Il programma devetrasformare il valore intero letto in un valore ditemperatura valido a seconda della scala termo-metrica scelta e rappresentarlo su un appositopannello. Il sistema deve essere in grado diavviare la lettura a comando e identificare il di-spositivo al momento della connessione, nonché

procedure TMainForm.FormActivate(Sender: TObject);begin

HidCtl.OnDeviceChange := HidCtlDeviceChange;end;

L I S T A T O 6

procedure TMainForm.HidCtlDeviceChange(Sender: TObject);var

Dev: TJvHidDevice;I: Integer;

beginLeggi.Down := False;for I := 0 to Lista.Count - 1 dobegin

Dev := TJvHidDevice(Lista.Items.Objects[I]);Dev.Free;

end;Lista.Items.Clear;HidCtl.Enumerate;if Lista.Items.Count > 0 then Lista.ItemIndex := 0;

end;

L I S T A T O 7

La lista dei dispositivi collegati viene svuotata.

Viene avviato il processo di enumerazione.

Il dispositivo corrente è il primo della lista.

gestire il momento in cui viene disconnesso.Considerando che si deve gestire un unico dispo-sitivo è possibile utilizzare l’eventoOnDeviceData fissando a priori le operazioni daeffettuare nel momento in cui da esso arriveran-no i dati. Si è deciso invece di assegnare l’even-to OnData a runtime a un dispositivo specifico.In questo modo si utilizza un codice che può tor-nare utile nel caso si debbano gestire più disposi-tivi differenti sullo stesso bus, soluzione che puòrisultare decisamente più versatile.Analizziamo nel concreto l’unità principale delprogramma presentando le procedure e i varigestori di eventi che la compongono (vediListato 6). Nel momento in cui la Form principa-le viene creata ed attivata assegnamo l’eventoOnDeviceChange che viene eseguito nelmomento in cui si avvia l’applicazione ed il di-spositivo risulta già collegato. La CPU quindiprende in carico il codice espresso nel Listato 7.La lista dei dispositivi viene completamentesvuotata.Si noti che la ListBox presente sul Form è unacollezione di oggetti. In ciascun elemento di que-sto vettore un po’ particolare viene memorizzatol’oggetto device corrispondente a ciascun dispo-sitivo fisico presente sul bus. Dopo aver ‘’pulito’’

la collezione viene avviato il processo di enume-razione (HidCtl.Enumerate). Al termine si ponecome dispositivo corrente il primo della lista.Molti di voi avranno capito che la soluzione èabbastanza semplicistica, visto che potremmoavere diversi dispositivi collegati con caratteristi-che completamente differenti dal TermoUSB.Beh, questo è il momento giusto per introdurreuna modifica implementativa che rende la cosapiù funzionale. Anziché assegnare il primo di-spositivo trovato dovremmo fare una ricerca sulbus fino a trovare il nostro dispositivo, cosa chesi può fare semplicemente attraverso la

CheckOutByProductName, passando come para-metro la stringa ‘’ThermoUSB PIC-USBCourse’’ che abbiamo inserito nel descritto-re del nostro device. L’enumerazione avvienecome nel Listato 8.La procedura estrae il nome del prodotto e loaggiunge alla lista presente sul Form. Nel caso lastringa nome prodotto sia nulla, viene utilizzatauna descrizione composta da VendorID eProductID. Non è il nostro caso ma in questomodo si vede come si può utilizzare la proprietàAttributes dell’oggetto TjvHiddevice.Successivamente il dispositivo viene estrattodalla lista tramite l’operazione di CheckOut esfruttando l’indice Idx che viene passato dallafunzione di enumerazione. Dopo il CheckOut ildispositivo è pronto per essere utilizzato pertan-to viene inserito nella collezione di oggetti. Altermine vengono valorizzati i campi del pannelloID-Dispositivo del form principale estraendo icampi che interessano (Nome prodotto, vendito-re, relativi ID e numero seriale).Realizzando la modifica che comporta la ricercadel dispositivo fate attenzione a modifcare anchel’enumerazione in quanto non si può fare ilCheckOut di un dispositivo che è stato già estrat-to dalla lista. Nel caso il dispositivo venga con-

Page 79: Corso PIC-USB

90 maggio 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

nesso o disconnesso si eseguono i relativi aggior-namenti sullo stato dello stesso. Naturalmente,da ciò consegue anche un OnDeviceChange per-tanto vengono aggiornati anche i controlli ine-renti la lista di dispositivi (Listato 9).Arriviamo quindi alla parte più importante, lagestione della lettura dati che viene attivata nelmomento in cui si fa clic sul bottone relativo

un ultimo controllo sull’accessibilità del disposi-tivo (HasReadWriteAccess) e se il controllo va abuon fine si assegna l’evento OnData del device,altrimenti il relativo puntatore viene posto a nil.Questa è l’assegnazione di Runtime di cui aveva-mo parlato all’inizio. Naturalmente consideran-do la semplificazione secondo cui dialoghiamocon un unico device avremmo potuto assegnare

function TMainForm.HidCtlEnumerate(HidDev: TJvHidDevice;const Idx: Integer): Boolean;

varN: Integer;Dev: TJvHidDevice;

beginif HidDev.ProductName <> '' thenN := Lista.Items.Add(HidDev.ProductName)elseN := Lista.Items.Add(Format('Device VID=%.4x PID=%.4x', [HidDev.Attributes.VendorID, HidDev.Attributes.ProductID]));

HidCtl.CheckOutByIndex(Dev, Idx);Lista.Items.Objects[N] := Dev;

edit1.Text:=inttostr(Dev.Attributes.ProductID);edit2.Text:=Dev.ProductName;edit3.Text:=inttostr(Dev.Attributes.VendorID);edit4.Text:=Dev.VendorName;edit5.Text:=Dev.SerialNumber;

Result := True;end;

L I S T A T O 8

Valorizzazione lista del form principale.

CheckOut del dispositivo tramite l’Idx e inserimentonella collezione di oggetti.

Valorizzazione pannello ID-Dispositivo del formprincipale.

procedure TMainForm.HidCtlArrival(HidDev: TJvHidDevice);beginEdit6.Text:='Connesso';end;

procedure TMainForm.HidCtlRemoval(HidDev: TJvHidDevice);beginEdit6.Text:='Disconnesso';end;

L I S T A T O 9

Dispositivo che viene connesso ad una porta USB.

Dispositivo che viene sconnesso da una porta USB.

(Listato 10). Dopo il clic viene effettuato un con-trollo sui parametri NTC per evitare errori comu-ni, nel caso vengano rilevate delle incongruenzeviene rilasciato il bottone (Leggi.Down=false)altrimenti viene calcolato il valore ‘’raz’’ che cor-risponde ai gradi per ciascun livello logico nel-l’intervallo di temperatura che l’utente ha impo-stato. Il sistema è fissato su parametri stabilitiattraverso una NTC con R25 a 33 kohm e nonviene prevista la possibilità di salvare i nuoviparametri se non per la singola sessione di lavo-ro. Per rendere le cose più professionali, un’ideapuò essere quella di salvare i parametri in un filedati che viene riletto ad ogni avvio. L’oggettodevice corrente viene valorizzato sulla basedell’ItemIndex attuale della lista di oggetti, nelnostro caso è il primo in elenco. Viene effettuato

l’evento in maniera comune a tutti direttamentedurante la progettazione dell’applicazione. Lascelta fatta però appare molto più versatile edinamica. Ecco quindi la procedura eseguita nelmomento in cui il dato è reso disponibile dal PICe quindi si avvia l’evento OnData (Listato 11).La procedura è relativamente semplice in quantoil valore scambiato è unico, pertanto sappiamogià che size sarà pari a 1, quindi leggiamo il buf-fer indirizzando immediatamente il primo ele-mento. Altrimenti avremmo dovuto realizzare unciclo for che legge in sequenza i vari elementiinviati. Una volta recuperato il valore, per estrar-re la temperatura bisogna elaborarlo sulla basedei parametri NTC. Per impostazione predefinitasi calcola il valore Celsius, poi, a seconda dellascelta fatta nel RadioGroup, esso viene trasfor-

Page 80: Corso PIC-USB

Elettronica In - maggio 2005 91

mato in base alla scala termometrica. Per ultimosi invia il dato rilevato all’LCD e al log. A pro-posito: abbiamo utilizzato un componente freescaricabile dalla rete (TLCD_Label) anche perl’LCD.Il codice che abbiamo visto è solo un esempiodidattico ed è migliorabile in molti punti: prende-telo come spunto per lo sviluppo professionale.

CCoorrssoo PPIICC--UUSSBB

PWMUSB - Il software

Nel secondo esperimento avevamo realizzato uncontroller PWM per piccoli motori DC, sfruttan-do l’uscita preposta sulla nostra demoboard elasciando all’intraprendenza del lettore la possi-bilità di adeguare il tutto attraverso l’uso di unMOSFET di potenza. L’esempio permetteva di >

procedure TMainForm.LeggiClick(Sender: TObject);var T1,T2,V1,V2:integer;begin

T1:=strtoint(Edit7.Text);T2:=strtoint(Edit8.Text);V1:=strtoint(Edit9.Text);V2:=strtoint(Edit10.Text);if ((T1=T2) or (V1=V2)) thenbeginmessagedlg('Errore: I parametri NTC devono definire un range.',mtcustom,[mbok],0);Leggi.down:=false;endelse if ((T1<T2) and (V1>V2)) thenbeginmessagedlg('Errore: parametri NTC incompatibili T1<T2 V1>V2',mtcustom,[mbok],0);Leggi.down:=false;endelse if ((T1>T2) and (V1<V2)) thenbeginmessagedlg('Errore: parametri NTC incompatibili T1>T2 V1<V2',mtcustom,[mbok],0);Leggi.down:=false;endelsebeginraz:=abs(T1-T2)/abs(V1-V2);Dispos := nil;if (Lista.Items.Count > 0) and (Lista.ItemIndex >= 0) thenbegin

Dispos := TJvHidDevice(Lista.Items.Objects[Lista.ItemIndex]);if not CurrentDevice.HasReadWriteAccess then

Leggi.Down := Falseelseif Leggi.Down then

Dispos.OnData := LetturaTempelse

Dispos.OnData := nil;end;

end;end;

L I S T A T O 1 0

Controlli di congruenza sui parametri NTC inseriti dall’utente. In particolare non sono ammissibili iseguenti casi:- T1=T2 e V1=V2- T1<T2 e V1>V2- T1>T2 e V1<V2

Calcolo del rapporto tra temperatura e livelli logici.

Estrazione del puntatore al dispositivo corrente edassegnazione a RunTime dell’evento OnData del device.

procedure TMainForm.LeggiTemp(HidDev: TJvHidDevice; ReportID: Byte;const Data: Pointer; Size: Word);

varw: double;Str: string;

beginStr := Format('%.2d', [Cardinal(PChar(Data)[0])]);w:=strtofloat(Str);w:=strtoint(edit7.text)-(strtoint(edit9.Text)-w) * raz;

case RadioGroup1.ItemIndex of1: w:=1.8*w+32;2: w:=w*0.8;3: w:=w+273;end;

LCD.Caption:=Format('%3.1f', [w]);

log.ItemIndex := log.Items.Add(Str);if log.ItemIndex>3 then log.Clear;

end;

L I S T A T O 1 1

Lettura del valore inviato dal PIC, calcolo dellatemperatura corrispondente in base al rapporto razcalcolato in precedenza.

Visualizzazione sul pannello LCD del valore risultante.

Visualizzazione del livello logico ricevuto dal PIC con lacancellazione del log al quarto valore.

Calcolo del valore da visualizzare sulla base della scalatermometrica selezionata.

Page 81: Corso PIC-USB

92 maggio 2005 - Elettronica In

indagare sulla comunicazione da host a devicecompletando il discorso iniziato con ilTermoUSB. Ebbene, considerato che, sfruttandoun ambiente di sviluppo RAD come Delphi laprima cosa da considerare è il riutilizzo del soft-

ware, abbiamo ripreso le procedure delTermoUSB e le abbiamo integrate con la funzionenecessaria ad inviare i dati di accensione del moto-rino al PIC. Per brevità analizziamo direttamentequesta procedura senza ripetere quelle già viste

CCoorrssoo PPIICC--UUSSBB

procedure TMainForm.ScriviClick(Sender: TObject);var

Buf: array [0..2] of Byte;Inviati: Cardinal;Err: DWORD;

beginif Assigned(Dispos) thenbegin

Buf[0]:= 0;Buf[1] := round((strtoint(Edit2.text))* 2.55);Buf[2] := round((strtoint(Edit3.Text))/5);

if not Dispos.WriteFile(Buf, 3, Inviati) thenbegin

Err := GetLastError;log.ItemIndex := log.Items.Add(Format('Errore Scrittura: %s --->[%x]', [SysErrorMessage(Err), Err]));endelsebegin

log.ItemIndex := log.Items.Add(Format('%.3d ', [Buf[1]])+ Format(' %.3d ', [Buf[2]]));Scrivi.Enabled:=false;Timer1.Interval:=1000*strtoint(edit3.Text);Timer1.Enabled:=true;end;

end;end;

L I S T A T O 1 2

Valorizzazione del Buffer, attraverso il ReportID che perdefault è il primo elemento ed è azzerato, la velocitàtradotta in livelli logici, il tempo tradotto in intervalli di

5 secondi.

Invio dei valori tramite la funzione WriteFile e gestionedell'eventuale errore.

Scrittura dei valori inviati nel log e disabilitazione delpulsante d’invio per il tempo necessario all’esecuzionedell’ istruzione di accensione da parte del PIC.

procedure TMainForm.WriteBtnClick(Sender: TObject);begin

Memo2.Clear;Memo3.Clear;Dispos := nil;Leggi.Down:=true;if (Lista.Items.Count > 0) and (Lista.ItemIndex >= 0) thenbegin

Dispos:= TJvHidDevice(Lista.Items.Objects[Lista.ItemIndex]);if not CurrentDevice.HasReadWriteAccess then

Leggi.Down := Falseelseif Leggi.Down then

Dispos.OnData := LeggiCriptoelse

Dispos.OnData := nil;end;if Assigned(Dispos) thenbeginIX:=0;JX:=1;if IX<= memo1.Lines.count thenbeginriga:=memo1.Lines[IX];if JX<= length(riga) thenbegin

Buf[0] := 0;Buf[1] := ord(riga[JX]);

if not Dispos.WriteFile(Buf, 2, Inviati) thenbegin

Err := GetLastError;log.ItemIndex := log.Items.Add(Format('Errore Scrittura: %s ---> [%x]', [SysErrorMessage(Err), Err]));end

else inc(JX);end;

end;end;end;

L I S T A T O 1 3

Cancellazione pannelli memo contenenti testocifrato e chiave.

Scaricamento del memo contenente il testo in chiaro,carattere per carattere e riga per riga. Viene utilizzata lafunzione WriteFile. In questo caso i byte da inviare sonosolo due: uno è il solito ReportID a 0 e l’altro è il codiceASCII del carattere del testo in chiaro da trasmettere.

Estrazione dalla lista dell’oggetto device corrente everifica della possibilità di accesso ad esso.

Assegnazione dell’evento OnData a RunTime per ildispositivo corrente.

Page 82: Corso PIC-USB

Elettronica In - maggio 2005 93

CCoorrssoo PPIICC--UUSSBB per il primo esperimento (Listato 12): anche in

questo caso il codice è piuttosto chiaro. Qualora ilpuntatore all’oggetto device corrente sia statoassegnato (non sia ‘’nil’’) dapprima si valorizza ilbuffer dati. Si consideri che per default il primoelemento è dato dal ReportID, che nel nostro casoè sempre pari a 0 in quanto il dispositivo gestisceun unico report. Agli altri due elementi si asse-gnano i valori relativi alla velocità convertita inlivello logico e al tempo di accensione in interval-li di 5 sec. Si sfrutta il risultato della funzione perverificare se c’è stato qualche errore. In tal casoviene emesso un apposito messaggio. Infine ivalori inviati sono visualizzati sul pannello di loge si disattiva il pulsante di Invio per fare in modoche l’accensione del motore sia terminata prima diinviare una nuova sequenza di accensione.

CifrarioUSB - Il software

Come avrete già intuito il software host delCifrarioUSB è in pratica un merge dei primi due,

memo2.Lines.Text:=memo2.Lines.Text+ Format('%.2x ', [Cardinal(PChar(Data)[0])]);memo3.Lines.Text:=memo3.Lines.Text+ Format('%.2x ', [Cardinal(PChar(Data)[1])]);

L I S T A T O 1 4

cedura LeggiCripto, la quale non fa altro che leg-gere i dati ritornati dal PIC attraverso le istruzio-ni del Listato 14.Esse trasferiscono i risultati nei relativi pannelli.Dopodichè viene richiamato nuovamente il codi-ce di scrittura dei prossimi caratteri, in questomodo ogni scrittura è cadenzata con una lettura.Non viene avviata la scrittura del carattere suc-cessivo finchè non è terminata la lettura deicaratteri del testo cifrato e della chiave.

Conclusione

Siamo arrivati al termine del nostro viaggio nellosviluppo di firmware e software per dispositiviUSB. La nostra trattazione non pretende di esse-re esaustiva ma ha voluto dare una visione abba-

stanza dettagliata del sistema di sviluppo. Si trat-ta in ogni caso di un buon punto di partenza perintraprendere qualche progetto interessante per ilPIC16C745 di Microchip. Speriamo di aver con-

realizzando un completo sistema di comunica-zione bidirezionale su USB. Per brevità elenco ilcodice relativo all’invio dei dati e alla loro rice-zione. Sarà facile riconoscere le istruzioni rica-vate dai precedenti programmi (vedi Listato 13).L’evento OnData viene gestito attraverso la pro-

tribuito alla comprensione di un’interfaccia dicomunicazione che avrà probabilmente sempremaggiore diffusione in futuro, soppiantando ivecchi sistemi (porte parallela e seriale RS232)che si stanno rivelando sempre più limitati, siaper velocità che per dinamicità d’uso.

Page 83: Corso PIC-USB

n seguito all’introduzione sul mercato daparte della Microchip della nuova famiglia

di microcontrollori a 28 pin PIC18F2455/2550,ci sembra doveroso integrare il corso di pro-grammazione PIC-USB con una serie di appro-fondimenti dedicati ai nuovi chip. L’evoluzione èdecisamente interessante sia per il fatto che que-sti micro sono dotati di memoria flash, sia perchéessi integrano le nuove funzionalità connessealla modalità full-speed. Naturalmente, tuttoquello che abbiamo spiegato nelle puntate prece-denti per la nuova famiglia di chip.È anche necessario considerare la presentazioneda parte del produttore di un nuovo frameworkche ci permette di sviluppare del firmware ingrado di sfruttare sia la stabilità della modalità abassa velocità che le prestazioni di quella full-speed. Non solo: puntualmente laMicroengineering Labs ha provveduto ad inter-pretare il firmware Microchip per adattarlo alleesigenze del compilatore PICBasic PRO, rila-sciandone la versione 2.46. Se poi aggiungiamola compatibilità “pin to pin” del

PIC18F2455/2550 con il precedentePIC16C745/765, comprendiamo come possiamofacilmente migrare i progetti presentati durante ilcorso verso la nuova piattaforma.Queste puntate di approfondimento hanno comescopo principale quello di presentare tutte leinformazioni necessarie e sufficienti all’utilizzodella nuova famiglia di PIC, illustrando le modi-fiche e le integrazioni da effettuare nel firmwarepresentato nel corso delle precedenti puntate.Vogliamo, inoltre, aggiungere alcuni concettiteorici inerenti ai trasferimenti bulk e sincroni alfine di permettere lo sfruttamento di tutte lepotenzialità di tali chip.Per concludere, studieremo un nuovo approcciodi sviluppo integrato nel framework Microchipin C18.Quest’ultimo approfondimento permetterà a tutticoloro che hanno seguito con attenzione il nostrocorso PIC-USB di disporre di un diverso punto divista che non deve mancare nel curriculum dellosviluppatore provetto. Bene, non ci resta che ini-ziare; buona lettura.

Elettronica In - giugno 2005 81

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

8AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittàà UUSSBBiimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorriiMMiiccrroocchhiipp PPIICC1188FF22445555 ee 1188FF22555500,,aarrggoommeennttoo ddii ggrraannddee aattttuuaalliittàà,,vviissttaa llaa ccrreesscceennttee iimmppoorrttaannzzaaddeellll’’UUnniivveerrssaall SSeerriiaall BBuussnneellllaa ccoommuunniiccaazziioonneettrraa ccoommppuutteerr ee ddiissppoossiittiivvii eesstteerrnnii..IInn qquueessttee ppaaggiinnee ccii ooccccuuppeerreemmoo ddeeiinnuuoovvii cchhiipp,, aannaalliizzzzeerreemmoo llaa vveerrssiioonnee22..4466 ddeell ccoommppiillaattoorree ee ssttuuddiieerreemmoo lloossvviilluuppppoo nneell ffrraammeewwoorrkk MMiiccrroocchhiipp iinntteeggrraattoo nneell CC1188.

a cura di Carlo Tauraso

Page 84: Corso PIC-USB

82 giugno 2005 - Elettronica In

>

CCoorrssoo PPIICC--UUSSBB

Le modifiche del compilatore PICBasic PRO 2.46

Partiamo immediatamente con le innovazioniintrodotte in questa nuova versione del compila-tore PICBasic PRO in maniera da poter iniziare aricompilare i nostri progetti e mettere subito infunzione il PIC18F2455/2550. Utilizzeremo lamedesima demoboard usata durante il Corso (inkit cod. K8055 oppure montata cod. VM110,Futura Elettronica), per rendere le cose più sem-plici e per poterci concentrare esclusivamente sulfirmware. Nella nuova versione oltre ad averinserito il supporto per i nuovi PIC aggiungendole relative include è stata prevista un’ulterioresottodirectory denominata USB18. Qui troviamotutti gli strumenti necessari ad affrontare lo svi-luppo per il PIC18F2455/2550. Si faccia atten-zione che è stata mantenuta anche la cartellaUSB contenente, invece, i file utilizzati per il16C745/765. Vediamo di elencare i file chiaveper la realizzazione del nuovo firmware:

1) USB18MEM.ASM2) USB18.ASM3) USB18.INC4) USBDESC.ASM5) *DSC.ASM6) *.BAS

1) Questo primo file è un gestore di memoria. Percapirne la funzione dobbiamo considerare che inuovi chip presentano un numero di endpointdecisamente superiore rispetto alla precedenteversione. Si passa da 6 a 16 endpoints bidirezio-nali. Analogamente la memoria assegnata per lagestione della BDT (Buffer Descriptor Table) edei buffer di trasferimento dati passa dai pochi64 byte a ben 1 kb. Per ottimizzare l’utilizzo diquesti spazi a seconda del numero di endpointimpiegati e del tipo di dispositivo (grazie allamodalità full-speed si possono emulare classi piùpotenti rispetto ai HID) è stato creato questo fileche permette l’allocazione corretta della memo-ria del PIC. Se proviamo ad aprire con un editoril file ci accorgeremo che uno dei parametri dibase su cui viene realizzata la struttura di memo-rizzazione è la variabile MAX_EP_NUMBER.Essa rappresenta il massimo numero di end-points utilizzato nel progetto, e verrà stabilita nelfile che raccoglie i descrittori.2) 3) In questi due file troviamo lo sviluppo delfirmware Microchip: essi sostituiscono fonda-mentalmente i fileusb_ch9.asm, usb_defs.inc,

hidclass.asm. Non vanno modificati ma sonointeressanti da analizzare per capire come sonostate sviluppate le funzioni di comunicazione sulbus USB. In particolare, il file USB18.INC per-mette la comprensione della definizione di alcu-ni importanti parametri come gli stati del dispo-sitivo, i tipi di descrittori, i tipi di trasferimentodati tutte cose che abbiamo già spiegato nelcorso. La creazione di questo nuovo frameworkha permesso di sintetizzare il tutto in due file ren-dendo il sistema più modulare. C’è da considera-re che l’interpretazione avvenuta per il PICBasictrae origine da una serie di file scritti in C18come spiegheremo nelle prossime puntate.Pertanto, le definizioni nascono fondamental-mente da un insieme di strutture dati (istruzionestruct). Sottolineiamo soltanto la presenza di unanuova struttura chiamata MUID (Microchip USBClass ID):

#define MUID_NULL 0#define MUID_USB9 1#define MUID_HID 2#define MUID_CDC 3#define MUID_MSD 4

Nel corso abbiamo parlato più volte di DeviceClass, concentrando la nostra attenzione sui di-spositivi HID che si potevano realizzare con faci-lità attraverso l’utilizzo dei PIC16C745/765.Attraverso la nuova famiglia 18F è possibilegestire anche altre tipologie come i CDC(Communication Device Class) o gli MSD (MassStorage Device). Vedremo più avanti che questastruttura è la base di una routine (USBCTRLTRF)specifica del framework Microchip e permette digestire i trasferimenti di controllo che tran-sitanosull’endpoint0. In pratica la tabella MUID racco-glie i record che identificano la classe proprieta-ria dell’attuale sessione di comunicazione. Inquesto modo il processo che deve smistare lerichieste relative alle diverse classi può passarlesenza problemi al gestore di ciascuna di esse.4) Questo file è praticamente identico a quelloche abbiamo utilizzato durante il Corso e contie-ne l’include necessaria a creare il collegamentocon il file contenente i descrittori del progetto(*DSC.ASM). L’istruzione deve essere opportu-namente modificata con il nome del file creatonei vari esperimenti.5) Contiene l’insieme dei descrittori del nostrodispositivo. Questo file dovrà essere modificatodurante lo sviluppo. Anche stavolta presentere-

Page 85: Corso PIC-USB

Elettronica In - giugno 2005 83

CCoorrssoo PPIICC--UUSSBB

#define EP0_BUFF_SIZE 8 ; 8, 16, 32, or 64#define MAX_NUM_INT 1 ; For tracking Alternate Setting#define MAX_EP_NUMBER 1 ; UEP1#define NUM_CONFIGURATIONS 1#define NUM_INTERFACES 1

#define MODE_PP _PPBM0#define UCFG_VAL _PUEN|_TRINT|_FS|MODE_PP ; Full-speed;#define UCFG_VAL _PUEN|_TRINT|MODE_PP ; Low-speed

;#define USE_SELF_POWER_SENSE_IO;#define USE_USB_BUS_SENSE_IO; *********************************************************; DEVICE CLASS USAGE#define USB_USE_HID; HID; Endpoints Allocation#define HID_INTF_ID 0x00#define HID_UEP UEP1#define HID_BD_OUT ep1Bo#define HID_INT_OUT_EP_SIZE 8#define HID_BD_IN ep1Bi#define HID_INT_IN_EP_SIZE 8#define HID_NUM_OF_DSC 1; *********************************************************DeviceDescriptor

retlw (EndDeviceDescriptor-DeviceDescriptor)/2; bLengthretlw DSC_DEV ; bDescType This is a DEVICE descriptorretlw 0x10 ; bcdUSBUSB Revision 1.10 (low byte)retlw 0x01 ; high byteretlw 0x00 ; bDeviceClassretlw 0x00 ; bDeviceSubClassretlw 0x00 ; bDeviceProtocolretlw EP0_BUFF_SIZE ; bMaxPacketSize for EP0retlw 0xD8 ; idVendor (low byte)retlw 0x04 ; (high byte)retlw 0x00 ; idProduct (low byte)retlw 0x00 ; (high byte)retlw 0x01 ; bcdDevice (low byte)retlw 0x00 ; (high byte)retlw 0x01 ; iManufacturerretlw 0x02 ; iProductretlw 0x03 ; iSerialNumberretlw NUM_CONFIGURATIONS ; bNumConfigurations

EndDeviceDescriptor; ******************************************************************USB_CD_PtrConfigs

db low Config1, high Config1db low Config1, high Config1

; ******************************************************************; Configuration DescriptorConfig1

retlw (Interface1-Config1)/2 ; bLength Length of this descriptorretlw DSC_CFG ; bDescType2 = CONFIGURATION

Config1Lenretlw low ((EndConfig1-Config1)/2) ; Length of this configurationretlw high ((EndConfig1-Config1)/2)retlw 0x01 ; bNumInterfaces Number of interfacesretlw 0x01 ; bConfigValue Configuration Valueretlw 0x04 ; iConfigString Index for this config = #01retlw 0xA0 ; bmAttributes attributes - bus poweredretlw 0x50 ; Max power consumption (2X mA)

; ******************************************************************Interface1

retlw (HIDDescriptor1-Interface1)/2 ; length of descriptorretlw DSC_INTFretlw 0x00 ; number of interface, 0 based arrayretlw 0x00 ; alternate settingretlw 0x01 ; number of endpoints used in this interfaceretlw 0x03 ; interface class - assigned by the USBretlw 0x01 ; boot deviceretlw 0x02 ; interface protocol - mouseretlw 0x05 ; index to string descriptor that describes this interface

; ******************************************************************HIDDescriptor1

retlw (Endpoint1-HIDDescriptor1)/2 ; descriptor size (9 byte)retlw 0x21 ; descriptor type (HID)retlw 0x00 ; HID class release number (1.00)retlw 0x01retlw 0x00 ; Localized country code (none)retlw 0x01 ; # of HID class descriptor to follow (1)retlw 0x22 ; Report descriptor type (HID)

; ******************************************************************ReportDescriptor1Len

retlw low ((EndReportDescriptor1-ReportDescriptor1)/2)retlw high ((EndReportDescriptor1-ReportDescriptor1)/2)

Endpoint1retlw (EndConfig1-Endpoint1)/2 ; length of descriptorretlw DSC_EPretlw 0x81 ; EP1, Inretlw 0x03 ; Interruptretlw 0x08 ; This should be the size of the endpoint bufferretlw 0x00retlw 0x0A ; polling interval (10ms)

EndConfig1

L I S T A T O 1

Diventa la TABELLA PARAMETRI GENERALI dove inseriremo una serie di valori che precisano il numeromassimo di endpoints, la grandezza del buffer endpoint0 ecc. Vengono utilizzati dalle routine firmwareper dimensionare opportunamente le strutture dati.

Diventa la TABELLA PARAMETRI CLASSE HID doveinseriremo una serie di configurazioni di inizializzazio-ne della classe di dispositivi HID che abbiamo usato diffusamente durante il corso.

Questa tabella viene divisa in cinque sezioni per rispec-chiare la sequenza dei vari descrittori.

Diventa la TABELLA 1 DESCRITTORE DEVICE riscrittadescrizione dei campi

Diventa la TABELLA DI INDIRIZZAMENTO CONFIGURATION

Diventa la TABELLA 2DESCRITTORE CONFIGURA-TION riscritta la descrizionedei campi

Diventa la TABELLA 3DESCRITTORE INTERFACEriscritta la descrizione deicampi secondo specificheUSB

Diventa la TABELLA 4DESCRITTORE HID riscritta ladescrizione dei campi

Diventa la TABELLA 5DESCRITTORE ENDPOINT

(continua)

Page 86: Corso PIC-USB

; ******************************************************************ReportDescriptor1

retlw 0x05retlw 0x01 ; usage page (generic desktop)retlw 0x09retlw 0x02 ; usage (mouse)retlw 0xA1retlw 0x01 ; collection (application)retlw 0x09retlw 0x01 ; usage (pointer)retlw 0xA1retlw 0x00 ; collection (linked)retlw 0x05retlw 0x09 ; usage page (buttons)retlw 0x19retlw 0x01 ; usage minimum (1)retlw 0x29retlw 0x03 ; usage maximum (3)retlw 0x15retlw 0x00 ; logical minimum (0)retlw 0x25retlw 0x01 ; logical maximum (1)retlw 0x95retlw 0x03 ; report count (3)retlw 0x75retlw 0x01 ; report size (1)retlw 0x81retlw 0x02 ; input (3 button bits)retlw 0x95retlw 0x01 ; report count (1)retlw 0x75retlw 0x05 ; report size (5)retlw 0x81retlw 0x01 ; input (constant 5 bit padding)retlw 0x05retlw 0x01 ; usage page (generic desktop)retlw 0x09retlw 0x30 ; usage (X)retlw 0x09retlw 0x31 ; usage (Y)retlw 0x15retlw 0x81 ; logical minimum (-127)retlw 0x25retlw 0x7F ; logical maximum (127)retlw 0x75retlw 0x08 ; report size (8)retlw 0x95retlw 0x03 ; report count (2)retlw 0x81retlw 0x06 ; input (2 position byte X & Y)retlw 0xC0 ; end collectionretlw 0xC0 ; end collection

EndReportDescriptor1; ******************************************************************langids

retlw low lang_1retlw high lang_1retlw low lang_2 ; String indexes of different languagesretlw high lang_2

lang_1 ; Englishretlw low String0 ; LangIDsretlw high String0retlw low String1_l1 retlw high String1_l1retlw low String2_l1retlw high String2_l1retlw low String3_l1retlw high String3_l1retlw low String4_l1retlw high String4_l1retlw low String5_l1retlw high String5_l1

Diventa la TABELLA 6DESCRITTORE REPORT

I campi vengono modificati in base allenostre esigenze e si riportano le defini-zioni di ciascun byte che compone i varicampi. Anche in questo caso, come per ildescrittore del corso PIC-USB, ci concen-triamo sulla definizione di un report suffi-cientemente "universale" per riutilizzarlo.

Diventa la TABELLA 7 DESCRITTORE STRINGPer ragioni di spazio non includiamo tutta la sequenza di stringhe, visto che la sua struttura è praticamente identica a quella analizzata durante ilcorso. I punti di ingresso delle stringhe definite seguono una codifica del tipo String+nr.Stringa+lnr.linguaggio: in pratica, la stringa 1 del linguaggio 2è inserita presso la label String1_l2..

84 giugno 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

mo una versione "riordinata" dello stesso perpermettere a ciascuno di voi di personalizzarlocon facilità e soprattutto di riutilizzarlo. In parti-colare, proporremo la riscrittura del nostro primoprogetto: il Termo-USB. 6) È il programma PICBasic che svolge le fun-zioni assegnate al progetto.Il nostro intervento si deve concentrare sui filedei punti 4, 5, 6. Iniziamo dai descrittori che rap-presentano la parte più importante. Anche qui,come nella seconda puntata del Corso, usiamo ilfile mousdesc.asm per analizzarne la struttura e

presentare le semplificazioni del nostro modellodi sviluppo.

Il file dei descrittori

Il mousdesc.asm rappresenta i descrittori di undispositivo che emula un mouse che ruota cicli-camente il cursore sullo schermo; si tratta di unesempio che Microchip aveva già incluso nellaprecedente versione del firmware e rappresentaun valido caso facilmente esportabile. Lo descri-ve il Listato 1, dove trovate anche le modifiche

Page 87: Corso PIC-USB

Elettronica In - giugno 2005 85

>

CCoorrssoo PPIICC--UUSSBB che apporteremo per renderlo facilmente replica-

bile. Si vede chiaramente come l’intero insiemedi descrittori risulti molto simile a quello vistodurante il Corso. Abbiamo infatti raccolto tutti icampi nelle solite sette tabelle che possono tran-

MAX_NUM_INT: è la dimensione dell’arrayche tiene traccia dei settaggi alternativi relativi aciascuna interfaccia (si ricordi che un dispositivopuò avere più interfacce, ciascuna con diversisettaggi che l’host può selezionare). In particola-re, nel caso di un dispositivo con diverse confi-gurazioni è necessario inserire in questo campo ilnumero di interfacce della configurazione che neha di più. Questa condizione è obbligatoria perevitare di indicizzare in maniera errata l’array.Per fare un esempio, se un dispositivo ha più

MAX_EP_NUMBER: è il massimo numeroendpoint utilizzato nel progetto. Si faccia atten-zione che stiamo parlando del numero che con-traddistingue l’endpoint e non il numero di end-point fisicamente utilizzati nel progetto. Non sideve considerare l’EP0, valore che viene utiliz-zato dal gestore di memoria USB18MEM.asmcome parametro fondamentale per dimensionarecorrettamente la BDT e i relativi buffer. Seponiamo MAX_EP_NUMBER a 1 verranno ini-zializzate quattro BD, due delle quali sono gene-rate di default per l’EP0 (IN e OUT) e servono aveicolare correttamente i trasferimenti di con-trollo. Le altre due sono quelle relative all’EP1(IN e OUT) secondo la Tabella 1.Siccome l’indirizzo di allocazione di ciascunaBDT è fissato a livello hardware, un numero ele-vato di questo parametro dovuto ad un utilizzonon contiguo degli endpoint può comportare unagestione inefficiente della memoria. Infatti, se unprogetto utilizza l’EP0 e l’EP4, per comunicare ilMAX_EP_NUMBER è pari a 4 (e non a 2).Questo fa sì che il gestore inizializzi anche leBDT per EP1, EP2, EP3; 24 byte che risulteran-no allocati ma inutilizzati. Naturalmente ha pocosenso saltare degli endpoint ma la precisazioneera necessaria visto che la decisione spetta esclu-sivamente allo sviluppatore.NUM_CONFIGURATIONS: è il numero diconfigurazioni del dispositivo. Negli esperimentidel Corso è sempre pari a 1.NUM_INTERFACES: è il numero di interfaccedel dispositivo. Negli esperimenti del Corso èsempre pari a 1.MODE_PP: le opzioni utilizzabili per questoparametro sono definite nel file USB18.inc(Listato 2).

Esse si riferiscono ad una particolare modalità digestione dei buffer associati a ciascun endpoint.

Tabella 1

_PPBM0 0x00 ; Pingpong Buffer Mode 0_PPBM1 0x01 ; Pingpong Buffer Mode 1_PPBM2 0x02 ; Pingpong Buffer Mode 2

L I S T A T O 2

quillamente essere riscritte con i valori inclusinel termodsc.asm del primo esperimento. La verainnovazione è tutta concentrata nella prima partedel file. Le due tabelle che raccolgono i parame-tri generali e quelli specifici della classe HID nonsono contemplate nella precedente versione delfirmware e derivano principalmente da una seriedi header C18 del framework.

La tabella dei parametri generali

Vediamo di analizzare nello specifico i singolicampi precisati nella tabella:

EP0_BUFF_SIZE: definisce la grandezza delbuffer in byte per l’Endpoint0 e quindi implicita-mente stabilisce la grandezza dei pacchetti che ildispositivo può scambiare con l’host. In praticasostituisce il valore del campo bMaxPacketSize0che si definiva nel Descrittore Device. Per i dis-positivi low-speed l’unico valore possibile è 8,mentre nella modalità full-speed si può usare 8,16, 32 o 64 byte.

configurazioni, una con due interfacce e l’altracon quattro, il campo dovrà essere pari a quattro.Finora, nel nostro Corso abbiamo sviluppatoesclusivamente dispositivi con un’unica configu-razione ed una sola interfaccia.

Page 88: Corso PIC-USB

86 giugno 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

In pratica, ad ogni endpoint viene associato undoppio buffer: uno per i trasferimenti pari, eduno per quelli dispari. In questo modo è possibi-le ottimizzare il passaggio dati, visto che la CPUpuò elaborare il contenuto di un buffer mentre ilSIE (USB Serial Interface Engine) carica l’altro.L’attuale versione del firmware permette esclusi-vamente di scegliere la modalità _PPBM0, che èproprio quella che disabilita tale possibilità.Infatti, il valore 0x00 viene registrato nei bit 0-1del registro UCFG (USB Configuration Register)del PIC che corrisponde alla voce "disabled".UCFG_VAL: questo parametro include unaserie di opzioni che sono sempre collegate ai bitdel registro UCFG (USB Configuration Register)del PIC. Vediamo i casi più importanti:

_LS o _FS: usato per stabilire se utiliz-ziamo la modalità Low-Speed o Full-Speed. Sitenga presente che nel primo caso è necessarioun clock in ingresso a 6 MHz, mentre nel secon-do caso il segnale deve "viaggiare" ad una fre-quenza di 48 MHz. Questo valore è direttamentecollegato al bit 2 del registro UCFG. I più curio-si diano un’occhiata alla pagina 168 dei data-sheet del PIC;

_PUEN: usato per stabilire se si vuoleusare delle resistenze di pull-up interne per lelinee dati USB. In particolare nel caso in cui ilprecedente parametro sia pari a LS (Low-Speed)il pull-up viene collegato alla linea D-. Nel caso,invece, il precedente parametro sia pari a FS(Full-Speed) il pull-up viene collegato alla lineaD+. Si faccia attenzione che sulla demoboard danoi usata (cod. K8055, Futura Elettronica) è giàinserita una resistenza di pull-up esterna, pertan-to non è necessario abilitare quella interna;

_TRINT o _TREXT: stabilisce se, perla comunicazione USB, si utilizza il transponderinterno o quello esterno. È collegato al bit3 delregistro UCFG. Si tratta di una possibilità offer-ta da questa nuova famiglia di PIC, che, even-

tualmente, permette di utilizzare, per la comuni-cazione, una sorta di bridge esterno. La cosa puòessere utile quando è necessario isolare il nostrodispositivo dalla porta USB.

USE_SELF_POWER_SENSE_IO: il moduloUSB può essere alimentato in diverse modalità.Quella che abbiamo utilizzato nei nostri esperi-menti è la cosiddetta "Bus Power Only" attraver-so la quale il PIC prende l’energia necessariadirettamente dal bus USB. Pertanto la relativadefine può essere tranquillamente commentata. Èpossibile attraverso questo parametro abilitare lapossibilità secondo cui il modulo utilizza unapposito pin di I/O per segnalare la presenza diuna fonte di energia alternativa al bus. Vieneusata, quindi, solo nel caso in cui si alimenti ilPIC separatamente.USE_USB_BUS_SENSE_IO: analogamente èpossibile utilizzare questo parametro per stabili-re un pin di I/O che ha la funzione di segnalare ilcollegamento ad un bus USB e quindi avviarel’attivazione del modulo relativo. Non utilizzia-mo tale possibilità quindi non commentiamoquesta define.USB_USE_HID: attraverso questa define stabi-liamo la classe di dispositivo per cui stiamo svi-luppando. Per tutti gli esperimenti del Corsoabbiamo utilizzato dei HID (Human InterfaceDevice). Nelle prossime puntate di approfondi-mento, svilupperemo anche un firmware per unadifferente classe di dispositivi, chiamata CDC(Communication Device Class: ad esempiomodem e interfacce). Vedremo in quella occasio-ne come questa definizione verrà modificata.

Fig. 1

Fig. 2

La tabella dei parametri HID

Questa struttura raccoglie una serie di parametriche stabiliscono alcune variabili specifiche dellaclasse di dispositivi HID (Human InterfaceDevice) relativamente all’allocazione degli end-points. Naturalmente, se sviluppassimo per un

Page 89: Corso PIC-USB

Elettronica In - giugno 2005 87

CCoorrssoo PPIICC--UUSSBB

>

Termodsc.asm VER PIC18Termodsc.asm VER PIC18; ***************************; TABELLA PARAMETRI GENERALI; ***************************#define EP0_BUFF_SIZE 8 #define MAX_NUM_INT 1 #define MAX_EP_NUMBER 1 #define NUM_CONFIGURATIONS 1#define NUM_INTERFACES 1#define MODE_PP _PPBM0#define UCFG_VAL _TRINT|MODE_PP#define USB_USE_HID; ****************************; TABELLA PARAMETRI CLASSE HID; ****************************#define HID_INTF_ID 0x00#define HID_UEP UEP1#define HID_BD_OUT ep1Bo#define HID_INT_OUT_EP_SIZE 8#define HID_BD_IN ep1Bi#define HID_INT_IN_EP_SIZE 8#define HID_NUM_OF_DSC 1; ****************************; TABELLA 1 DESCRITTORE DEVICE; ****************************DeviceDescriptor

retlw (EndDeviceDescriptor-DeviceDescriptor)/2 ;bLength

retlw DSC_DEV ; bDescriptorTyperetlw 0x10 ; bcdUSB (low-b)retlw 0x01 ; bcdUSB (high-b)retlw 0x00 ; bDeviceClassretlw 0x00 ; bDeviceSubClassretlw 0x00 ; bDeviceProtocolretlw EP0_BUFF_SIZE ; bMaxPacketSize0retlw 0xd8 ; idVendor (low-b)retlw 0x04 ; idVendor (high-b)retlw 0x00 ; idProduct (low-b)retlw 0x00 ; idProduct (high-b)retlw 0x00 ; bcdDevice (low-b)retlw 0x01 ; bcdDevice (high-b)retlw 0x01 ; iManufacturerretlw 0x02 ; iProductretlw 0x03 ; iSerialNumber

retlw NUM_CONFIGURATIONS ; bNumConfigurationsEndDeviceDescriptor; *****************************; Puntatore tabella di configurazione.; *****************************USB_CD_PtrConfigs

db low Config1, high Config1db low Config1, high Config1

; ************************************; TABELLA 2 DESCRITTORE CONFIGURATION; ************************************Config1

retlw (Interface1-Config1)/2; bLengthLengthretlw DSC_CFG ; bDescriptorType

Config1Lenretlw low ((EndConfig1-Config1)/2) ; wTotalLength (low-b)retlw high ((EndConfig1-Config1)/2) ; wTotalLength (high-b)retlw 0x01 ; bNumInterfacesretlw 0x01 ;

bConfigurationValueretlw 0x04 ; iConfigurationretlw 0xA0 ; bmAttributesretlw 0x32 ; MaxPower

Termodsc.asm VER PIC16Termodsc.asm VER PIC16; ****************************************; ROUTINE DI INDIRIZZAMENTO CONFIGURATION ; ****************************************OMISSIS

;**************************************; INSERIMENTO ULTERIORI CONFIGURAZIONI;**************************************

OMISSIS

; *********************************; ROUTINE DI INDIRIZZAMENTO REPORT; *********************************OMISSIS

;**************************************;PUNTO DI INSERIMENTO ULTERIORI REPORT;**************************************

OMISSIS

; ****************************; TABELLA 1 DESCRITTORE DEVICE; ****************************Descriptions

banksel EP0_startmovf EP0_start+1,wmovwf PCLATHmovf EP0_start,wmovwf PCL

DeviceDescriptorStartDevDescr

retlw 0x12 ; bLengthretlw 0x01 ; bDescriptorTyperetlw 0x10 ; bcdUSB (low-b)retlw 0x01 ; bcdUSB (high-b)retlw 0x00 ; bDeviceClassretlw 0x00 ; bDeviceSubClassretlw 0x00 ; bDeviceProtocolretlw 0x08 ; bMaxPacketSize0retlw 0xd8 ; idVendor (low-b)retlw 0x04 ; idVendor (high-b)retlw 0x00 ; idProduct (low-b)retlw 0x00 ; idProduct (high-b)retlw 0x00 ; bcdDevice (low-b)retlw 0x01 ; bcdDevice (high-b)retlw 0x01 ; iManufacturerretlw 0x02 ; iProductretlw 0x03 ; iSerialNumberretlw NUM_CONFIGURATIONS ;

bNumConfigurations; ************************************; TABELLA 2 DESCRITTORE CONFIGURATION; ************************************Config1

retlw 0x09 ; bLengthLengthretlw 0x02 ; bDescriptorType retlw EndConfig1 - Config1 ; wTotalLength (low-b)retlw 0x00 ; wTotalLength (high-b)retlw 0x01 ; bNumInterfacesretlw 0x01 ; bConfigurationValueretlw 0x04 ; iConfigurationretlw 0xA0 ; bmAttributesretlw 0x32 ; MaxPower

L I S T A T O 3

(continua)

altro tipo di classe, la tabella dovrebbe essereopportunamente modificata (lo vedremo nel casodei CDC) assieme alla precedente define. Latabella segue una struttura ripetuta per ciascunendpoint utilizzato nella comunicazione conl’host. Analizziamo i vari campi separatamentenel caso di un HID che utilizza l’EP1 IN e OUT:

HID_INTF_ID: Definisce l’identificativo del-l’interfaccia HID. Viene utilizzato dalla funzioneUSBCheckHIDRequest (inclusa nel fileUSB18.asm) che permette di stabilire se la richie-sta arrivata al dispositivo è specifica della classeHID e quindi deve essere passata al gestore rela-tivo. Per i nostri dispositivi utilizziamo il valore 0.

Page 90: Corso PIC-USB

88 giugno 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

HID_UEP: Stabilisce il registro di controllo delPIC a cui ci riferiamo nelle righe successive perla definizione dei diversi Buffer Descriptors. Neidispositivi analizzati nel nostro Corso abbiamo

utilizzato esclusivamente l’UEP1 (USBEndpoint 1 Control Register).HID_BD_OUT: Definisce il BD per l’endpointcontrollato dal registro precedente (nel caso del

; *******************************; TABELLA 3 DESCRITTORE INTERFACE; *******************************Interface1

retlw (HIDDescriptor1-Interface1)/2; bLengthretlw DSC_INTF ; bDescriptorTyperetlw 0x00 ; bInterfaceNumberretlw 0x00 ; bAlternateSettingretlw 0x01 ; bNumEndpointsretlw 0x03 ; bInterfaceClassretlw 0x01 ; bInterfaceSubClassretlw 0x02 ; bInterface Protocolretlw 0x05 ; iInterface

; *************************; TABELLA 4 DESCRITTORE HID; *************************HID_Descriptor1

retlw (Endpoint1-HIDDescriptor1)/2 ; bLengthretlw 0x21 ; bDescriptorType retlw 0x00 ; bcdHID (low-b)retlw 0x01 ; bcdHID (high-b)retlw 0x00 ; bCountryCoderetlw 0x01 ; bNumDescriptorsretlw 0x22 ; bDescriptorType

ReportDescriptor1Lenretlw low ((EndReportDescriptor1-ReportDescriptor1)/2)retlw high ((EndReportDescriptor1-ReportDescriptor1)/2); *******************************; TABELLA 5 DESCRITTORE ENDPOINT; *******************************Endpoint1

retlw (EndConfig1-Endpoint1)/2 ; bLengthretlw DSC_EP ; bDescriptorTyperetlw 0x81 ; bEndpointAddressretlw 0x03 ; bmAttributesretlw 0x01 ; wMaxPacketSize (low-b)retlw 0x00 ; wMaxPacketSize (high-b)retlw 0xFA ; bInterval

EndConfig1; ******************************; TABELLA 6 DESCRITTORE REPORT; ******************************ReportDescriptor1

retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01;Usage Page (low-b) ("Vendor Defined Page 1")retlw 0xFF;Usage Page (high-b) ("Vendor Defined Page 1")retlw 0x09 ;Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage ("Vendor Defined Usage 1")retlw xA1 ;Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Collection ("Application")retlw 0x09 ;Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage ("Vendor Defined Usage 2")retlw 0xA1 ;Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Collection ("Physical")retlw 0x06 ;Byte di prefisso (bTag,bType,bSize)retlw 0x02;Usage Page (low-b) ("Vendor Defined Page 2")retlw 0xFF;Usage Page (high-b) ("Vendor Defined Page 2")retlw 0x09 ;Byte di prefisso (bTag,bType,bSize)retlw 0x03 ; Usage ("Vendor Defined Usage 3")retlw 0x15 ;Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Logical Minimum (0)retlw 0x26 ;Byte di prefisso (bTag,bType,bSize)retlw 0xFF ; Logical Maximum (low-b) (255)retlw 0x00 ; Logical Maximum (high-b) retlw 0x75 ;Byte di prefisso (bTag,bType,bSize)retlw 0x08 ; Report Size (8 bits)retlw 0x95 ;Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Report Count (1 campo dati)retlw 0x81 ;Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Input (Data, Var, Abs)retlw 0xC0 ; End Collection ("Physical")retlw 0xC0 ; End Collection ("Application")

EndReportDescriptor1

; *******************************; TABELLA 3 DESCRITTORE INTERFACE; *******************************Interface1

retlw 0x09 ; bLengthretlw INTERFACE ; bDescriptorTyperetlw 0x00 ; bInterfaceNumberretlw 0x00 ; bAlternateSettingretlw 0x01 ; bNumEndpointsretlw 0x03 ; bInterfaceClassretlw 0x01 ; bInterfaceSubClassretlw 0x02 ; bInterface Protocolretlw 0x05 ; iInterface

; **************************; TABELLA 4 DESCRITTORE HID; **************************HID_Descriptor

retlw 0x09 ; bLengthretlw 0x21 ; bDescriptorType retlw 0x00 ; bcdHID (low-b)retlw 0x01 ; bcdHID (high-b)retlw 0x00 ; bCountryCoderetlw 0x01 ; bNumDescriptorsretlw 0x22 ; bDescriptorType

retlw (end_ReportDescriptor - ReportDescriptor) (low-b)retlw 0x00 ; wDescriptorLength (high-b); *******************************; TABELLA 5 DESCRITTORE ENDPOINT; *******************************Endpoint1

retlw 0x07 ; bLengthretlw ENDPOINT ; bDescriptorTyperetlw 0x81 ; bEndpointAddressretlw 0x03 ; bmAttributesretlw 0x01 ; wMaxPacketSize (low-b)retlw 0x00 ; wMaxPacketSize (high-b)retlw 0xFA ; bInterval

EndConfig1; *****************************; TABELLA 6 DESCRITTORE REPORTReportDescriptorLen

retlw low (end_ReportDescriptor-ReportDescriptor)retlw 0x06 ; Byte di prefisso (bTag,bType,bSize)retlw 0x01;Usage Page (low-b) ("Vendor Defined Page 1")retlw 0xFF;Usage Page (high-b) ("Vendor Defined Page 1")retlw 0x09 ;Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Usage ("Vendor Defined Usage 1")retlw xA1 ;Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Collection ("Application")retlw 0x09 ;Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Usage ("Vendor Defined Usage 2")retlw 0xA1 ;Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Collection ("Physical")retlw 0x06 ;Byte di prefisso (bTag,bType,bSize)retlw 0x02;Usage Page (low-b) ("Vendor Defined Page 2")retlw 0xFF;Usage Page (high-b) ("Vendor Defined Page 2")retlw 0x09 ;Byte di prefisso (bTag,bType,bSize)retlw 0x03 ; Usage ("Vendor Defined Usage 3")retlw 0x15 ;Byte di prefisso (bTag,bType,bSize)retlw 0x00 ; Logical Minimum (0)retlw 0x26 ;Byte di prefisso (bTag,bType,bSize)retlw 0xFF ; Logical Maximum (low-b) (255)retlw 0x00 ; Logical Maximum (high-b) retlw 0x75 ;Byte di prefisso (bTag,bType,bSize)retlw 0x08 ; Report Size (8 bits)retlw 0x95 ;Byte di prefisso (bTag,bType,bSize)retlw 0x01 ; Report Count (1 campo dati)retlw 0x81 ;Byte di prefisso (bTag,bType,bSize)retlw 0x02 ; Input (Data, Var, Abs)retlw 0xC0 ; End Collection ("Physical")retlw 0xC0 ; End Collection ("Application")

EndReportDescriptor

(continuazione Listato 3)

Page 91: Corso PIC-USB

Elettronica In - giugno 2005 89

>

CCoorrssoo PPIICC--UUSSBB nostro esempio è il numero 1) nella direzione

host->device. Allo scopo si utilizza una conven-zione di denominazione secondo il seguente for-mato: ep<#>B<d>. In esso # è il numero del-l’endpoint mentre d è la direzione di trasferi-mento, direzione che può essere sia IN (i) cheOUT (o). Nel nostro caso utilizzeremo solamen-te l’endpoint numero 1, con direzione "o" cioèOUT, quindi "ep1Bo".

HID_BD_IN: È analogo al HID_BD_OUT eriguarda l’endpoint con direzione device->host(IN). Si utilizza la stessa convenzione di denomi-nazione, pertanto, il valore è "ep1Bi".HID_INT_IN_EP_SIZE: Definisce la grandez-za in byte del buffer dell’endpoint della riga pre-cedente. Anche qui imponiamo un valore di 8.HID_NUM_OF_DSC: Definisce il numero didescrittori HID del dispositivo e, nei nostri pro-

' VERSIONE PER PIC18F'Dichiarazioni variabili applicazionetemper VAR BYTE

DEFINE OSC 24 ' Clock 24Mhz'DEFINE SHOW_ENUM_STATUS 1 'Visualizza Enumerazione

' Definizioni per l'utilizzo dell'istruzione ADCINDEFINE ADC_BITS 8 ' Bits RisultatoDEFINE ADC_CLOCK 3 ' Clock RC TAD=4uS/bit

'9,5TAD/byteDEFINE ADC_SAMPLEUS 50 ' Frequenza CampionamentouS

PORTB = 0 ' 8 LED uscite digitali spentiTRISB = 0 ' PORTB definita in uscita

INIZIO: USBInit ' Processo di enumerazione alla

fine il device' entra nello stato Configurato

TRISA = %11111111 ' PORTA tutta in ingressoADCON1= 4 ' [DDDDADAA] RA0,RA1 analogici Vdd

di rif

Pause 500 ' Attesa CONV:

ADCIN 0, temper 'Campiona segnale su RA0in temp INVIA:

USBService 'Gestione USBUSBOut 1, temper, 1, INVIA 'Invia risul-

tatoGoTo CONV ' Continua all'infinito

'VERSIONE PER PIC16C'Dichiarazioni variabili necessarie firmware USBwsave VAR BYTE $70 system 'salva Wssave VAR BYTE bank0 system 'salvaSTATUSpsave VAR BYTE bank0 system 'salvaPCLATHfsave VAR BYTE bank0 system 'salva FSR'Dichiarazioni variabili applicazionetemper VAR BYTE DEFINE OSC 24 DEFINE SHOW_ENUM_STATUS 1' Definizioni per l'utilizzo dell'istruzione ADCINDEFINE ADC_BITS 8 DEFINE ADC_CLOCK 3 DEFINE ADC_SAMPLEUS 50

PORTB = 0TRISB = 0

GoTo INIZIO ' Salta al main

DEFINE INTHAND BUSINTAsmBUSINT

movf FSR, W ;salvataggio di FSRmovwf fsavemovlw High ServiceUSBIntmovwf PCLATHbtfsc PIR1, USBIFCall ServiceUSBInt

RIPREGclrf STATUS

movf fsave, Wmovwf FSRmovf psave, Wmovwf PCLATHswapf ssave, Wmovwf STATUSswapf wsave, Fswapf wsave, Wretfie ; Torno al pgm prin-

cipaleEndAsm

INIZIO: USBInitTRISA = %11111111 ADCON1= 4 Pause 500

CONV:Pause 100ADCIN 0, temper Pause 150USBOut 1, temper, 1, CONVGoTo CONV

L I S T A T O 4

HID_INT_OUT_EP_SIZE: Stabilisce la gran-dezza in byte del buffer dell’endpoint precisatonella riga precedente. Nel nostro caso utilizzia-mo un valore pari a 8.

getti, equivale sempre a 1. Detto questo, possia-mo finalmente iniziare a riscrivere il nostrodescrittore per il Termo-USB (si veda il relativoarticolo) utilizzando il nuovo framework.

Page 92: Corso PIC-USB

90 giugno 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

Il nuovo file dei descrittori del Termo-USB

Per creare la nuova versione del file in maniera dacapire quali sono le modifiche concrete rispetto alvecchio termodsc.asm, abbiamo pensato di affian-care i due listati. Non è difficile identificare, inentrambe le versioni, le strutture dei diversidescrittori. Se escludiamo le due tabelle iniziali diparametri ed il fatto che, in varie occasioni, si sonoutilizzati dei nomi costante anziché valori discreti,possiamo tranquillamente affermare che le modi-fiche comportano, per lo sviluppatore, ben pocolavoro. La convenienza nel passaggio alla nuovafamiglia di PIC è quindi reale, visto che a fronte dipoche modifiche firmware si possono sfruttaredelle feature molto interessanti. Nel nuovo listatoabbiamo evidenziato le parti che più lo differen-ziano dal vecchio. Per questioni di spazio omettia-

ancora più semplice, visto che il gestore di cia-scuna attività della porta USB è stato concentra-to tutto in un’unica funzione chiamataUSBService. Il codice risultante non è più basatosulla gestione dei segnali di interrupt ma esclusi-vamente su una continua interrogazione dei regi-stri associati alla porta per identificare le varieoperazioni che devono essere svolte. Ci troviamoperciò nella condizione di richiamare regolar-mente (almeno ogni 10 ms) tale funzione.Mettiamo a confronto i due listati visibili con-temporaneamente nel Listato 4.Nella nuova versione si vede chiaramente lamancanza di tutta la parte inerente alla gestionedegli interrupt del modulo USB, sostituita diret-tamente dalla routine USBService. Tale routine èrichiamata sia subito dopo l’operazione di cam-pionamento, sia tutte le volte che nel buffer del-

mo i descrittori stringa, perchè sono praticamenteidentici sia per struttura che contenuto in entram-be le versioni. Le modifiche inserite nel file deidescrittori sono piuttosto semplici da realizzare; sirichiede soltanto un po’ di sforzo iniziale per"digerire" il significato dei parametri inclusi nelleprime due tabelle (Param. Generali e HID). Il fileUSBDESC.asm permette di collegare il file deidescrittori al nostro progetto e rimane essenzial-mente identico visto che abbiamo chiamato le dueversioni allo stesso modo. L’istruzione di inclusio-ne relativa è visibile nel Listato 5. Siamo arrivatiquasi alla conclusione della nostra operazione diriscrittura. Dobbiamo ancora affrontare le modifi-che al programma principale.

Il codice del programma principale

Con la nuova versione del compilatore PICBasicil listato del nostro termometro USB diventa

l’endpoint1 non c’è nulla da inviare. Per quantoriguarda il resto del listato la sequenza di istru-zioni è praticamente identica, abbiamo soltantoaggiunto la label INVIA affinché l’USBServicevenga richiamato ad intervalli di tempo quantopiù brevi possibili. A questo punto non ci restache ricompilare il nostro firmware.

La compilazione del nuovo termousb.bas

Per generare il file .hex da caricare nelPIC18F2455/2550 dobbiamo eseguire il compi-latore PBP con l’opzione -a. Tale necessità sispiega facilmente pensando che il PBP, se lacompilazione non ha errori, avvia automatica-mente l’assembler PM; il problema è che il PMnon supporta questa famiglia di microcontrollori.Se richiamiamo il compilatore alla solita manie-ra riceveremo in uscita il messaggio di Fig. 3.Dobbiamo quindi avviare il compilatore facendoin modo che sostituisca il PM con un altroassembler compatibile con la nuova famiglia diPIC. Lo stesso messaggio di errore ci indica la

Fig. 3

include "termodsc.asm" ;Descrittori TermoUSB-Esp.1

L I S T A T O 5

Page 93: Corso PIC-USB

Elettronica In - giugno 2005 91

strada da seguire: utilizzeremo l’MPASM(assembler) che esiste in due versioni:1) MPASMWIN: a 32 bit per windows distribui-ta gratuitamente assieme all’IDE MPLAB o sca-ricabile direttamente dal sito della microenginee-ring Labs (www.melabs.com) 2) MPASM: versione da linea di comando distri-buita assieme al compilatore C18 dellaMicrochip (www.microchip.com).Entrambe sono compatibili praticamente contutte le versioni dei sistemi operativi Microsoft(9X, ME, NT, 2K, XP); quella a linea di coman-do non supporta i nomi dei file lunghi, pertanto ènecessario utilizzare il formato 8.3 (nome file di

CCoorrssoo PPIICC--UUSSBB

otto caratteri, estensione di tre). Nel primo casodobbiamo utilizzare il comando:

pbpw -ampasmwin -p18f2550 termousb.bas

Al termine del processo di compilazione, seniente è andato storto, comparirà una finestracome quella di Fig. 4. Nel secondo caso la strin-ga da digitare sulla linea di comando diventa:

pbp -ampasm -p18f2550 termousb.bas

Anche qui, al termine della compilazione, avre-mo un messaggio di avvertimento (vedi Fig. 5). >

Fig. 4

Fig. 5

Page 94: Corso PIC-USB

92 giugno 2005 - Elettronica In

In entrambe le eventualità avremo generato nellastessa directory il file termousb.hex.

Il Clock

C’è ancora un piccolo problema da risolvere e loaffrontiamo ora perché direttamente collegato adun file di configurazione utilizzato dall’MPASM.Il compilatore PICBasic PRO presuppone che

CONFIG1H). Questi particolari parametri sonoletti dall’MPASM e vengono elencati nel filep18f2550.inc incluso nella directory del compila-tore. Li riassumiamo nel Listato 7.C’è da dire che la famiglia di PIC della quale cioccupiamo permette diverse modalità di genera-zione del segnale di clock: quella che il compila-tore in questione per impostazione predefinitaimpiega un moltiplicatore PLL (Phase Lock

CCoorrssoo PPIICC--UUSSBB

__CONFIG _CONFIG1L, _PLLDIV_5_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L__CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H

L I S T A T O 6

nel nostro progetto venga usata una sorgente diclock a 20 MHz. Infatti, se andiamo a verificaregli header inclusi durante la compilazione, trove-remo il file 18F2550.INC (naturalmente il nomedipende dal dispositivo scelto tramite l’opzione-p durante la compilazione). L’archivio in que-stione è salvato nella directory \pbp e contienedue stringhe fondamentali meglio definite nelListato 6.Esse stabiliscono i valori di due registri di confi-gurazione piuttosto importanti (CONFIG1L e

Loop) con un segnale in uscita a 96 MHz cheviene opportunamente suddiviso per estrarre ilclock di sistema. Nel registro CONFIG1L si pre-cisano tre campi di base:

PLLDIV (3bit): permette la selezione del circui-to prescaler, nella riga di default viene precisatoil valore che divide per 5 (PLLDIV=100b) ilsegnale in ingresso. Il PLL necessità di un segna-le a 4 MHz, pertanto è corretto che i 20 MHz pro-venienti dall’oscillatore siano divisi per cinque.

;----- CONFIG1L Options --------------------------------------------------_PLLDIV_1_1L EQU H'F8' ; No divide (4MHz input)_PLLDIV_2_1L EQU H'F9' ; Divide by 2 (8MHz input)_PLLDIV_3_1L EQU H'FA' ; Divide by 3 (12MHz input)_PLLDIV_4_1L EQU H'FB' ; Divide by 4 (16MHz input)_PLLDIV_5_1L EQU H'FC' ; Divide by 5 (20MHz input)_PLLDIV_6_1L EQU H'FD' ; Divide by 6 (24MHz input)_PLLDIV_10_1L EQU H'FE' ; Divide by 10 (40MHz input)_PLLDIV_12_1L EQU H'FF' ; Divide by 12 (48MHz input)

_CPUDIV_OSC1_PLL2_1L EQU H'E7' ; [OSC1/OSC2 Src: /1][96MHz PLL Src: /2]_CPUDIV_OSC2_PLL3_1L EQU H'EF' ; [OSC1/OSC2 Src: /2][96MHz PLL Src: /3]_CPUDIV_OSC3_PLL4_1L EQU H'F7' ; [OSC1/OSC2 Src: /3][96MHz PLL Src: /4]_CPUDIV_OSC4_PLL6_1L EQU H'FF' ; [OSC1/OSC2 Src: /4][96MHz PLL Src: /6]

_USBDIV_1_1L EQU H'DF' ; Clock source from OSC1/OSC2_USBDIV_2_1L EQU H'FF' ; Clock source from 96MHz PLL/2

;----- CONFIG1H Options --------------------------------------------------_FOSC_XT_XT_1H EQU H'F0' ; XT oscillator, XT used by USB_FOSC_XTPLL_XT_1H EQU H'F2' ; XT oscillator, PLL enabled, XT used by USB_FOSC_ECIO_EC_1H EQU H'F4' ; External clock, port function on RA6, EC used by USB_FOSC_EC_EC_1H EQU H'F5' ; External clock, CLKOUT on RA6, EC used by USB_FOSC_ECPLLIO_EC_1H EQU H'F6' ; External clock, PLL enabled, port function on RA6, EC used by USB_FOSC_ECPLL_EC_1H EQU H'F7' ; External clock, PLL enabled, CLKOUT on RA6, EC used by USB_FOSC_INTOSCIO_EC_1H EQU H'F8' ; Internal oscillator, port function on RA6, EC used by USB_FOSC_INTOSC_EC_1H EQU H'F9' ; Internal oscillator, CLKOUT on RA6, EC used by USB_FOSC_INTOSC_XT_1H EQU H'FA' ; Internal oscillator, XT used by USB_FOSC_INTOSC_HS_1H EQU H'FB' ; Internal oscillator, HS used by USB_FOSC_HS_1H EQU H'FC' ; HS oscillator, HS used by USB_FOSC_HSPLL_HS_1H EQU H'FE' ; HS oscillator, PLL enabled, HS used by USB

_FCMEM_OFF_1H EQU H'BF' ; Disabled_FCMEM_ON_1H EQU H'FF' ; Enabled

_IESO_OFF_1H EQU H'7F' ; Disabled_IESO_ON_1H EQU H'FF' ; Enabled

L I S T A T O 7

Page 95: Corso PIC-USB

Elettronica In - giugno 2005 93

CCoorrssoo PPIICC--UUSSBB CPUDIV (2bit): permette la selezione del divi-

sore da applicare al segnale di partenza da 96MHz. Per impostazione predefinita il valore èpari a 2 (CPUDIV=01b) pertanto il clock disistema "viaggia" a 48 MHz. Quest’ultima fre-quenza va bene per la modalità full-speed, manon per quella low-speed, per la quale sarànecessario utilizzare il divisore pari a quattro(CPUDIV=11b).

USBDIV (1bit): permette di stabilire se il clockviene prelevato dal moltiplicatore PLL (USB-DIV=1b) oppure direttamente dall’oscillatoresenza il postscaler. Questo campo è direttamentecollegato al registro UCFG ed in particolare albit 2 che stabilisce se la modalità full-speed èattivata o meno. Questo bit viene controllatoattraverso il parametro _FS -- _LS che abbiamovisto nella tabella parametri generali del file deidescrittori. Nel registro CONFIG1H, invece sistabilisce con un valore a 4 bit il tipo di oscilla-

i settaggi da precisare (con oscillatore a 20 MHz)nelle due modalità. Quindi, modifichiamo il file\pbp\18F2550.inc inserendo la stringa CPUDI-VOSC3_PLL4_1L al posto di quella prevista didefault e ricompiliamo il nostro firmware. A que-sto punto non ci resta che sostituire il quarzo a 6MHz della demoboard con uno a 20 MHz varian-do anche la coppia di condensatori C4 e C5 da 33pF con altri due da 15 pF. Programmiamo il PIC

Tabella 2

e inseriamolo sulla demoboard sostituendo laprecedente versione finestrata del micro.Possiamo tranquillamente utilizzare i programmipresentati durante il Corso per collegarci alnostro dispositivo e verificare che il suo funzio-namento sia corretto. Bene, siamo arrivati ariscrivere i nostri vecchi progetti per adeguarlialle caratteristiche del nuovo firmwareMicrochip. I nostri sforzi però non finiscono qua.Sarebbe poco "furbo" non sfruttare tutte le fun-zionalità e le prestazioni di questi nuovi chip.

tore. Per impostazione predefinita il firmwareusa l’HSPLL (FOSC0-3=111xb) quindi un oscil-latore ad alta velocità con il PLL attivato.(HSPLL High Speed Crystal/Resonator withPLL). Riassumiamo (nella Tabella 2) quali sono

Pertanto, nel prossimo numero inizieremo par-lando di modalità full-speed e di trasferimentiBulk e Isocroni. Capiremo che cosa sono i di-spositivi CDC e vedremo uno sviluppo firmwareche li coinvolge. Dunque: alla prossima!

Page 96: Corso PIC-USB

ontinuiamo il discorso anticipato al termi-ne della precedente puntata con una breve

digressione sulla modalità full-speed, grazie allaquale vi chiarirete le idee prima di affrontare ilnuovo esempio di sviluppo firmware.

Modalità Full-Speed

I nuovi chip PIC18F2455/2550 sono compatibilicon le specifiche USB2.0 e vengono utilizzatisecondo due possibili modalità:Low-Speed: permette i trasferimenti Interrupt eControl con un transfer rate massimo da 1,5Mb/s, trasferimenti largamente utilizzati negliesempi del corso. Full-Speed: permette due ulteriori tipi di trasfe-rimento per notevoli quantità di dati, denominati"Bulk" e Isocroni, caratterizzati da un transferrate massimo di 12 Mb/s.

Questa seconda modalità non è utilizzabile nellaprecedente famiglia di microprocessori, dellaquale rappresenta un’interessante evoluzione.

Siccome è importante capire bene la differenzatra questi due tipi di trasferimento dati, di segui-to esponiamo uno per uno i dettagli caratteristici.Bulk: sono usati per elevate quantità di datisequenziali, per le quali deve essere garantital’integrità, come nel caso di sequenze inviateverso una stampante o da uno scanner; il rappor-to tra il numero di byte inviati e il tempo non ècostante, pertanto l’utilizzo di banda sul busUSB può variare a seconda delle necessità.Sicccome una Pipe bulk può trasferire dati inun’unica direzione, se si desidera una comunica-zione bidirezionale bisogna predisporre duePipe, una per ciascun verso. Ogni Endpoint iso-crono può veicolare pacchetti con una lunghezzadi 8, 16, 32 e 64 byte. Tale lunghezza è stabilitanel campo wMaxPacketSize del descrittore ed èpresa in considerazione anche dal lato host perverificare che i dati inviati verso il dispositivoclient non la superino mai.Isocroni: servono per lunghe sequenze di datiquando il tempo di trasferimento è un parametrodeterminante, mentre non è necessaria la garan-

Elettronica In - luglio / agosto 2005 83

>

CCoorrssoo PPIICC--UUSSBB Corso ddi

programmazione pper PPIC:l’interfaccia UUSBB

9AAllllaa ssccooppeerrttaa ddeellllaa ffuunnzziioonnaalliittàà UUSSBBiimmpplleemmeennttaattaa nneeii mmiiccrrooccoonnttrroolllloorriiMMiiccrroocchhiipp PPIICC1188FF22445555 ee 1188FF22555500..IInn qquueessttaa ppuunnttaattaa aaffffrroonnttiiaammoo llee mmooddaalliittàà ddii ttrraassffeerriimmeennttoo LLooww ee FFuullllSSppeeeedd eedd ii ttrraassffeerriimmeennttii BBuullkk ee iissooccrroonnii,,pprreesseennttaannddoo uunn’’aapppplliiccaazziioonnee ddii ssiiccuurrooiinntteerreessssee:: uunn ccoonnvveerrttiittoorree ddaa UUSSBB aasseerriiaallee RRSS223322-CC.. AApppprrooffoonnddiirreemmoo iinnoollttrree aallllaa ccoonnoosscceennzzaaddeellllaa ccllaassssee ddeeii CCoommuunniiccaattiioonn DDeevviicceeUUSSBB..

a cura di Carlo Tauraso

Page 97: Corso PIC-USB

84 luglio / agosto 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

zia dell’integrità delle informazioni; il data/rate ècostante. In questa categoria si contemplano leapplicazioni di "data streaming", per le quali laperdita di qualche byte non influenza il risultatofinale: ad esempio la trasmissione di segnaleaudio digitale. L’integrità dei dati inviati nonviene controllata (come avviene, invece, nellesequenze Bulk) perché non c’é tempo di ritra-smettere i dati stessi senza degradare il servizio.L’utilizzo di banda del bus è fisso, per garantireun flusso ininterrotto di dati che devono essereinviati in modo da non perderne la temporizza-zione. Una Pipe isocrona può trasferire dati inun’unica direzione, quindi se occorre una comu-nicazione bidirezionale si devono predisporredue Pipe, una per ciascun verso. Ogni Endpointisocrono può veicolare pacchetti con una lun-ghezza fino a 1023 byte.Queste tipologie di trasferimento possono esseremolto utili per espandere i campi di utilizzo dellecircuiterie equipaggiate con la nuova famiglia diPIC. Quando si vuole realizzare un progetto, sitenga ben presente la differenza tra le diversemodalità di trasferimento: ciò perché ciascuna diesse ha dei precisi limiti e potenzialità.

CDC Communication Device Class

Grazie alla piena compatibilità della nuova fami-glia di chip con la modalità Full-Speed, i micropossono emulare una nuova tipologia di disposi-tivi che va ad aggiungersi a quella HID già suffi-cientemente analizzata durante il corso, una clas-se che definisce una serie di specifiche chedescrivono dei modelli di comunicazione per di-spositivi come telefoni, modem, interfacceEthernet ecc. In realtà vengono definite tre diver-se classi che formano un’architettura in grado disupportare qualunque tipo di dispositivo dicomunicazione; esse sono:Communication Device Class: contiene unaserie di definizioni utilizzate dall’host per identi-ficare un dispositivo che può contenere diversitipi di interfacce. Permette, quindi all’host dicapire, ad esempio, quali protocolli di comunica-zione sono gestibili dal dispositivo.Si faccia attenzione che già tale fatto differenzianotevolmente la classe CDC da quella HID pre-sentata nelle precedenti puntate del corso, cheutilizzava un’unica interfaccia.Communication Interface Class: descrive unmeccanismo generale per realizzare qualunqueservizio di comunicazione sul bus USB.

Data Interface Class: descrive un meccanismogenerale per realizzare delle transazioni bulk oisocrone tramite il bus USB; in particolare essaviene utilizzata quando il formato di trasmissio-ne non è assimilabile ad una classe già definitanelle specifiche: ad esempio l’audio.

Un dispositivo di comunicazione può quindi pre-sentare più interfacce; per comprendere benequesta affermazione si prenda ad esempio unnormale telefono: secondo un modello presenta-to nelle specifiche CDC esso deve essere compo-sto da almeno una Communication InterfaceClass, ma per essere funzionale allo scopo biso-gna aggiungergli una tastiera numerica, che sipuò descrivere solo attraverso una HID class. Sicomprende quindi come tali oggetti possano,aggiungendo via-via delle interfacce, diventarepiuttosto complessi. Dunque, i nostri HID diven-gono dei dispositivi facenti parte di un sistemacooperativo ben più vasto.Si potrebbe pensare di aggiungere al telefonoun’ulteriore interfaccia dati in grado di operarecome un modem, al fine di inviare e riceverestream sulla linea stessa: modelli di questo gene-re sono stati utilizzati, ad esempio, in alcuni tipidi telefono (di un noto marchio tedesco) che per-mettevano di gestire le chiamate sia voce che datidirettamente dal proprio PC, sfruttando un colle-gamento ISDN. Naturalmente in questa sede nonabbiamo lo spazio necessario a descrivere tutti imodelli presenti nelle specifiche CDC, per que-sto rimandiamo al sito www.usb.org chi fosseinteressato ad approfondire l’argomento: vi tro-verà tutti i dettagli nei documenti ufficiali che daesso si possono scaricare. Per la nostra trattazio-ne abbiamo scelto un modello che, oltre ad esse-re particolarmente versatile, è anche decisamen-te utile, visto che permette la costruzione deicosiddetti emulatori seriali su bus USB: si trattadi un esempio che inizialmente è stato descrittodalla Microchip come applicativo, ma che poi èstato ripreso anche dall’azienda produttrice delcompilatore PICBasic che sicuramente molti divoi avranno utilizzato nei propri progetti.La possibilità di sviluppare codice direttamentein un linguaggio semplice e diffuso, nonchè lagrande utilità del progetto, ci ha spinto ad analiz-zarlo in dettaglio, dando a tutti la possibilità diimplementarlo. Inoltre la presenza di diverse fun-zionalità Microchip (scritte in C18) per la gestio-ne della conversione RS232-USB, ci permetteràdi terminare il nostro percorso nel vasto mondo

Page 98: Corso PIC-USB

Elettronica In - luglio / agosto 2005 85

>

CCoorrssoo PPIICC--UUSSBB delle applicazioni USB PIC presentando un

ambiente di sviluppo per certi versi più profes-sionale, sebbene un po’ più complesso. Non ci resta che iniziare presentando un’altraapplicazione pratica a corollario del corso: lacostruzione di un’interfaccia USB-RS232. Sinoti che le informazioni relative a questo proget-to sono facilmente utilizzabili per dotare diun’interfaccia USB il proprio modem analogico,il cavo data-link del cellulare e, in generale, qual-siasi dispositivo funzionante in RS-232.È doveroso dire che questo esempio è stato giàpresentato sia dalla Microchip che dallaMicroengineering Lab, tant’è che nella versione

molti è sorto il problema di adattare i propri pro-dotti per renderli compatibili al nuovo sistema dicomunicazione; i primi sono stati senz’altro iproduttori di modem, apparecchi che fino al2000 erano prevalentemente seriali: la migrazio-ne verso il nuovo sistema avrebbe certamentecomportato dei grossi problemi, visto che sisarebbe dovuto riscrivere buona parte delle appli-cazioni host e che sarebbe occorso operare unradicale re-engineering delle circuiterie. Il pro-blema è stato risolto realizzando un modello didispositivo USB in grado di emulare pienamenteil comportamento della canonica seriale. Cosìfacendo, dal lato host non si è obbligati ad effet-

Tabella 1

2.46 del PicBASIC Pro troviamo il necessariofirmware. Noi ne diamo una descrizione un po’più dettagliata, approfondendo gli argomentirelativi alla costruzione dei descrittori e all’im-plementazione, consegnando a tutti voi gli stru-menti e le informazioni necessarie a compren-derne tutti gli aspetti. In particolare, tutto il firm-ware è stato riordinato evidenziando in strutturetabellari le varie parti che lo compongono: perogni tabella, inoltre, affianchiamo la descrizioneteorica di ciascun campo riferendoci alle specifi-che ufficiali CDC. Tutto ciò ha un intento didat-tico, ma nello stesso tempo vuole sposare la filo-sofia secondo la quale osservare il funzionamen-to di un dispositivo non ha valore senza avercapito il perché del suo funzionamento.

La sezione 3.6.2.1delle specifiche CDC

Questa sezione presenta un modello di controlloastratto per l’emulazione seriale, che nasce prin-cipalmente per fornire ai produttori di modemanalogici la documentazione necessaria al fine dimigrare dall’interfaccia RS-232 verso l’USB.Negli ultimi anni si è palesata sempre più la ten-denza da parte dei maggiori produttori di compu-ter ad eliminare le porte COM, a pieno favoredello standard USB. È quindi chiaro che per

tuare alcun cambiamento, visto che il sistemaoperativo vede il dispositivo stesso come unaporta seriale virtuale che può essere gestita conle funzioni degli stessi applicativi previsti per ilcontrollo di un modem seriale. Invece, sulla partedevice, lo schema circuitale precedente rimaneinvariato: si aggiunge soltanto, a monte dellelinee di comunicazione seriale, un apposito chipin grado di gestire il bus USB (un PIC18F2550va benissimo). Per il corretto funzionamento delmodello sono necessarie due interfacce: unaCommunication Class Interface ed una DataClass Interface. La prima utilizza un endpoint INcon trasferimenti di tipo interrupt e serve a noti-ficare all’host lo stato della connessione. Laseconda, invece, impiega due endpoint, uno INed uno OUT, con trasferimenti di tipo bulk pergestire il trasferimento delle sequenze di byteattraverso l’interfaccia USB-RS232. Nella docu-mentazione viene descritta una serie di richiestespecifiche che devono essere opportunamentegestite dalla classe. L’insieme necessario e suffi-ciente al corretto funzionamento di un dispositi-vo di comunicazione seriale è riassunto nellaTabella 1. Volendo farsi un’idea della funzione ditali richieste, si consideri che per inviare al di-spositivo un comando del tipo ATDT (chiamata atoni) verrà utilizzata la richiesta SEND_ENCAP-SULATED_COMMAND. Analogamente, se

Page 99: Corso PIC-USB

86 luglio / agosto 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

l’host vorrà settare la velocità di comunicazione(ad esempio 9600 bps) utilizzerà il comandoSET_LINE_CODING. Tali richieste sono previ-ste dal firmware incluso nel PICBasic: in parti-colare, ne troviamo un gestore direttamente nelfile USB18.asm inserito nel percorso\pbp\USB18. I più curiosi possono verificarloricercando all’interno dello stesso file le stringherelative alle richieste in questione.

Esperimento n. 4 - Un’interfaccia USB-RS232Il circuito

Lo schema circuitale è piuttosto semplice, vistoche buona parte delle funzioni è gestita diretta-mente dal firmware caricato nel PIC; esterna-mente è stato necessario aggiungere solamenteun convertitore per i segnali da TTL a RS-232costituito dal diffusissimo MAX232.

I L C O N V E R T I T O R E U S B - R S 2 3 2

R1: 10 kohmR2: 470 ohmR3: 470 ohmR4: 18 kohmC1, C2: 15 pF ceramicoC3: 1 µF 100 VL elettroliticoC4: 1 µF 100 VL elettrolitico

C5: 1 µF 63 VL elettroliticoC6: 1 µF 63 VL elettroliticoC7: 220 nF multistratoU1: PIC18F2550 (MF593)U2: MAX232LD1: led 3 mm verdeLD2: led 3 mm rosso

Varie:- Connettore USB-A- Connettore DB9 maschio- Zoccolo 14+14- Zoccolo 8+8- Circuito stampato codice

S0593

ELENCO COMPONENTI:

Schema elettrico e piano di cablaggio del convertitore USB-RS232 realizzato col nuovo microPIC18F2550. Il firmware può essere scaricato gratuitamente dal sito www.elettronicain.it

Page 100: Corso PIC-USB

Elettronica In - luglio / agosto 2005 87

>

CCoorrssoo PPIICC--UUSSBB Con pochi componenti di contorno, grazie ad una

pompa di tensione interna, questo integrato è ingrado di convertire i livelli logici TTL (0/5 V) nei±10 V utilizzati nella porta seriale del PC.Un’altra cosa che probabilmente avrete notato èche sulle linee dati dell’USB non abbiamo inse-rito alcuna resistenza di pull-up: anzi, lo stessopin Vusb che, nei precedenti progetti forniva lanecessaria tensione, è ora collegato al GND tra-mite C7. Tutto ciò è possibile perché su questotipo di chip le resistenze di pull-up sono integra-te ed è possibile controllarne il collegamentoattraverso due bit del registro UCFG: in pratica ilbit UPUEN (bit 4) stabilisce se esse sono abilita-

Come vedremo nei prossimi paragrafi, il valoredel registro UCFG viene stabilito all’inizio delfile dei descrittori. In Fig. 1 trovate una tipicaconfigurazione full-speed con un pull-up esterno.

Il file dei descrittori

Spieghiamo le differenze fondamentali tra idescrittori per dispositivi HID e quelli per dispo-

sitivi CDC, scrivendo direttamente la strutturanecessaria al nostro esperimento. Innanzituttovediamo il descrittore di dispositivo nel Listato1: se lo mettiamo a confronto con il descrittore

Config1retlw 9 ; bLengthretlw DSC_CFG ; bDescType

Config1Lenretlw low ((EndConfig1 - Config1)/2) ; wTotalLength (low-byte)retlw high ((EndConfig1 - Config1)/2) ; wTotalLength (high-byte)retlw NUM_INTERFACES ; bNumInterfacesretlw 0x01 ; bConfigurationValueretlw 0x02 ; iConfigurationretlw 0x80 ; bmAttributesretlw 0x50 ; Maxpower

L I S T A T O 2

Fig. 1

specifiche CDC. Passiamo quindi al descrittoreConfiguration (Listato 2); continuiamo il con-fronto e focalizziamo la nostra attenzione sulcampo bNumInterfaces. Nel caso del HID,TermoUSB avevamo messo il valore 1, mentreora si inserisce una costante (NUM_INTERFA-CES) pari a 2. Ricordiamo, infatti, che stiamorealizzando un dispositivo con una doppia inter-faccia costituita da una Communication Interface

DeviceDescriptorretlw (EndDeviceDescriptor-DeviceDescriptor)/2 ; bLengthretlw DSC_DEV ; bDescTyperetlw 0x10 ; bcdUSB (low-b)retlw 0x01 ; bcdUSB (high-b)retlw CDC_DEVICE ; bDeviceClassretlw 0x00 ; bDeviceSubClassretlw 0x00 ; bDeviceProtocolretlw EP0_BUFF_SIZE ; bMaxPacketSizeretlw 0xD8 ; idVendor (low-b)retlw 0x04 ; idVendor (high-b)retlw 0x00 ; idProduct (low-b)retlw 0x00 ; idProduct (high-b)retlw 0x00 ; bcdDevice (low-b)retlw 0x01 ; bcdDevice (high-b)retlw 0x01 ; iManufacturerretlw 0x02 ; iProductretlw 0x03 ; iSerialNumberretlw NUM_CONFIGURATIONS ; bNumConfigurations

EndDeviceDescriptor

L I S T A T O 1

te, mentre il bit FSEN (bit 2) precisa la linea sullaquale una di esse lavora. Se FSEN = 0 il PIC è undispositivo Low-Speed e il pull-up è sulla lineaD-, mentre se FSEN = 1 il micro lavora come unFull-Speed e il pull-up insiste sulla linea D+.

del nostro TermoUSB ci accorgiamo che l’unicadifferenza è quella relativa al campobDeviceClass, che precisa la classe cui appartie-ne il dispositivo. In questo caso viene utilizzatauna costante pari a 2, così come stabilito nelle

Page 101: Corso PIC-USB

88 luglio / agosto 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

ed una Data Interface. Il resto dei campi è prati-camente identico, tranne per quanto riguardal’indice puntatore alla stringa descrittiva dellaconfigurazione: si tratta soltanto di una modificaformale che non comporta alcun cambiamentofunzionale; la stessa cosa vale per MaxPower.

la gestione dei comandi AT ed è descritto com-pletamente in uno standard internazionale la cuidocumentazione di riferimento è identificata conla sigla V25-ter.Mentre nel descrittore del TermoUSB si passa aldescrittore HID, qui ne viene inserito uno speci-fico della classe CDC; anche in questo caso lastruttura è relativa esclusivamente allaCommunication Interface. Ogni descrittore spe-cifico della classe è costituito da uno o piùdescrittori funzionali preceduti da un Header ini-ziale. La struttura è formata dalle sezioni:

1) HEADER FUNCTIONAL DESCRIPTOR;2) ABSTRACT CONTROL MANAGEMENT

FUNCTIONAL DESCRIPTOR;3) UNION FUNCTIONAL DESCRIPTOR;4) CALL MANAGEMENT FUNCTIONAL

DESCRIPTOR.

retlw 9 ; bLengthretlw DSC_INTF ; bDescriptorType INTERFACEretlw 0x00 ; bInterfaceNumberretlw 0x00 ; bAlternateSettingretlw 0x01 ; bNumEndpointsretlw COMM_INTF ; bInterfaceClassretlw ABSTRACT_CONTROL_MODEL ; bInterfaceSubClassretlw V25TER ; bInterfaceProtocolretlw 0x00 ; iInterface

L I S T A T O 3

Tabella 2

Con il descrittore Interface le cose cambiano acausa della presenza di più interfacce; lo capia-mo esaminando il caso della CommunicationInterface (Listato 3). In esso si faccia attenzioneche i campi del descrittore sono da riferirsi allasingola interfaccia, pertanto il numero di end-point è da intendersi per la CommunicationInterface e non per l’intero insieme di interfacce.Il byte identificativo della classe di interfaccia èpari a 2 (COMM_INTF) come stabilito nelle spe-cifiche CDC; la sottoclasse si ricava dalla Tabella2. Infine viene definito il protocollo specifico uti-lizzato dalla classe, il cui codice descrittivo è sta-bilito sulla base della Tabella 3.

Tabella 3

Vediamole nel concreto con la solita rappresenta-zione tabellare (riferirsi alla Tabella 4); la relati-va sequenza di istruzioni è visibile nel Listato 4.L’Abstract Control Management FunctionalDescriptor stabilisce i comandi supportati dallaCommunication Class Interface. La sua strutturaè rappresentata in Tabella 5, mentre la relativasequenza di istruzioni è descritta nel Listato 5.Si faccia attenzione che nel campobmCapabilities viene valorizzato solo il bit 1,che comprende l’insieme di richieste specifichenecessarie al corretto funzionamento del disposi-

Tabella 4

Il codice di cui parliamo è 1 ed è comunque defi-nito come una costante chiamata V25TER. Ineffetti il protocollo Hayes Compatibile prevede

tivo. A proposito: se il bit viene valorizzato a 1significa che la relativa funzionalità risulta abili-tata, mentre se è a 0 la stessa viene disabilitata.

Page 102: Corso PIC-USB

Elettronica In - luglio / agosto 2005 89

CCoorrssoo PPIICC--UUSSBB

delle interfacce viene definita come master delgruppo: lo scopo di ciò è fare in modo che alcu-ne tipologie di messaggi inviati ad essa si possa-

ramente, il gruppo in questione consta di duesole interfacce: la prima, ossia laCommunication Class Interface, viene definitacome master perché è in grado di gestire almeglio i messaggi di controllo sullo stato dellacomunicazione. L’altra è uno slave, in quantofondamentalmente funge da strato di trasporto.L’ultimo descrittore definisce le capacità digestione del processo di chiamata da parte dellaCommunication Class Interface. Detta così la

Tabella 6

retlw 5 ; bFunctionLength (HEADER_FN_DSC)retlw CS_INTERFACE ; bDescriptorTyperetlw DSC_FN_HEADER ; bDescriptorSubTyperetlw 0x10 ; bcdCDC (low byte)retlw 0x01 ; bcdCDC (high byte)

L I S T A T O 4

Il terzo descrittore definisce le relazioni intercor-renti in un gruppo di interfacce che possono con-siderarsi un’unità funzionale autonoma; una

Tabella 5

retlw 4 ; bFunctionLength (ACM_FN_DSC)retlw CS_INTERFACE ; bDescriptorTyperetlw DSC_FN_ACM ; bDescriptorSubTyperetlw 0x02 ; bmCapabilities

L I S T A T O 5

>

no intendere come inviate al gruppo nel suo com-plesso. In Tabella 6 riepiloghiamo i campi chefanno parte di questa struttura, ciascuno con larelativa istruzione (Listato 6). Come si vede chia-

cosa sembra piuttosto complessa; in realtà si sta-bilisce se le interfacce possono gestire il control-lo delle chiamate e se tale controllo è condivisoo esclusivo della Communication ClassInterface.Nel nostro caso dovremo disabilitare la possibili-tà da parte del dispositivo di operare un effettivocontrollo delle chiamate (vedi Tabella 7). Lerelative istruzioni sono descritte nel Listato 7;come si vede, in esso il campo bmCapabilities èazzerato, quindi il dispositivo controlla le chia-mate, ma non autonomamente. Per la DataInterface opzionale si usa il relativo indice, che èstato prefissato attraverso una costante chiamata,

Page 103: Corso PIC-USB

90 luglio / agosto 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

che in questo caso in alcuni campi vengono uti-lizzate delle costanti al posto dei valori discreti.Si noti che il bmAttributes è sempre pari a 3,

appunto, CDC_DATA_INTF_ID e posta all’ini-zio del file, come vedremo al termine del para-grafo. A questo punto, così come avveniva per i

dispositivi HID, precisiamo il descrittoreEndpoint, ricordando che stiamo definendo l’in-terfaccia Communication che utilizzerà soltantoun endpoint IN con trasferimenti di tipo Interrupt(Listato 8). La struttura è praticamente identica aquella vista nel TermoUSB, tranne per il fatto

retlw 5 ; bFunctionLength (UNION_FN_DSC)retlw CS_INTERFACE ; bDescriptorTyperetlw DSC_FN_UNION ; bDescriptorSubTyperetlw CDC_COMM_INTF_ID ; bMasterInterfaceretlw CDC_DATA_INTF_ID ; bSlaveInterface0

L I S T A T O 6

Tabella 7

retlw 5 ; bFunctionLength (CALL_MGT_FN_DSC)retlw CS_INTERFACE ; bDescriptionTyperetlw DSC_FN_CALL_MGT ; bDescriptionSubTyperetlw 0x00 ; bmCapabilitiesretlw CDC_DATA_INTF_ID ; bDataInterface

L I S T A T O 7

visto che per entrambe i dispositivi utilizziamodei trasferimenti di tipo Interrupt.A questo punto l’interfaccia Communication èterminata. Dobbiamo ancora specificare la strut-tura che descrive l’interfaccia Data e, allo scopo,partiamo, come per la precedente, dal descrittored’interfaccia (vedi Listato 9) nel quale il numerodi endpoint usati è pari a 2 e la classe d’interfac-cia è cambiata per la Data Class Interface; larelativa sottoclasse non viene specificata e non è

neppure necessario precisare alcun tipo di proto-collo, visto che il livello in questione non avràalcuna funzione di controllo della comunicazio-ne, ma servirà esclusivamente per trasferiresequenze di dati in ingresso e in uscita. Anche ildescrittore Endpoint è piuttosto semplice e, lo

vediamo, ricalca la medesima struttura vista perla precedente interfaccia: l’unica differenza èdovuta al fatto che in questo caso gli endpoint

retlw 7 ; bLength (USB_EP_DSC)retlw DSC_EP ; bDescriptorTyperetlw _EP02_IN ; bEndpointAddressretlw 3 ; bmAttributes retlw low (CDC_INT_EP_SIZE) ; wMaxPacketSize (low-byte)retlw high (CDC_INT_EP_SIZE) ; wMaxPacketSize (high-byte)retlw 0x02 ; bInterval

L I S T A T O 8

Page 104: Corso PIC-USB

Elettronica In - luglio / agosto 2005 91

>

CCoorrssoo PPIICC--UUSSBB

sono due, pertanto le definizioni raddoppiano.Ricordiamo che gli endpoint dell’interfacciaData useranno dei trasferimenti di tipo Bulk,quindi sarà sicuramente necessario variare ilcampo bmAttributes (vedi Listato 10). La descri-

zione dei due endpoint differisce esclusivamenteper la direzione di utilizzo.In entrambi i casi si utilizzano delle costanti perstabilire la massima grandezza del pacchetto el’indirizzo dell’endpoint. Facciamo anche notareche il campo bInterval ha senso nei trasferimen-

le medesime strutture di quelli usati per i dispo-sitivi già analizzati nelle precedenti puntate delcorso PicUSB, spiegarli in questa sede non costi-tuirebbe nulla di nuovo, ma, piuttosto, una ripeti-zione di concetti che, giunti a questo punto,dovreste già aver compreso a dovere. Dunque,per non sprecare spazio dedicandolo a un banaleelenco di caratteri, non ne parliamo. Andiamo,invece, a vedere l’header del file RSUSBdsc.asm,dove troviamo finalmente la definizione di alcu-ne delle costanti utilizzate nei descrittori.Come abbiamo già fatto in altre occasioni, il fileè stato riscritto in maniera da riordinarne la strut-tura evidenziando le varie parti che lo compon-gono. Il descrittore specifico della classe CDC èstato diviso nelle quattro sezioni, spiegate affin-

retlw 9 ; bLength retlw DSC_INTF ; bDescriptorTyperetlw 0x01 ; bInterfaceNumberretlw 0x00 ; bAlternateSettingretlw 0x02 ; bNumEndpointsretlw DATA_INTF ; bInterfaceClassretlw 0 ; bInterfaceSubclassretlw NO_PROTOCOL ; bInterfaceProtocolretlw 0x00 ; iInterface

L I S T A T O 9

retlw 7 ; bLength (USB_EP_DSC)retlw DSC_EP ; bDescriptorTyperetlw _EP03_OUT ; bEndpointAddressretlw 2 ; bmAttributes retlw low (CDC_BULK_OUT_EP_SIZE) ; wMaxPacketSize (low-byte)retlw high (CDC_BULK_OUT_EP_SIZE) ; wMaxPacketSize (high-byte)retlw 0x00 ; bIntervalretlw 7 ; bLength (USB_EP_DSC)retlw DSC_EP ; bDescriptorTyperetlw _EP03_IN ; bEndpointAddressretlw 2 ; bmAttributes retlw low (CDC_BULK_IN_EP_SIZE) ; wMaxPacketSize (low-byte)retlw high (CDC_BULK_IN_EP_SIZE) ; wMaxPacketSize (high-byte)retlw 0x00 ; bInterval

L I S T A T O 1 0

ché sia possibile verificare "sul campo" quantodetto. L’header, così come per il file dei descrit-tori del TermoUSB, è diviso in due tabelle: unaper i parametri generali ed un’altra per quellispecifici della classe CDC (vedi Listato 11).Nella prima tabella è facilmente riconoscibile la

; **********************************************************************; TABELLA PARAMETRI GENERALI; **********************************************************************#defineEP0_BUFF_SIZE 8#defineMAX_NUM_INT 1#defineMAX_EP_NUMBER 3#defineNUM_CONFIGURATIONS 1#defineNUM_INTERFACES 2#defineMODE_PP _PPBM0#defineUCFG_VAL _PUEN|_TRINT|_FS|MODE_PP ; Full-speed#define USB_USE_CDC

L I S T A T O 1 1

ti Interrupt, ma nel caso qui analizzato perde lasua utilità e viene pertanto azzerato.Con questo siamo arrivati al termine del file deidescrittori; riteniamo, infatti, che non sia neces-sario stabilire il descrittore Report, il quale è unastruttura tipica degli HID e si può finire inclu-dendo i descrittori stringa. Avendo questi ultimi

stessa sequenza presente nel file dei descrittoridel TermoUSB; varia solo il massimo numero diendpoint utilizzati, che passa da 1 a 3: questi ulti-mi sono infatti destinati uno alla CommunicationInterface e due alla Data Interface.Infine, si osservi una definizione fondamentaleche abbiamo evidenziato in rosso: si tratta di

Page 105: Corso PIC-USB

92 luglio / agosto 2005 - Elettronica In

CCoorrssoo PPIICC--UUSSBB

#define USB_USE_CDC, che stabilisce la classedi dispositivo utilizzata nel firmware e quindiinforma il compilatore delle istruzioni che devenecessariamente includere.Per esempio, se analizzate il contenuto del fileUSB18.asm localizzato nella directory\pbp\USB18 vedrete che esistono delle direttivedi compilazione (#ifdef) le quali includono omeno delle routine, a seconda che nel sorgente siinseriscano la define USB_USE_CDC (utilizzodi Communication Device Class) o laUSB_USE_HID (impiego di dispositivi di classeHID). Un tipico caso è quello della routineUSBCheckCDCRequest, che verifica le richiesteinviate e le passa al relativo gestore.Si noti che esiste un’altra routine, chiamataUSBCheckHIDRequest, che viene inclusa soltan-to con la define USB_USE_HID. Per ulteriori

controllo (UEP2, UEP3) associati agli endpoint,nonché grandezza e direzione dei buffer utilizza-ti dagli endpoint stessi per i trasferimenti di cuiessi devono occuparsi. L’indice identificativo perle due interfacce (COMM_INTF_ID eDATA_INTF_ID) è chiaramente differente: vale0 per la Communication e 1 per la Data Interface.Bene, detto ciò siamo quindi arrivati al terminedel file dei descrittori RSUSBDSC.asm. Come alsolito, dobbiamo aggiornare il link nel file USB-DESC.asm, affinché il compilatore includa cor-rettamente i descrittori appena sviluppati.L’istruzione con cui provvediamo a fare ciò èvisibile nel Listato 13, nel quale vi invitiamo aprestare eventualmente attenzione a commentarele righe relative ai descrittori utilizzati in altriprogetti anteponendo un simbolo ; (punto e vir-gola) alla rispettiva include.

chiarimenti sulle altre voci della tabella si veda laprecedente puntata del corso pubblicata nelfascicolo n° 99 della rivista.La tabella che raggruppa i parametri specificidella classe CDC è, invece, di facile comprensio-ne, tanto più se la si mette a confronto con quel-la utilizzata per il TermoUSB avendo bene amente la configurazione degli endpoint appenaesposta e visibile nel Listato 12.Nella sequenza in oggetto vengono definiti gli

Bene, con ciò anche questo mese lo spazio anostra disposizione si è esaurito.Sperando che abbiate appreso le nozioni fonda-mentali sui trasferimenti bulk e isocroni, e sulleCommunication Device Class dei dispositiviUSB (chi volesse approfondire l’argomento tro-verà interessante la pagina Webhttp://www.usb.org/developers/devclass_docs) viaccenniamo che nella prossima puntata vedremoi dettagli dello sviluppo PICBasic necessario a

; **********************************************************************; TABELLA PARAMETRI CLASSE CDC; **********************************************************************#define CDC_COMM_INTF_ID 0x00#define CDC_COMM_UEP UEP2#define CDC_INT_BD_IN ep2Bi#define CDC_INT_EP_SIZE 8#define CDC_DATA_INTF_ID 0x01#define CDC_DATA_UEP UEP3#define CDC_BULK_BD_OUT ep3Bo#define CDC_BULK_OUT_EP_SIZE 64#define CDC_BULK_BD_IN ep3Bi#define CDC_BULK_IN_EP_SIZE 64

L I S T A T O 1 2

include "RSUSBDSC.ASM" ; Descrittori Convertitore RS232-USB Esp.4 Corso PIC-USB

L I S T A T O 1 3

endpoint relativi alle due interfacce.Nel caso della Communication Class Interfaceviene precisato un endpoint con trasferimentiinterrupt a 8 byte, mentre per la seconda inter-faccia si definiscono due endpoint con trasferi-menti bulk a 64 byte.Per ogni interfaccia vengono definiti i registri di

far funzionare il nostro convertitore USB-RS232.Scopriremo altresì come creare il file .hexmediante la versione 2.46 del compilatore etesteremo "sul campo" il dispositivo con essocreato. Chiariremo, infine, un altro aspetto di svi-luppo dei dispositivi CDC, analizzando il nuovoframework Microchip. Alla prossima!

Page 106: Corso PIC-USB