Tutorat système IMA4 (USB et ATMega32u4)Julien Forget, Xavier Redon et Thomas Vantroys2021 - 2022 |
Le but de ce tutorat est de comprendre le fonctionnement du bus USB par la pratique. Pour cela, vous allez utiliser une carte spécifiquement conçue pour ce tutorat à base de microcontrôleur ATMega32u4. Vous trouverez de précieuses informations sur cette carte à l’URL https://wiki-ima.plil.fr/mediawiki/index.php/IMA4_2018/2019_SEC4.
Vous aurez à programmer la carte comme périphérique USB de type joystick. Vous aurez aussi à programmer utilitaire sur PC avec la libusb-1.0 pour gérer les LED et les vibreurs de la carte.
Pour le tutorat vous disposerez d’une carte manette Polytech’Lille et de son câble USB. Si vous manipulez correctement, vous n’aurez besoin d’aucun autre matériel. En cas de microcontrôleur non initialisé ou briqué, il est toujours possible de flasher l’ATMega32u4 au travers de son connecteur ICSP. Un connecteur ICSP dispose de toutes les lignes permettant de flasher un ATMega, à savoir l’alimentation, le reset et les lignes du bus SPI. Si vous en arrivez là, il vous faudra un Arduino à utiliser comme programmateur et quelques câbles pour connecter l’Arduino à la manette. Référez-vous au site de la manette pour le détail de la procédure.
La carte comporte un accéléromètre que vous allez utiliser durant ce tutorat. Le PCB de la carte comporte une erreur concernant l’accéléromètre, laquelle ? Comment ce bogue de conception de la carte a-t-il été corrigé ?
Vous allez devoir écrire deux programmes.
Il s’agit du point le plus délicat du tutorat, la programmation du comportement USB de la manette. Cela va se faire sur le microcontrôleur
ATMega32u4. Comme le u de son nom l’indique, ce microcontrôleur possède une gestion matérielle du bus USB (USB2.0).
Sur le principe vous devez implanter un périphérique USB HID (périphérique d’interface homme-machine, Human Interface Device en patoi).
Un tel périphérique comporte une interface de classe HID avec au minimum un point d’accès entrant (IN). Plutôt que d’utiliser le joystick
de la carte pour votre HID, vous utiliserez l’accéléromètre.
Vous allez ajouter à ce périphérique USB une interface supplémentaire pour gérer les LED et les vibreurs. L’interface supplémentaire doit
présenter un point d’accès de type interruption en écriture (endpoint OUT). Les données envoyéies sur ce point d’accès doivent avoir une
taille de deux octets. Organisez les bits correspondant aux LED et aux vibreurs comme vous l’entendez.
Pour téléverser votre programme sur l’ATMega32u4, le paquetage Debian dfu-programmer est nécessaire. Installez le au besoin. La procédure à suivre pour charger votre programme sur l’ATMega32u4 est la suivante :
dfu-programmer atmega32u4 erase dfu-programmer atmega32u4 flash Manette.hex dfu-programmer atmega32u4 reset
Commencez par un test basique de la clef : faites clignoter des LED, activez un vibreur. Testez aussi les boutons et l’accéléromètre. Pour le programme de test, vous pouvez partir du programme disponible sur la page de description de la carte.
Sur le site http://www.fourwalledcubicle.com/LUFA.php, téléchargez la dernière version de la bibliothèque USB LUFA. 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 du sous-chemin Device/ClassDriver/Joystick sous le nom, par exemple, Manette. Renommez aussi les fichiers dans le répertoire et modifiez le makefile. Au niveau du makefile indiquez atmega32u4 comme microcontrôleur, NONE comme platine, ajustez le chemin d’accès LUFA_PATH et passez à 16Mhz.
Importez les fonctions de gestion de la carte Polytech’Lille dans le répertoire PolytechLille/Manette. Modifiez le fichier makefile pour compiler ces sources. Modifiez ensuite le fichier Manette.c, en particulier la fonction CALLBACK_HID_Device_CreateHIDReport pour créer des rapports HID en fonction des valeurs retournées par l’accéléromètre.
En toute théorie, il serait possible d’intégrer la gestion des LED et des vibreurs sous la classe USB HID. Le moins que l’on puisse dire c’est que
cela complexifie considérablement le descripteur HID et encore il faut faire de l’ingéniérie inverse pour le constituer. Nous allons donc procéder
autrement. Vous allez ajouter, à l’interface standard HID, une autre interface de classe spécifique au vendeur (USB_CSCP_VendorSpecificClass,
pas de descripteur supplémentaire nécessaire) peuplée d’un point d’accès de type interruption en écriture (endpoint OUT). La communication sur ce
point d’accès se fera sur deux octets. Le premier octet peut commander les 8 premières LED, le second octet peut commander les LED restantes et
les deux vibreurs.
Pour la gestion des points d’accès interruption, vous pouvez vous aider de la démonstration Keyboard dans le répertoire Device/LowLevel.
La déclaration des interfaces et des points d’accès est clairement montrée dans les fichiers Descriptors.c et Descriptors.h de cette
démonstration. La gestion de points d’accès de type interruption est montrée dans l’autre source C de la démonstration, cherchez les fonctions
Endpoint_ConfigureEndpoint, Endpoint_SelectEndpoint, etc.
N’hésitez pas à consulter la documentation de la bibliothèque sur Internet.
Utilisez la bibliothèque USB libusb-1.0 pour écrire un programme C permettant de contrôler les LED et les vibreurs de la manette 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.
Ecrivez une fonction pour examiner tous les périphériques USB disponibles sur les bus USB
de votre machine de TP. Dès qu’un périphérique s’avère être un périphérique USB du type cherché,
sauvez la "poignée" (obtenue avec libusb_open) vers ce périphérique dans un tableau statique
global de type libusb_device_handle[].
Vous pouvez utiliser la commande lsusb pour trouver les identifiants USB de votre type de
périphérique. Pour chaque périphérique sélectionné, faites afficher le numéro du bus sur lequel
se trouve le périphérique ainsi que son adresse sur ce bus.
Une fois un périphérique détecté, il faut récupérer sa configuration. La fonction
libusb_get_active_config_descriptor qui permet cela nécessite un pointeur
sur périphérique de type libusb_device *. Vous pouvez retrouver ce pointeur en fonction de
la "poignée" par la fonction libusb_get_device. Faites afficher la valeur de cette configuration.
Il vous reste ensuite, à réclamer les interfaces nécessaires 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 chaque interface détectée et réclamée. Affichez aussi le numéro du point d’accès trouvé.
Ecrivez une fonction qui libère les périphériques détectés. Pour cela, relachez toutes les interfaces réclamées puis fermez la "poignée". Vous allez devoir, à nouveau, explorer la structure arborescente de description de configuration du périphérique ou sauver les numéros des interfaces dans le tableau global. Affichez l’indice et le numéro de chaque interface libérée.
Dans un premier temps, testez les manettes en allumant des LED et en actionnant les vibreurs. Par exemple, réalisez un chenillard avec vibrations en fin de chaque balayage. Sur arrêt du programme par CTRL-C, éteignez les LED et désactivez les vibreurs et fermez le périphérique USB. La gestion des LED et des vibreurs des manettes doit être effectuée via le point d’accès OUT de l’interface spécifique. Pour communiquer avec les manettes vous utiliserez la fonction libusb_interrupt_transfer. Les LED et les vibreurs doivent être activés sur toutes les manettes connectées.
Pour mettre les dernières touches à votre tutorat :
Ce document a été traduit de LATEX par HEVEA