USB Présentation du protocole Exemple de réalisation hardware Choix d'un composant USB rapide Description du composant Description d'une carte Exemple de réalisation software Logiciel côté périphérique Logiciel côté serveur
Vue générale de l'architecture (1) Le bus USB est un bus point à point : le point de départ étant le host (PC ou hub), il va vers un périphérique ou un autre hub. Il n'y a qu'un seul host dans une architecture USB. Certains périphériques ont un hub intégré. Les périphériques partagent la bande passante de l'USB. Le protocole est basé sur des jetons (token). L'ordinateur fournit un jeton au périphérique sélectionné, lequel lui renvoie le jeton par sa réponse. Ce bus permet une connexion déconnexion à chaud.
Vue générale de l'architecture (2) La topologie du bus peut être considérée comme un arbre dont le PC serait la racine et les périphériques les feuilles. Les périphériques ne communiquent jamais entre eux directement. PC Hub
Interface physique Au niveau électrique, le câble USB transfère le signal et l'alimentation sur 4 fils. Il s'agit d'une paire torsadée d'impédance caractéristique 90 . Le débit peut être soit 1.5 Mbits/s ou 12 Mbits/s (480 Mbits/s pour l'USB 2.0). Suivant le délai de propagation du câble sa longueur peut atteindre 4.5 m. Au niveau de la connectique il existe 2 types de connecteur (A plat rectangulaire côté PC ou hub et B carré côté périphérique). Vcc Gnd D- D+
Alimentation Au niveau de l'alimentation, le câble (par l'intermédiaire du PC ou du hub) fournit la tension nominale de 5V. Comme chacun des périphériques peuvent s'auto-alimenter, ils indiquent au host la consommation souhaitée. Le système tient à jour la consommation totale demandée et regarde s'il peut effectivement fournir l'énergie souhaitée. Dans le cas contraire il peut demander aux périphériques de se mettre en veille. Néanmoins la partie USB est toujours active.
Protocole du bus USB Une transaction sur le bus nécessite au moins trois paquets. Chaque transmission commence par : L'envoi par le host d'un paquet indiquant le type, la direction de transaction, l'adresse de l'USB et son point terminal (End Point). Ce paquet porte le nom de "token packet" (jeton). Puis le transmetteur envoie son paquet de données, ou indique qu'il n'a pas de paquet à transmettre Enfin le destinataire envoie un paquet d'accusé de réception On donne le nom de Pipe au lien virtuel entre le host et l'un des End Point du périphérique USB. Chaque lien est caractérisé par sa bande passante, son type de service et la taille des paquets. Chaque paquet est cadencé à la milliseconde.
Type de transfert Il existe 4 types de transfert pour un lien virtuel : Control : mode utilisé pour réaliser des configurations sur le périphérique. Ce lien est sans perte de données. Bulk : mode utilisé pour la transmission d' importantes quantités de données. Ce lien est sans perte de données et la bande passante octroyée à ce type de données dépend des autres périphériques. Elle est la moins prioritaire. Interrupt : assure le transfert de petites quantités de données, très rapidement. Le temps de réaction ne peut être plus lent que la valeur demandée par le périphérique. Isochronous : fonctionne en temps réel. La bande passante et le délai sont garantis. C'est le mode le plus prioritaire. Du côté applicatif des erreurs d'underruns peuvent être détectées.
Échange en mode Bulk Idle Jeton IN OUT DATA 0/1 NAK STALL DATA 0/1 Données ACK ACK NAK STALL Idle Acquittement
Exemple de mise en oeuvre Un rapide sondage à montré que de nombreux développeurs utilisent des composants du fabriquant Cypress (Intel, Motorola, Mitsubishi, Philips). Ce constructeur fournit toute une gamme de produit du plus lent 1.5 Mbits/s au plus plus rapide 480 Mbits/s. En fait le composant choisi est un dérivé de la famille 8051 avec des fonctions USB entièrement intégrés. Un kit de développement (CY3671) très performant est disponible, permettant ainsi d'appréhender les différentes possibilités de l'USB.
Caractéristiques des CYC646XX Transceiver USB et SIE intégré sur la puce Code 8051 dans la ram interne (8KB) ou externe, chargée à partir d'EEPROM ou via le bus USB. 14 Bulk/Interrupt endpoints avec une taille maximum de 64 bytes par paquet. 16 Isochrones endpoints avec un buffer total de 2KB. Intégré 8051amélioré: 4 clocks par cycle machine au lieu de 12, horloge de 48 MHz, 2 uarts, 3 compteurs / timers D+ D- Serial Interface Engine octets µP 8051
Schéma bloc du CYC64613
Exemple de carte (1)
Exemple de carte (2)
Outils logiciels Il va falloir utiliser 2 séries d'outils pour piloter la partie logicielle : Côté périphérique, on utilise un outil de développement pour écrire du code compatible 8051. Avec le kit de développement est livré une version limitée du compilateur Keil. Le code sera écrit dans une Eeprom compatible I2C est chargé lors de démarrage du µP. Côté host, on utilise un produit capable d'accéder à une DLL système.
Initialisation du protocole Void TDINIT (void) { IN07VAL = bmEP2; OUT07VAL = bmEP2; // Valide EndPoint 2. IN07VAL et OUT07VAL sont 2 registres qui indiquent les "Endpoint" valides en entrée et sortie EPIO[OUT2BUF_ID].bytes = 0; //Arm Endpoint2 out to recieve data // Activation de l'adressage en sbit PORTSETUP=1; // SFRPORT=1 // Activation des Ports D,E et B OED= 0xf0; OUTD=0; // bit 0-3 comme entrée, tout à 0 OEE=0x00; // bit 0-7 comme entrée OEB=0xC0; OUTB=00; // bit 6-7 comme sortie tout à 0 } void TD_Init(void) // Called once at startup { // Enable endpoint 2 in, and endpoint 2 out IN07VAL = bmEP2; // Validate all EP's OUT07VAL = bmEP2; // Enable double buffering on endpoint 2 in, and endpoint 2 out USBPAIR = 0x09; // Arm Endpoint 2 out to recieve data EPIO[OUT2BUF_ID].bytes = 0; // Setup breakpoint to trigger on TD_Poll() BPADDR = (WORD)TD_Poll; USBBAV |= bmBPEN; // Enable the breakpoint USBBAV &= ~bmBPPULSE; // Activation de l'adressage en sbit PORTSETUP=1; // SFRPORT=1 // Activation du Port D OED= 0xf0; // bit 0-3 comme entrée OUTD=0; // tout à 0 OEE=0x00; // bit 0-7 comme entrée OEB=0xC0; // bit 6-7 comme sortie OUTB=00; // tout à 0 //initio(); }
Réception des données On peut travailler en mode Polling ou par interruption. Le registre de contrôle et d'état permet de contrôler chaque "Bulk Endpoint" if((EPIO[OUT2BUF_ID].cntrl & bmEPBUSY)==0 )// Il y a quelques choses dans le buffer { count =EPIO[OUT2BUF_ID].bytes; //Nombre d'octets reçus dans le buffer for(i=0;i<count;++i) pMsg[i]= OUT2BUF[i]; // On récupère les données pMsg[i+1]= 0; EPIO[OUT2BUF_ID].bytes = 0; }
Emission des données On vérifie l'état du registre EPIO pour savoir si on peut émettre des données : read8Data(pMsg); // On lit 8 données d'un convertisseur while( (EPIO[IN2BUF_ID].cntrl & bmEPBUSY) ); // On attend que IN2BUF soit disponible ++j; // incrémente le No du message memcpy(&IN2BUF[0],&j,2); memcpy(&IN2BUF[2],&pMsg[0],16); // copie de 16 caractères d'un message EPIO[IN2BUF_ID].bytes = 18; // les données sont automatiquement émises.
Développement côté PC On travaille avec un fichier virtuel en utilisant les fonctions appropriées de la librairie Kernel 32. Au lancement de Windows un driver générique livré avec le kit de développement permet de reconnaître les circuits USB de la famille Cypress. Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Public Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, ByVal nOutBufferSize As Long, lpBytesReturned As Long, ByVal lpOverlapped As Long) As Long
Structures utilisées côté PC (1/2) Public Type USBDeviceDescriptorType ' USB device descriptor bDescriptorLength As Byte: bDescriptor As Byte iSpecRelease As Integer bDeviceClass As Byte: bDeviceSubClass As Byte bDeviceProtocol As Byte bMaxPacketSize As Byte iVendorID As Integer: iProductID As Integer iDeviceRelease As Integer : bManufacturer As Byte : bProduct As Byte : bSerialNumber As Byte bNumberConfigurations As Byte fill(128) As Byte End Type Public Type BulkTransferControlType lPipeNum As Long
Structures utilisées côté PC (2/2) Public Type USBDPipeInformationType ' OUTPUT, These fields are filled in by USBD iMaximumPacketSize As Integer 'Maximum packet size for this pipe bEndpointAddress As Byte ' 8 bit USB endpoint address (includes direction) bInterval As Byte ' Polling interval in ms if interrupt pipe PipeType As USBDPipeEnum ' PipeType identifies type of transfer valid for this pipe lPipeHandle As Long ' INPUT, These fields are filled in by the client driver lMaximumTransferSize As Long ' Maximum size for a single request in bytes. lPipeFlags As Long End Type Public Type USBDInterfaceInformationType iLength As Integer ' Length of this structure, including all pipe information structures ' INPUT, Interface number and Alternate setting this structure is associated with bInterfaceNumber As Byte : bAlternateSetting As Byte ' OUTPUT , These fields are filled in by USBD bClass As Byte : bSubClass As Byte : bProtocol As Byte : bReserved As Byte lInterfaceHandle As Long : lNumberOfPipes As Long Pipes(MAX_PIPES) As USBDPipeInformationType
Initialisation côté PC Dim usbDD As USBDeviceDescriptorType Dim pi As USBDInterfaceInformationType ' Global dans le projet driverName = "\\.\" & "Ezusb-0" hDriverHandle = CreateFile(driverName, (GENERIC_READ Or GENERIC_WRITE), (FILE_SHARE_READ Or FILE_SHARE_WRITE), ByVal 0, OPEN_EXISTING, 0&, 0) result = DeviceIoControl(hDriverhandle, IOCTL_Ezusb_GET_DEVICE_DESCRIPTOR, usbDD, Len(usbDD), usbDD, Len(usbDD), lBytesReturned, 0) If usbDD.iVendorID <> &H547 And usbDD.iProductID <> &H1002 Then CloseHandle hDriverhandle result = DeviceIoControl(hDriverhandle, IOCTL_Ezusb_GET_PIPE_INFO, pi, Len(pi), pi, Len(pi), lBytesReturned, 0) ' Information sur le type de lien If result = 0 Then CloseHandle hDriverhandle
Émission des données par le PC result = DoBulkXfer(usrUsbParametre.hDriverhandle, eWrite, buffer, lngDataLen) ' Emission d'un buffer …. Function DoBulkXfer(hDriverhandle As Long, pipe As Integer, ByRef buffer() As Byte, ByRef dataLen As Long) As Long If pi.lNumberOfPipes <= pipe Then ' Le lien est-il correct DoBulkXfer = eBadPipe : Exit Function Else ' met ce lien dans la structure BulkTransferControl btc.lPipeNum = pipe End If ' determine en fonction du No du EndPoint le sens du transfert If (pi.Pipes(pipe).bEndpointAddress <= 128) Then result = DeviceIoControl(hDriverhandle, IOCTL_EZUSB_BULK_WRITE, btc, Len(btc), buffer(0), dataLen, dataLen, 0)
Réception des données par le PC result = DoBulkXfer(usrUsbParametre.hDriverhandle, eRead, buffer, lngDataLen) ' Réception d'un buffer …. Function DoBulkXfer(hDriverhandle As Long, pipe As Integer, ByRef buffer() As Byte, ByRef dataLen As Long) As Long If pi.lNumberOfPipes <= pipe Then ' Le lien est-il correct DoBulkXfer = eBadPipe : Exit Function Else ' met le lien dans la structure BulkTransferControl btc.lPipeNum = pipe End If ' determine en fonction du No du EndPoint le sens du transfert If (pi.Pipes(pipe).bEndpointAddress > 128) Then result = DeviceIoControl(hDriverhandle, IOCTL_EZUSB_BULK_READ, btc, Len(btc), buffer(0), dataLen, dataLen, 0)
Budget approximatif Le coût du composant et circuits annexes ~ 25€ Outillage, film, cuivre et câblage ~240€ Outil de développement Cypress CY3671 ~ 600€ Kit de développement Keil ~2200€ Programmateur d'Eeprom ~800€
Bilan Parmi les problèmes rencontrés on peut citer Circuit CAO classe 5 Approvisionnement du composant Outils logiciels importants bien que plus facile que le bus PCI Prix du prototype et des outils de bases,… Parmi les points positifs Portabilité du protocole (PC, Mac, Unix) Utilisation d'un micro contrôleur famille 8051 Evolution des performances (USB 2.0) et (USB OTG On the Go pas de Host)
Bibliographie "Le bus USB Guide du concepteur" de Xavier Fenard, DUNOD, ISBN 2-10-004704-3 "Universal Serial Bus System Architecture, Second Edition" de Don Anderson / Dave Dzatko, MindShare, Inc., ISBN 0-201-30975-0 http://www.cypress.com http://www.usb.org