« SE4 2022/2023 EC5 » : différence entre les versions
m (Correction et ajout de référence vers les vidéos) |
m (Corrections) |
||
Ligne 36 : | Ligne 36 : | ||
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard. | Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard. | ||
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]] | [[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]] | ||
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. | J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. | ||
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je | J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description. | ||
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action ! | Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action ! | ||
Ligne 152 : | Ligne 152 : | ||
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens. | J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens. | ||
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un | Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus. | ||
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]] | [[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]] | ||
Ligne 170 : | Ligne 170 : | ||
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2. | On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2. | ||
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]]. | Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur<ref name=":0" group="Code associé">Configuration de l'horloge</ref>. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]]. | ||
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, | En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]<ref>Vidéo AT90 et Arduino/LCD qui récupère les caractères</ref>. | ||
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]] | [[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]] | ||
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]<ref>Vidéo démo Clavier -> AT90 (USART) -> ATMEGA -> PC</ref>. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés | Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]<ref>Vidéo démo Clavier -> AT90 (USART) -> ATMEGA -> PC</ref>. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base). | ||
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90. | On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90. | ||
Ligne 181 : | Ligne 181 : | ||
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel. | Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel. | ||
J'attaque désormais l'implémentation de la mémoire | J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu. | ||
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :<syntaxhighlight lang="c"> | Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :<syntaxhighlight lang="c" line="1"> | ||
int main(void) | int main(void) | ||
{ | { | ||
Ligne 207 : | Ligne 207 : | ||
{ | { | ||
KeyboardHost_Task(&page_actual, &page_buffer_size); | KeyboardHost_Task(&page_actual, &page_buffer_size); | ||
Flash_Task(&page_start, &page_actual, &page_buffer_size); | |||
USB_USBTask(); | USB_USBTask(); | ||
} | } | ||
Ligne 248 : | Ligne 248 : | ||
// ... | // ... | ||
} | } | ||
</syntaxhighlight>Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée afin de trouver | </syntaxhighlight>Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash. | ||
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé. | L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance) | ||
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.<syntaxhighlight lang="c"> | Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.<syntaxhighlight lang="c"> | ||
Ligne 314 : | Ligne 314 : | ||
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide. | * Si oui, on lit l'octet de commande et on attends que la voie série soit vide. | ||
* Ensuite on effectue une tâche selon le code: | * Ensuite on effectue une tâche selon le code: | ||
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin | ** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie. | ||
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer. | ** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer. | ||
*** On parcourt toutes les pages qui ont pu être enregistrées. | *** On parcourt toutes les pages qui ont pu être enregistrées. | ||
Ligne 321 : | Ligne 321 : | ||
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court) | *** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court) | ||
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à ''page_actual'' qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt ''FLASH_PAGE_SIZE'' | A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à ''page_actual'' qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt ''FLASH_PAGE_SIZE'' fois le tableau de donnée récupéré. | ||
Ligne 345 : | Ligne 345 : | ||
} | } | ||
} | } | ||
</syntaxhighlight>On lit quel bouton est appuyé et on le compare pour ensuite envoyé une commande via la liaison série. On peut observer un délai juste avant l'envoie de la commande qui est nécessaire pour être sur de l'envoyer qu'une seule fois. Sans ce délai, les commandes se serait envoyés plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecute rapidement et le temps entre l'appui du bouton et son relâchement, il y'a | </syntaxhighlight>On lit quel bouton est appuyé et on le compare pour ensuite envoyé une commande via la liaison série. On peut observer un délai juste avant l'envoie de la commande qui est nécessaire pour être sur de l'envoyer qu'une seule fois. Sans ce délai, les commandes se serait envoyés plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecute rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appuie et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction Flash_Task d'être executée plus d'une fois. | ||
Ligne 419 : | Ligne 419 : | ||
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. | |||
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essaie de code, j'ai observé qu'à chaque envoie d'octet via la liaison série et de la fonction '''''Serial_SendByte''''', on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série. | |||
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]]. | On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]]. | ||
Ligne 438 : | Ligne 439 : | ||
ReX : Erreur dans le <code>makefile</code>, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction <code>main</code> : | ReX : Erreur dans le <code>makefile</code>, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction <code>main</code> : | ||
CLKSEL0 = 0b00010101; // sélection de l'horloge externe | CLKSEL0 = 0b00010101; // sélection de l'horloge externe<ref name=":0" group="Code associé" /> | ||
CLKSEL1 = 0b00001111; // minimum de 8Mhz | CLKSEL1 = 0b00001111; // minimum de 8Mhz | ||
CLKPR = 0b10000000; // modification du diviseur d'horloge (CLKPCE=1) | CLKPR = 0b10000000; // modification du diviseur d'horloge (CLKPCE=1) |
Version du 12 août 2023 à 07:30
Objectifs
Il vous est demandé de :
- réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :
- un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,
- un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,
- une mémoire flash pour pouvoir sauver les touches capturées ;
- commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;
- poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;
- vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;
- enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;
- il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.
Matériel nécessaire
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.
Le Fichier:2023-keylogger-fritzing.zip fichier Fritzing de la carte est disponible (à renommer en .fzz
).
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [1].
Travail réalisé
Semaine 1
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA.
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !
Vidéo : Fichier:EC5-Semaine1.mp4[1]
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.
ReX : La fonction de délai est _delay_ms
, le fichier d'inclusion nécessaire est util/delay.h
.
Semaine 2
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) [Image 1], mais le périphérique reste inconnu pour ma machine.
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel FLIP et en suivant cette vidéo (https://youtu.be/Vd0F0XHzchY).
ReX : Tu tentes de faire le projet sous windows ?
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec dfu-programmer
.
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier (voir vidéo)[2].
ReX : Heu je te vois taper sur ton clavier ?
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !
Semaine 3
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance.
Fichier : Code_AT90USB
Question : Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel.
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers.
Semaine 4
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le wiki j'avais trouvé ce fichier, alors que vous faisiez référence à ce projet.
MassStorage : J'ai repris le code MassStoragePeiP et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.
Update : Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : lien).
ReX : Oui :)
KeyboardHost : J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...
J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.
// Et ça m'affiche le caractère A sur l'écran LED
putchar('A');
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.
NB : pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.
Semaine 5
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et trouvé. On peut voir la démonstration du programme avec la vidéo suivante[3].
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la vidéo suivante[4].
On retrouve le code des deux programmes via ce lien.
J'ai ajouté dans le code une fonction blink_ending pour distinguer les fins de fonction.
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en vidéo[5].
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur[Code associé 1]. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge ici.
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via ce lien[6].
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la vidéo suivante[7]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).
On peut retrouver ci-joint les deux programmes Keyboard et KeyboardHost qui sont exécutés respectivement sur l'Atmega et l'AT90.
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.
int main(void)
{
CLKPR = (1<<CLKPCE);
CLKPR = 0;
MCUCR |= (1<<JTD);
MCUCR |= (1<<JTD);
SetupHardware();
puts_P(PSTR(ESC_FG_CYAN "Keyboard HID Host Demo running.\r\n" ESC_FG_WHITE));
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
GlobalInterruptEnable();
/* Variable for the AT45DB641E */
int page_start = 0;
int page_actual = page_start;
int page_buffer_size = 0;
for (;;)
{
KeyboardHost_Task(&page_actual, &page_buffer_size);
Flash_Task(&page_start, &page_actual, &page_buffer_size);
USB_USBTask();
}
}
// ...
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)
{
// ...
/* Checking if the previous buffer was full to change pages or not */
if (*page_buffer_size == FLASH_PAGE_SIZE) {
*page_buffer_size = 0;
(*page_actual)++;
}
/* AT45DB641E communication */
/* Recup of the data of the actual page to re-write on */
unsigned char data[FLASH_PAGE_SIZE];
AT45DB641E_read_page(&SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);
/* Writing the Modifier and Keycode in the array */
data[(*page_buffer_size)++] = KeyCode;
/* Writing in the AT45DB641E buffer before writing in the flash */
AT45DB641E_write_buffer(&SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);
/* Writing the buffer into the flash at page_actual address */
AT45DB641E_write_page(&SPI_PORT, SPI_SS, *page_actual);
/* Waiting the flash finishing writing at page_actual address */
while(AT45DB641E_busy(&SPI_PORT, SPI_SS)) {
LEDs_TurnOnLEDs(LEDS_LED1);
}
LEDs_TurnOffLEDs(LEDS_LED1);
/* Serial communication */
Serial_SendByte(KeyCode);
// ...
}
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page page_actual. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance)
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)
{
/* Clear the report contents */
memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));
if (Serial_IsCharReceived())
{
ReportData->KeyCode[0] = Serial_ReceiveByte();
}
}
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction Serial_SendData pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.
De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF). Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)
{
if (Serial_IsCharReceived())
{
uint8_t Command_Byte = Serial_ReceiveByte();
uint8_t Ending_Byte;
do {
Ending_Byte = Serial_ReceiveByte();
} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));
if (Command_Byte == SERIAL_FLASH_RESET)
{
*page_actual = *page_start;
*page_buffer_size = 0;
}
if (Command_Byte == SERIAL_FLASH_GET)
{
uint8_t data[FLASH_PAGE_SIZE];
int address, j;
for (address = (*page_start); address <= (*page_actual); address++)
{
AT45DB641E_read_page(&SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);
for (j = 0; j < ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)
{
/* Communicating data by serial connection */
while (!Serial_IsSendReady());
Serial_SendByte(data[j]);
Serial_SendByte(data[j+1]);
while (!Serial_IsSendComplete());
_delay_ms(50);
}
}
}
}
}
- Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMEGA vers l'AT90.
- Si oui, on lit l'octet de commande et on attends que la voie série soit vide.
- Ensuite on effectue une tâche selon le code:
- SERIAL_FLASH_RESET qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.
- SERIAL_FLASH_GET qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.
- On parcourt toutes les pages qui ont pu être enregistrées.
- On récupère les touches tapés sur la page.
- On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).
- On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à page_actual qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt FLASH_PAGE_SIZE fois le tableau de donnée récupéré.
void Flash_Task(void)
{
uint8_t ButtonStatus_LCL = Buttons_GetStatus();
/* Reset flash button */
if (ButtonStatus_LCL & BUTTONS_BUTTON1){
_delay_ms(200);
Serial_SendByte(SERIAL_FLASH_RESET);
// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);
while(!Serial_IsSendComplete());
}
/* Get all the flash */
if (ButtonStatus_LCL & BUTTONS_BUTTON2){
_delay_ms(200);
Serial_SendByte(SERIAL_FLASH_GET);
// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);
while(!Serial_IsSendComplete());
}
}
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)
{
/* Clear the report contents */
memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));
if (Serial_IsCharReceived())
{
uint8_t ReceivedByte;
ReportData->KeyCode[0] = Serial_ReceiveByte();
do {
ReceivedByte = Serial_ReceiveByte();
} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData->KeyCode[0]));
ReportData->Modifier = ReceivedByte;
}
}
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)
{
//..
uint8_t KeyCode = KeyboardReport.KeyCode[0];
uint8_t Modifier = KeyboardReport.Modifier;
/* Check if a key has been pressed */
if (KeyCode)
{
/* Toggle status LED to indicate keypress */
LEDs_TurnOnLEDs(LEDS_LED2);
/* Serial communication */
Serial_SendByte(KeyCode);
Serial_SendByte(Modifier);
/* Checking if the previous buffer was full to change pages or not */
if (*page_buffer_size == FLASH_PAGE_SIZE) {
*page_buffer_size = 0;
(*page_actual)++;
}
/* AT45DB641E communication */
/* Recup of the data of the actual page to re-write on */
uint8_t data[FLASH_PAGE_SIZE];
AT45DB641E_read_page(&SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);
/* Writing the Modifier and Keycode in the array */
data[(*page_buffer_size)++] = KeyCode;
data[(*page_buffer_size)++] = Modifier;
/* Writing in the AT45DB641E buffer before writing in the flash */
AT45DB641E_write_buffer(&SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);
/* Writing the buffer into the flash at page_actual address */
AT45DB641E_write_page(&SPI_PORT, SPI_SS, *page_actual);
/* Waiting the flash finishing writing at page_actual address */
while(AT45DB641E_busy(&SPI_PORT, SPI_SS)) {
LEDs_TurnOnLEDs(LEDS_LED1);
}
LEDs_TurnOffLEDs(LEDS_LED1);
LEDs_TurnOffLEDs(LEDS_LED2);
}
}
// ...
}
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essaie de code, j'ai observé qu'à chaque envoie d'octet via la liaison série et de la fonction Serial_SendByte, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien ci-joint.
On peut voir beaucoup de ligne commentée, mais parmis elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.
On peut visionner la vidéo de démonstration du Keylogger via ce lien[8].
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'ancien programme se lance à la place des nouveaux ?
Documents Rendus
Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file
ReX : Erreur dans la fonction LEDs_ToggleLEDs
.
ReX : Erreur dans le makefile
, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction main
:
CLKSEL0 = 0b00010101; // sélection de l'horloge externe[Code associé 1] CLKSEL1 = 0b00001111; // minimum de 8Mhz CLKPR = 0b10000000; // modification du diviseur d'horloge (CLKPCE=1) CLKPR = 0; // 0 pour pas de diviseur (diviseur de 1)
Tests AT45DB641E : Fichiers de test mémoire
Tests AT90USB647 : Fichiers KerboardHost
Fichiers Keylogger : Fichiers Keylogger | Fichiers Keylogger sans la mémoire | Fichiers d'expérimentation pour la liaison série
Liste des références vidéo :
- ↑ Vidéo rapport semaine 1
- ↑ Video-atmega16u2-usb
- ↑ Vidéo test mémoire par commande
- ↑ Test mémoire en écriture et lecture
- ↑ Vidéo démo du programme KeyboardHost sur l'AT90
- ↑ Vidéo AT90 et Arduino/LCD qui récupère les caractères
- ↑ Vidéo démo Clavier -> AT90 (USART) -> ATMEGA -> PC
- ↑ Vidéo démo du Keylogger
Liste des références image :
Erreur de référence : Des balises <ref>
existent pour un groupe nommé « Code associé », mais aucune balise <references group="Code associé"/>
correspondante n’a été trouvée