Tutorat système SE4 : USBXavier Redon2022 - 2023 |
Vous allez programmer un périphérique USB basé sur un microcontrôleur ATMega16u2 et un utilitaire d’interaction avec ce périphérique USB via la bibliothèque libusb-1.0.
Le périphérique USB embarque quelques LED et des mémoires de capacité modeste. Vous pourrez le programmer directement par DFU (Device Firmware Update) USB, c’est à dire en basculant le périphérique dans une configuration USB particulière permettant de lui envoyer le programme à exécuter par le bus USB.
Votre but est de faire en sorte que le périphérique apparaisse comme un périphérique de stockage avec une fonctionnalité supplémentaire permettant d’obtenir quelques informations sur l’utilisation du périphérique.
Le périphérique USB a été conçu avec le logiciel KiCAD (projet keyloggerDevice.zip), voir son schéma électronique :
Le périphérique comporte principalement :
Comme vous l’avez compris, vous allez devoir écrire deux programmes.
Il s’agit du point le plus délicat du tutorat : la réalisation d’une interface USB de classe "Mass Storage" étendue.
Commencez par un test basique de la clef : faire clignoter une ou plusieurs LED. Avec un peu de soudure, vous pouvez aussi tester les boutons.
Pour le programme de test, vous pouvez partir de ce projet : TestLED.tgz.
La seconde étape est de tenter de communiquer avec les mémoires SPI. Lisez la documentation de la mémoire (DS-45DB641E-027-1385809.pdf). Pour
vous faciliter la vie une micro-bibliothèque de gestion des mémoires AT45DB641E est donnée : AT45DB641E.tgz. Récupérez les octets
d’identification des mémoires. Utilisez les LED de la carte pour communiquer les octets reçus.
Vous pouvez enfin passer à l’utilisation de la bibliothèque LUFA pour implanter un périphérique USB de classe Mass Storage.
Téléchargez la dernière version de la bibliothèque LUFA http://www.fourwalledcubicle.com/LUFA.php.
Créez un répertoire PolytechLille au même niveau que les répertoires Demos et Projects. Le principe serait
de recopier la démonstration de périphérique USB bas niveau MassStorage dans le répertoire PolytechLille et
de l’adapter pour le périphérique du tutorat. Mais, pour vous aider, une version modifiée de cette démonstration MassStorage
est donnée : MassStorageSimple.tgz. Dans cette version, vous n’avez à modifier que les fichiers Lib/DataflashManager.h
et Lib/DataflashManager.c.
Une tendance naturelle est de créer un tableau pour stocker une page mémoire mais avec un ATMega16u2, il vaut mieux éviter : ce microcontrôleur
ne possède que 512 octets de mémoire vive. Même allouer un tableau pour une page de 256 octets n’est pas une bonne idée sachant que la bibliothèque
LUFA consomme déjà de la mémoire. Vous écrirez donc les octets un à un dans le tampon d’écriture des mémoires et vous lirez les octets d’une page mémoire un à un.
La fonctionnalité supplémentaire est décrite dans la section 5.4.
Vous allez modifier le projet pour ajouter une interface "spécifique vendeur" et des points d’accès de type interruption.
Il faut un point d’accès "OUT" (sens hôte vers périphérique) et un point d’accès "IN" (sens périphérique vers hôte).
La déclaration des interfaces et des points d’accès se font dans les fichiers Descriptors.c et Descriptors.h.
La gestion des points d’interruption se fait dans l’autre source .c.
La démonstration Keyboard comporte déjà le code pour déclarer et exploiter des points d’accès de type interruption.
Inspirez-vous en (cherchez les fonctions Endpoint_ConfigureEndpoint, Endpoint_SelectEndpoint, etc).
N’hésitez pas à consulter la documentation de la bibliothèque LUFA sur Internet.
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 :
dfu-programmer atmega16u2 erase dfu-programmer atmega16u2 flash MassStorage.hex dfu-programmer atmega16u2 reset
Pour tester le bon fonctionnement de votre carte, procédez comme suit :
L’objectif est d’utiliser la bibliothèque USB libusb-1.0 pour écrire un programme C permettant de récupérer des informations de votre périphérique USB.
Vous avez le manuel complet de la bibliothèque à l’URL http://libusb.sourceforge.net/api-1.0/modules.html. Vous trouverez un résumé de la bibliothèque à l’URL http://rex.plil.fr/Enseignement/Systeme/Systeme.IMA4/. Pour cette utilisation assez basique nous utiliserons les fonctions de communication bloquantes.
Pour simplifier la programmation vous utiliserez la fonction libusb_open_device_with_vid_pid
pour trouver votre périphérique USB.
Faites afficher le numéro du bus sur lequel se trouve le périphérique ainsi que son adresse sur ce bus.
Commencez par récupérer la configuration courante du périphérique. La fonction libusb_get_active_config_descriptor
qui permet cela nécessite un pointeur sur périphérique de type libusb_device *. Vous pouvez obtenir ce pointeur en
fonction de la "poignée" dont vous disposez par la fonction libusb_get_device. Faites afficher la valeur de cette configuration.
Il vous reste ensuite à réclamer l’interface de type "spécifique vendeur" pour votre usage.
Attention, la fonction libusb_claim_interface nécessite le numéro de l’interface et pas son indice.
Vous allez donc parcourir la structure arborescente de description de configuration du périphérique de la façon suivante :
Affichez l’indice et le numéro de l’interface détectée et réclamée. Affichez aussi les numéros et directions des points d’accès trouvés.
Ecrivez une fonction qui libère le périphérique détecté. Pour cela, relachez l’interface réclamée puis fermez la "poignée". Pour faire cela facilement, vous aurez besoin du couple "poignée" et numéro d’interface. Prévoyez donc une structure pour pouvoir passer facilement ce couple de fonction en fonction. Affichez l’indice et le numéro de l’interface libérée.
Votre programme doit pouvoir s’utiliser dans deux modes différents, initialisation des informations et récupération des informations. Le mode est déterminé
par la valeur du premier paramètre passé au programme.
Dans le mode initialisation, votre programme va juste envoyer un octet au périphérique sur le point d’accès "OUT" de l’interface spécifique. A minima, le
programme doit permettre de remettre à zéro les compteurs de lecture et d’écriture des pages.
Dans le mode récupération, votre programme doit simplement lancer une requête sur le point d’accès "IN". Les quelques octets retournés doivent contenir
les informations sur votre "mémoire de masse", a minima le nombre de pages écrites et lues. Votre programme doit afficher ces informations de façon claire
pour un humain.
La fonction de la bibliothèque à utiliser pour les communications est libusb_interrupt_transfer.
Ce document a été traduit de LATEX par HEVEA