BE 2019-2020

De Wiki de bureau d'études PeiP

Présentation du bureau d'étude

Nous vous proposons de découvrir ce qu'est réellement cet objet devenu banal appelé clé USB (Universal Serial Bus).

Firefly-serenity-usb-flash-drive.jpg

Le bureau d'étude consiste à construire de A à Z une clé USB :

  • en créant un circuit électronique ou PCB (Printed Circuit Board) à l’aide d’un logiciel ;
  • en soudant des composants électroniques (micro-contrôleur, mémoire FLASH, ...) ;
  • en programmant le micro-contrôleur pour gérer la communication USB en utilisant la bibliothèque LUFA (Lightweight USB Framework for AVRs) ;
  • en programmant le micro-contrôleur pour accéder à la mémoire ;
  • en fabriquant un beau boitier pour votre clef.

Pour personnaliser votre clé n'hésitez pas à ajouter des fonctionnalités :

  • LED qui clignotent lors des accès en lecture ou écriture ;
  • vumètre qui indique le remplissage de la clé ;
  • micro-interrupteurs pour verrouiller la clé ;
  • vibreur parce que c'est possible, vous trouverez bien une justification ;
  • microphone permettant d’espionner les conversations ;
  • toute autre fonction plus ou moins utile mais qui vous inspire ...

Les supports de la présentation de ce bureau d'études : Media:BE_clef_USB.pdf.

Survol d'USB

Evolution des connexions USB

L'acronyme USB signifie "Universal Serial Bus" et effectivement l'USB peut être défini comme un bus USB très verbeux. L'USB est géré par un consortium autonome "USB Implementers Forum".

USB-2.png
Jusqu'à la version 2, l'acronyme est fidèle à la réalité. Pour ces périphériques, 3 vitesses de transfert sont possibles sur la paire différentielle :
  • basse vitesse : 1,5 Mb/s ;
  • pleine vitesse : 12 Mb/s ;
  • haute vitesse : 480 Mb/s.


USB-3.jpg
A partir de l'USB 3.0, la notion de bus série est un peu oubliée. La vitesse augmente en utilisant les deux nouvelles paires blindées : 5Gb/s (super vitesse).


USB-4.png
Et maintenant USB (USB 3.1, USB 3.2, USB 4) se prend pour de l'Ethernet. En effet, le connecteur USB-C ajoute, à la paire historique, quatre paires blindées. USB 3.2 promet des vitesses jusqu'à 20G/s.


Un protocole verbeux

USB-communication.gif

L'initialisation d'un périphérique USB se fait comme suit :

  • détection électrique de la connexion du périphérique ;
  • alimentation électrique du périphérique ;
  • utilisation de l'adresse temporaire 0 sur le bus ;
  • récupération de la taille des messages pour le point d'accès 0 ;
  • envoi de l'adresse au périphérique sur le point d'accès 0 ;
  • envoi des descripteurs du périphérique au contrôleur USB via le point d'accès 0.

Pour un périphérique simple :

  • souris : environ 100 octets pour le descripteur de configuration ;
  • clavier : environ 150 octets pour le descripteur de configuration.


USB-descripteurs.gif

Les points d'accès (terminaison sur le schéma) :

  • des identifiants sur 8 bits (numéro sur 4 bits) ;
  • un point d'accès de contrôle de numéro 0 bidirectionnel ;
  • les communications se font de ou vers les points d'accès ;
  • un sens de communication (bit de poid fort) :
    • IN => du périphérique vers le contrôleur ;
    • OUT => du contrôleur vers le périphérique.
  • la direction est IN ou OUT vis à vis de l’hôte.

Plusieurs types de points d'accès :

  • isodromique (isochronous) : débit réservé (e.g. vidéo en temps réel) ;
  • par interruption (interrupt) : latence garantie (e.g. souris) ;
  • de volume (bulk) : débit maximal sans garantie (e.g. clef mémoire).


Logiciels

Pour la conception de circuits imprimés nous vous recommandons le logiciel fritzing.

Pour la découpe laser de nombreux utilisateurs utilisent inkscape.

Pour la conception 3D vous pouvez tenter freeCAD. Une solution en ligne existe : onshape.

Pour la programmation du micro-contrôleur vous utiliserez le compilateur C avr-gcc et le logiciel de téléversement dfu-programmer.

Les composants électroniques

ATMega16u2

Le coeur de votre clé va être un micro-contrôleur AVR plus exactement l'ATMega16u2. Ce micro-contrôleur possède l'électronique nécessaire pour la gestion d'un bus USB 2.0. Un document très important pour comprendre le fonctionnement de ce micro-contrôleur est le document technique (datasheet en patoi) : [1].

AT45DB641E-SHN2B-T
MT29F128G8

Sans mémoire une clé n'est pas une clé.

Vous pouvez utiliser des mémoires AT45DB641E faciles à gérer avec un ATMega16u2. Ces mémoires sont accessibles par un bus série SPI et facile à souder. Par contre elles sont de faible capacité (64Mb). Le document technique [2] de ces mémoires permet de connaître les commandes pour les configurer et y accéder en lecture et en écriture.

Si vous êtes téméraire, vous pouvez utiliser une mémoire MT29F128G8 accessible par un bus de 8 bits, plus difficile à souder, plus difficile à programmer mais d'une capacité intéressante (128Gb). La documentation technique est plus difficile à trouver, il faut aller sur le site du fabricant (micron) et montrer patte blanche. Vous trouverez le document dans le répertoire éponyme des machines de projet.

Il vous faudra aussi quelques autres composants comme un quartz, des résistances, des condensateurs, des diodes, des régulateurs de tension et bien sur des LED pour ajouter un peu de lumière. La carte de base peut être décrite comme suit.

  • Le micro-contrôleur peut être accompagné d'un quartz à 8Mhz et de ses condensateurs et résistance.
  • Le micro-contrôleur peut être alimenté par le connecteur USB en 5v (broche UVCC) mais avec ses lignes VCC et AVCC bouclées sur la sortie UCAP du régulateur 3.3v interne.
  • Un convertisseur 5v vers 3.3v est nécessaire pour l'alimentation des mémoires.
  • Le micro-contrôleur dialogue avec les mémoires par le bus SPI, une ligne de sélection est nécessaire par mémoire.

Pour la conception de votre clé vous pouvez vous appuyer sur un prototype de clef réalisé pour ce bureau d'études.

Cartes version alpha

Schéma électronique
Carte électronique


Le schéma décrit le circuit électronique partie par partie. A partir du circuit, il faut créer une carte sans croisement de pistes pour éviter les court-circuits. Le fichier source Fritzing est disponible : Media:cle_usb.zip (renommer en .fzz).

Une autre carte est disponible pour une mémoire parallèle de plus grande capacité. Attention cette carte n'a pas été testée.

Schéma électronique
Carte électronique


Le fichier source Fritzing est disponible : Media:cle_usb_bis.zip (renommer en .fzz).

Cartes version beta

Schéma électronique
Carte électronique

Une piste parasite entre masse et 3,3v a été supprimée, le reset est en 3,3v et un mini-connecteur ICSP a été ajouté. Le fichier source Fritzing est disponible : Media:cle_usbv2.zip (renommer en .fzz).

Schéma électronique
Carte électronique

Le reset est en 3,3v et un mini-connecteur ICSP a été ajouté. Le fichier source Fritzing est disponible : Media:cle_usb_bisv2.zip (renommer en .fzz).

Il peut y avoir des problèmes lors du chargement des fichiers, des composants peuvent être déclarés absents. Essayez d'importer les composants suivants :

Renommez les fichiers de .zip en .fzpz avant de les importer dans Fritzing.

Test des cartes

Premier test, faire clignoter une LED par programmation DFU

Recto des deux cartes
Verso des deux cartes

Vision recto et verso des deux circuits décrit dans la section précédente (ancienne version à gauche). A noter que dans l'ancienne version seule les deux puces mémoire se trouvent au recto. Pour la nouvelle version la carte a du être agrandie et le micro-contrôleur rejoint la mémoire au verso.

La première étape de test consiste à insérer les PCB dans un port USB. Remarquez la sur-épaisseur réalisée à l'aide d'un papier un peu épais pour assurer le contact. Si l'ATMega16u2 est fonctionne correctement, en lançant l'utilitaire lsusb vous devez voir apparaître un périphérique labellé Atmel DFU device.

Pour tester plus en avant, il est proposé d'envoyer sur le micro-contrôleur un programme permettant de faire clignoter la LED connectée au micro-contrôleur (la LED est contrôlée par PB6 sur l'ancienne version et sur PB0 sur la nouvelle).

Vous pouvez trouver les programmes de test dans cette archive : Media:ClefUSB.zip. Pour compiler les programmes, il suffit de se placer dans le répertoire correspondant à la version de la clef et lancer le makefile avec la commande make. Pour télécharger le programme un simple make upload suffit. Pour remettre les micro-contrôleur en mode DFU pour les reprogrammer, il faut court-circuiter les broches reset et de la masse (connecteur à deux broches sur les deux cartes).

Premier problème, correction par programmation SPI

Voila le résultat de l'exécution du programme de test du micro-contrôleur sur la nouvelle version : Media:ClefUSBTestLed.mp4.

Force est de constater un problème, la LED clignote bien trop lentement. Quelques recherches apprennent que les ATMega16u2 sont vendus configurés avec un diviseur d'horloge par 8 activé. Le micro-contrôleur fonctionne donc à 1MHz et pas à 8Mhz comme souhaité. Ce type de configuration passe par une reconfiguration des fuses du micro-contrôleur. Manque de chance ces fuses ne peuvent être changées que par programmation SPI : impossible de les modifier en mode DFU. Voir le paragraphe ci-après pour comprendre comment se fait une programmation par SPI.

Ancienne clef, fils soudés au vol et programmateur SPI
Nouvelle clef, fils soudés sur le micro-ICSP et programmateur SPI

Les premières version de PCB n'étaient pas prévues pour ce type de programmation. Le mode DFU semblait suffisant. Pour faciliter cette programmation, des via ont été placées de façon à implanter un mini connecteur ICSP. Une erreur a été corrigée en passant : la ligne reset du micro-contrôleur était alimentée en 5v, elle a été passée à 3,3v. En attendant les nouvelles cartes, des fils ont été soudés sur les cartes pour avoir un accès au bus SPI et au reset. D'ailleurs, une malheureuse tentative de programmation en 5v ayant grillé les micro-contrôleur, d'autres cartes version alpha ont du être soudées.

Une fois le dispositif de programmation SPI adéquat mis au point, une configuration est tentée pour désactiver la division de l'horloge (modification de la valeur de l'octet de configuration appelé lfuse) :

 avrdude -c arduino -p atmega16u2 -P /dev/ttyACM0 -b 19200 -U lfuse:w:0xFF:m



Cette configuration échoue : le micro-contrôleur est passé, en usine, en état verrouillé. Vous pouvez vérifier cela avec la commande ci-dessous et en utilisant l'outil de calcul des fuses en ligne [3].

 avrdude -c arduino -p atmega16u2 -P /dev/ttyACM0 -b 19200 -U lock:r:-:h

Il faut donc totalement réinitialiser le micro-contrôleur :

 avrdude -c arduino -p atmega16u2 -P /dev/ttyACM0 -b 19200 -t
 avrdude> erase
 avrdude> quit

Il est alors possible de modifier l'octet de configuration lfuse comme indiqué ci-dessus. Sauf que maintenant le micro-contrôleur ne contient même plus l'amorçeur. Il n'est plus possible de le programmer en mode DFU. Il ne semble pas possible de mettre la main sur l'amorceur du fondeur pour ATMega16u2. Heureusement l'amorceur pour une précédente version de la puce est disponible : media:at90usb162-bl-usb-1_0_5.zip. Il est assez simple d'installer l'amorceur par programmation SPI :

 avrdude -c arduino -p atmega16u2 -P /dev/ttyACM0 -b 19200 -U flash:w:at90usb162-bl-usb-1_0_5.hex

Après la modification de l'octet de configuration lfuse, la LED clignote normalement : media:ClefUSBTestLedBis.mp4. A noter qu'il faut maintenant télécharger le programme en utilisant at90usb162 comme cible au lieu de atmega16u2 à cause de la différence d'amorceur.

Second test, accès aux mémoires

Il faut maintenant souder le régulateur 3,3v pour alimenter les mémoires et aussi souder les-dites mémoires.

Ensuite il faut tester si l'accès aux mémoires fonctionne. Les programmes sont différents suivant les types de mémoire.

Test des mémoires AT45DB641E

Mémoires AT45DB641E

Pour tester une des deux mémoires, il faut déjà sélectionner la mémoire sur le bus SPI. La première mémoire se sélectionne en passant la ligne PD0 à l'état bas. Pour la seconde mémoire, il faut utiliser la ligne PB4. La broche reset des deux mémoires est reliée à la ligne PB5 du micro-contrôleur. Il faut donc passer PB5 en sortie et la mettre à l'état haut.

Pour tester une mémoire, il est possible de demander ses identifiants. Pour cela, il faut envoyer sur le bus SPI, une fois la mémoire sélectionnée, l'octet 0x9F. Ensuite, il faut lire les cinq octets des identifiants (ID fabricant, ID de la mémoire, ...) puis il faut remonter la ligne de sélection à l'état haut.

Un programme de test est disponible Media:ClefUSBTestMem.zip. Pour communiquer la valeur des cinq octets d'identification, un système de clignotement de LED est implanté. Pour chaque bit un clignotement représente un 0 et deux clignotement représentent un 1. Le prototype de clef USB avec des mémoires AT45DB641E passe avec succès ce test.

Pour aller plus loin, il faut écrire dans les mémoires et vérifier, par une lecture, que les écritures ont été bien effectuées. Un programme de test est disponible Media:ClefUSBTestMemRW.zip. Ce programme écrit cinq octets dans la première mémoire, les lit, les multiplie par 2 et écrit les résultats dans la seconde mémoire. Les cinq octets de la seconde mémoire sont lus et communiqués avec le système de clignotement de LED décrit ci-dessus.

Test de la mémoire MT29F128G8

Cette mémoire est sélectionnée par défaut. Il faut juste arriver à lui envoyer un ordre en utilisant les 8 lignes de contrôle.

Programmation de micro-contrôleur par SPI

Nativement les micro-contrôleurs AVR peuvent être programmés via le bus SPI. Généralement un amorceur (bootloader) est installé sur ces micro-contrôleurs pour qu'ils puissent être programmés plus facilement par une connexion série pure (cas de l'ATMega328p par exemple) ou par une connexion USB (cas de l'ATMega16u2). Malheureusement les amorceurs peuvent être effacés par une mauvaise manoeuvre ou ne permettent pas de configurer tous les aspects du micro-contrôleur.

Arduino Uno comme programmateur

Généralement pour une programmation de micro-contrôleur par bus SPI, un connecteur ICSP est utilisé. Ce connecteur regroupe les lignes du bus SPI, la masse, l'alimentation et le reset. Un simple Arduino UNO peut-être utilisé comme programmateur par bus SPI. Les lignes MISO, MOSI, SCK, GND, VCC du programmateur sont connectées sur les mêmes lignes de la cible. La ligne 10 du programmateur est connectée sur le reset de la cible. Le programme ArduinoISP doit être téléversé sur le UNO jouant le rôle de programmateur. Ce programme fait partie des exemples fournis avec l'IDE Arduino.

Un exemple d'utilisation d'un programmateur par bus SPI pour obtenir les fuses d'un ATMega16u2 (les fuses sont des octets de configuration bas niveau du micro-contrôleur) :

avrdude -c arduino -p atmega16u2 -P /dev/ttyACM0 -b 19200 -v

Un exemple pour télécharger un programme par SPI sur un ATMega16u2 :

avrdude -c arduino -p atmega16u2 -P /dev/ttyACM0 -b 19200 -U flash:w:programme.hex

Dans ces exemples, il est supposé que le port série associé à l'UNO est /dev/ttyACMO.

Arduino mini-pro comme programmateur

Si le micro-contrôleur est alimenté en 3,3v utiliser un Arduino Uno comme programmateur est une mauvaise idée : un UNO fonctionne à 5v et la communication SPI entre une plateforme à 5v et une autre à 3,3v ne fonctionne pas. Il existe assez peu de plateformes Arduino en 3,3v. Vous pouvez utiliser un Arduino Mini Pro 3,3v en conjonction avec un FTDI (convertisseur USB/série) lui aussi en 3,3v. Le Mini Pro ne dispose pas d'un connecteur ICSP. Il faut utiliser la ligne 11 pour connecter la ligne MOSI de la cible, la ligne 12 pour MISO et la ligne 13 pour SCK.

L'utilitaire avrdude peut être utilisé pour programmer la cible comme avec le programmateur à base d'UNO. Attention le port série sera probablement /dev/ttyUSBO cette fois.

Bibliothèque LUFA

Pour la gestion du bus USB par le micro-contrôleur nous allons nous appuyer au maximum sur la bibliothèque USB LUFA. Cette bibliothèque permet d'exploiter plus facilement les aspects USB des micro-contrôleurs AVR comme l'ATMega16u2.

Vous pouvez télécharger la dernière version de la bibliothèque [4]. Il est ensuite conseillé d'effectuer quelques manipulations pour pouvoir développer dans de bonnes conditions.

  • Créez un répertoire PolytechLille au même niveau que les répertoires Demos et Projects.
  • Dans ce répertoire copiez la démonstration de périphérique USB bas niveau MassStorage. Au niveau du makefile indiquez atmega16u2 comme micro-contrôleur, NONE comme platine et restez à 8Mhz.
  • Il faut ensuite modifier la configuration de la mémoire et les fonctions d'accès à cette mémoire dans le sous-répertoire Lib du répertoire PolytechLille/MassStorage. Pour vous aider une version modifiée de la démonstration MassStorage est disponible media:MassStoragePeiP.zip. Dans cette version, vous n'avez à modifier que les fichiers Lib/DataflashManager.h et Lib/DataflashManager.c en vous appuyant sur les programmes de test des mémoires.

Pour téléverser votre programme sur l’ATMega16u2, le paquetage Debian dfu-programmer est nécessaire. Installez-le au besoin. La procédure à suivre pour charger votre programme sur l’ATMega16u2 est la suivante :

  • court-circuitez momentanément les lignes reset et masse de l’ATMega16u2, l'utilitaire lsusb doit lister la carte comme étant en mode DFU, vous pouvez alors exécuter les commandes suivantes :
    • dfu-programmer atmega16u2 erase
    • dfu-programmer atmega16u2 flash MassStorage.hex
    • dfu-programmer atmega16u2 reset
  • débranchez et rebranchez votre carte, votre programme doit être actif sur le micro-contrôleur.

Test du programme avec la bibliothèque LUFA

Un premier test très simple à réaliser consiste à compiler le programme MassStoragePeiP sans ajouter les accès à la mémoire puis à le télécharger sur le micro-contrôleur. Vous devriez déjà vous apercevoir que votre carte est reconnue comme une clef USB. Sur un système Linux, les deux utilitaires dmesg et lsblk vous en convaincront.

# dmesg | tail
[21942.134207] usb 1-1: new full-speed USB device number 4 using xhci_hcd
[21942.333156] usb 1-1: New USB device found, idVendor=03eb, idProduct=2045, bcdDevice= 0.01
[21942.333161] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[21942.333163] usb 1-1: Product: LUFA Mass Storage Demo
[21942.333166] usb 1-1: Manufacturer: Dean Camera
[21942.333168] usb 1-1: SerialNumber: 758303337383514140C1
[21942.339211] usb-storage 1-1:1.0: USB Mass Storage device detected
[21942.339407] scsi host6: usb-storage 1-1:1.0
[21943.358141] scsi 6:0:0:0: Direct-Access     LUFA     Dataflash Disk   0.00 PQ: 0 ANSI: 0
[21943.358778] sd 6:0:0:0: Attached scsi generic sg2 type 0
[21943.359523] sd 6:0:0:0: [sdb] 2048 512-byte logical blocks: (1.05 MB/1.00 MiB)
[21943.359910] sd 6:0:0:0: [sdb] Write Protect is off
[21943.359915] sd 6:0:0:0: [sdb] Mode Sense: 00 00 00 00
[21943.360221] sd 6:0:0:0: [sdb] Asking for cache data failed
[21943.360241] sd 6:0:0:0: [sdb] Assuming drive cache: write through
[21943.404925] sd 6:0:0:0: [sdb] Attached SCSI removable disk
# lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 119,2G  0 disk 
├─sda1   8:1    0 114,4G  0 part /
├─sda2   8:2    0     1K  0 part 
└─sda5   8:5    0   4,9G  0 part [SWAP]
sdb      8:16   1     1M  0 disk 
sr0     11:0    1  1024M  0 rom

Pour vous familiariser avec le code, vous pouvez tenter de changer les noms du produit, du fabricant, le numéro de série et même la taille de la clef.

Avant de faire un test de votre clef avec un système de fichier, vous pouvez tester si elle gère correctement ses blocs mémoires. Le programme media:TestBlock.zip permet d'effectuer une écriture dans les blocs et, dans un second temps, de vérifier que ces blocs contiennent bien les bonnes valeurs. Pour l'utiliser, insérez votre clef, trouvez le nom du périphérique avec la commande lsblk et lancez la commande ci-dessous (ici il est supposé que le nom du périphérique est /dev/sdb) :

./testblock /dev/sdb W

Une fois le programme terminé, enlevez la clef pour s'assurer que la lecture ne se fera pas dans les tampons, remettez la et envoyez la commande :

./testblock /dev/sdb R

Si le programme ne vous affiche pas de différence d'octet, c'est que votre clef fonctionne correctement.

Vous pouvez alors formater votre clef :

 mkfs -t vfat /dev/sdb

La monter :

 mount /dev/sdb /mnt

Mettre quelques fichiers dessus, la démonter (avec la commande umount) et vérifier que vos fichiers sont encore là quand vous reconnectez la clef.

Réalisations des binômes

Numéro Elèves Fonctionnalité supplémentaire Page
Binôme 1 Nicolas DEBAISIEUX & Maxence FLAMENT Affichage température par leds Binôme 1 2019/2020
Binôme 2 Eve POITEVIN & Alix DUFOUR Déverrouillage par haut volume sonore Binôme 2 2019/2020
Binôme 3 Corentin GIELIN & Julien DUMON Afficheurs 7-seg en tant que vumètre numérique Binôme 3 2019/2020
Binôme 4 Clément DELECOURT & Thomas MOSTOWFI Signal mauvaise orientation Binôme 4 2019/2020
Binôme 5 Gaëtan DELPLANQUE & Tristan PAYEN Verrouillage code Binôme 5 2019/2020
Binôme 6 Louise MAES & Léo POUMAER Ecran LCD + vumètre + affichage nom fichier Binôme 6 2019/2020
Binôme 7 Martin SERGEANT & Quirin DECAUDIN Binôme 7 2019/2020
Binôme 8 Mateo POURRIER & Martin PLAUD Binôme 8 2019/2020
Binôme 9 Baptiste BLACK & Alexandre ROUSSEL Hub + Vumètre Binôme 9 2019/2020
Binôme 10 Theo DELAUNOIS & Antoine MALENGE Code d'accès + Grande mémoire + leds Binôme 10 2019/2020
Binôme 11 Florian DERLIQUE & Ahimen BENDIF Affichage heure Binôme 11 2019/2020