Reconfiguration d'un FPGA : Différence entre versions
(→Spécifications techniques) |
|||
(38 révisions intermédiaires par un autre utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
+ | <include nopre noesc src="/home/pedago/pimasc/include/video-ReconfigurationFPGA-iframe.html" /> | ||
+ | __TOC__ | ||
+ | <br style="clear: both;"> | ||
+ | Wiki du projet de reconfiguration d'un FPGA. | ||
− | + | Le wiki est classé par thème mais chronologique : La prise en main de la Beaglebone Black a commencé avant la carte de test, etc. | |
+ | |||
+ | = Cahier des charges = | ||
Projet réalisé par ''Simon Malthieu''. | Projet réalisé par ''Simon Malthieu''. | ||
Ligne 6 : | Ligne 12 : | ||
Tuteurs : ''Alexandre Boé'', ''Thomas Vantroy'', ''Mickaël Coronado''. | Tuteurs : ''Alexandre Boé'', ''Thomas Vantroy'', ''Mickaël Coronado''. | ||
− | Suite à la réunion avec Mickaël Coronado, gérant de Inodesign, le cahier des charges suivant a été établi : | + | Suite à la réunion avec Mickaël Coronado, gérant de Inodesign, le cahier des charges suivant a été établi : |
− | + | == Description du projet == | |
− | Le but du projet est de permettre une mise à jour aisé d'un FPGA. Il y a deux manières de programmer un FPGA. Soit directement via une liaison J-TAG. Dans ce cas-ci, le FPGA | + | Le but du projet est de permettre une mise à jour aisé d'un FPGA. Il y a deux manières de programmer un FPGA. Soit directement via une liaison J-TAG. Dans ce cas-ci, le FPGA doit être reprogrammé à chaque mise sous tension. Il existe cependant une autre solution, qui consiste à associer une mémoire de type EEPROM au FPGA. Ainsi, il suffit d'écrire le bitstream dans la mémoire, et le FPGA va lire l'EEPROM à chaque mise sous tension. |
− | Les deux manières devront être développées. | + | Les deux manières devront être développées. (obsolète au 02/04) |
L'interface devra aussi pouvoir vérifier l'intégrité des données, afin d'éviter un chargement de bitstream corrompu. | L'interface devra aussi pouvoir vérifier l'intégrité des données, afin d'éviter un chargement de bitstream corrompu. | ||
− | L'autre partie du projet consiste à gérer la partie récupération du bitstream par FTP, ou mieux par SFTP. L'ensemble devra donc être autonome, de la récupération du bitstream à programmation du FPGA. | + | L'autre partie du projet consiste à gérer la partie récupération du bitstream par FTP, ou mieux par SFTP. L'ensemble devra donc être autonome, de la récupération du bitstream à programmation du FPGA. (obsolète au 02/04) |
+ | |||
+ | '''EDIT 02/04''' : Suite à une réunion avec Mickael Coronado à propos de l'avancement de projet, il a été décidé d'abandonner la transmission par J-TAG et de se concentrer sur une interface web permettant l'upload de bitstream et le contrôle du programme. | ||
+ | |||
+ | == Objectifs du projet au 02/04 == | ||
+ | |||
+ | * Concevoir un programme, exécuté par un ordinateur embarqué de type Beaglebone Black, permettant d'écrire dans une EEPROM de type M25P80 un fichier bitstream de FPGA | ||
+ | * Le programme devra aussi pouvoir vérifier l'intégrité des données écrites dans la mémoire | ||
+ | * Développer une interface web permettant de contrôler le programme : Elle doit permettre de téléverser un fichier sur l'ordinateur et exécuter le programme d'écriture avec ce fichier | ||
− | + | == Spécifications techniques == | |
− | La plateforme choisie pour | + | '''Materiel''' |
+ | |||
+ | La plateforme choisie pour piloter l'EEPROM est la Beaglebone black. C'est un micro-ordinateur miniature embarquant un processeur Texas Instrument, modèle Sitara XAM3359AZCZ100 Cortex A8 ARM cadencé à 1 GHz. Une exemplaire de cette plateforme est prêté par Mickaël Coronado pour les besoins du projet. | ||
+ | Cet ordinateur est adapté au prototypage car, contrairement au Raspberry Pi, son processeur peut être acheté séparément et placé sur une carte personnalisée. C'est ce que compte faire Mr Coronado pour le futur du projet. | ||
[[Fichier:beaglebone.jpg | centre | Image du Beaglebone Black]] | [[Fichier:beaglebone.jpg | centre | Image du Beaglebone Black]] | ||
− | Un système d'exploitation est inclus de base dans la eMMC de la beaglebone. Il faudra | + | L'EEPROM choisie est la M25P80 de chez Micron, notamment parce qu'elle est adapté aux FPGA de la marque Xilinx. Le FPGA connaît les commandes de lecture de cette EEPROM. Sa taille est 1 Mo, et elle possède une interface SPI qui servira à communiquer avec la BBB. |
+ | |||
+ | '''Logiciel''' | ||
+ | |||
+ | Un système d'exploitation est inclus de base dans la eMMC de la beaglebone. Il faudra vérifier si cela suffit pour développer le programme, ou s'il faut installer un autre OS. | ||
− | Le langage choisi est le C. | + | Le langage choisi pour le programme est le C, principalement parce que c'est le langage que je maîtrise le mieux. Il est aussi tout à fait adapté à la programmation embarquée |
− | L' | + | L'interface web sera en HTML et PHP, là aussi parce que le PHP est le langage serveur que je connais le mieux. |
− | + | == Étapes de la première partie : Ecriture dans l'EEPROM == | |
* Prise en main de la Beaglebone black (OS, interface de développement, ...) | * Prise en main de la Beaglebone black (OS, interface de développement, ...) | ||
Ligne 37 : | Ligne 58 : | ||
* Lire les registres de l'EEPROM : Le début de l'EEPROM est constitué de registres contenant des informations diverses comme sa taille, sa date de fabrication ou son constructeur. Le but est de pouvoir lire ces registres depuis la beaglebone. | * Lire les registres de l'EEPROM : Le début de l'EEPROM est constitué de registres contenant des informations diverses comme sa taille, sa date de fabrication ou son constructeur. Le but est de pouvoir lire ces registres depuis la beaglebone. | ||
* Écrire dans l'EEPROM via SPI | * Écrire dans l'EEPROM via SPI | ||
+ | * Écrire un fichier dans l'EEPROM | ||
+ | * Lire les données écrites et vérifier leur intégrité | ||
+ | |||
+ | == Etapes de la seconde partie : Interface Web == | ||
+ | |||
+ | * Installation et configuration d'un serveur web sur le BBB | ||
+ | * Écriture de la page web en HTML | ||
+ | * Écriture de la page de traitement en PHP | ||
− | + | = Prise en main de la BBB = | |
− | + | == Liens hypertextes destinés à la prise en main == | |
* [http://www.angstrom-distribution.org/ Site internet de la distribution linux Angstrom] | * [http://www.angstrom-distribution.org/ Site internet de la distribution linux Angstrom] | ||
Ligne 47 : | Ligne 76 : | ||
* [http://beagleboard.org/latest-images Dernières versions de Angstrom pour BBB] | * [http://beagleboard.org/latest-images Dernières versions de Angstrom pour BBB] | ||
− | + | == Mise à jour de la distribution == | |
La BBB possède une mémoire interne : une eMMC de 2Go, ce qui est amplement suffisant pour le projet. D'office, une distribution linux spécialement créée pour la programmation embarquée est installée sur la eMMC : Angstrom distribution. | La BBB possède une mémoire interne : une eMMC de 2Go, ce qui est amplement suffisant pour le projet. D'office, une distribution linux spécialement créée pour la programmation embarquée est installée sur la eMMC : Angstrom distribution. | ||
Ligne 60 : | Ligne 89 : | ||
* Rester appuyé sur le bouton BOOT (le plus prêt de la carte SD) et alimenter la BBB. Le flashage devrait commencer. Cela peut durer jusqu'à 45 minutes. Une fois terminé, les LEDs à droite du port Ethernet restent allumées. Il suffit alors de débrancher la BBB puis de la rebrancher EN AYANT RETIRÉ LA CARTE SD ! Sinon le flashage recommence. | * Rester appuyé sur le bouton BOOT (le plus prêt de la carte SD) et alimenter la BBB. Le flashage devrait commencer. Cela peut durer jusqu'à 45 minutes. Une fois terminé, les LEDs à droite du port Ethernet restent allumées. Il suffit alors de débrancher la BBB puis de la rebrancher EN AYANT RETIRÉ LA CARTE SD ! Sinon le flashage recommence. | ||
− | + | == Accéder à la BBB== | |
Une interface réseau est simulé lorsqu'on branche la BBB par USB sur un ordinateur. Sous Ubuntu 13.10, aucun driver spécifique n'est nécessaire, l'interface est immédiatement reconnue. Une interface web est disponible avec une page de présentation à l'adresse 192.168.7.2 . L'IDE [https://c9.io/ cloud 9] en web-application est aussi préinstallé et disponible sur le port 3000. Malgré de riches fonctionnalités, cloud 9 ne semble pas convenir au développement en langage C : Pas de debugeur ni de compilateur disponible d'après le site internet. | Une interface réseau est simulé lorsqu'on branche la BBB par USB sur un ordinateur. Sous Ubuntu 13.10, aucun driver spécifique n'est nécessaire, l'interface est immédiatement reconnue. Une interface web est disponible avec une page de présentation à l'adresse 192.168.7.2 . L'IDE [https://c9.io/ cloud 9] en web-application est aussi préinstallé et disponible sur le port 3000. Malgré de riches fonctionnalités, cloud 9 ne semble pas convenir au développement en langage C : Pas de debugeur ni de compilateur disponible d'après le site internet. | ||
Ligne 68 : | Ligne 97 : | ||
Il est aussi possible de s'y connecter via minicom directement (9600 bauds, sans contrôle de flux sur /dev/ttyACM0) | Il est aussi possible de s'y connecter via minicom directement (9600 bauds, sans contrôle de flux sur /dev/ttyACM0) | ||
− | |||
− | |||
+ | =Réalisation de la carte de test= | ||
+ | |||
+ | L'EEPROM utilisé est une M25P80 de chez Micron. Il faut les empreintes de ces composants au format Altium pour créer le PCB. Elles sont disponibles sur le site Altium après création d'un compte. PCB créé, mais la carte ne peut pas être réalisée à l'école pour l'instant, car les machines permettant de créer les circuits sont hors-services. | ||
+ | |||
+ | En attendant, Mr Thierry Flamen possède des circuits pré-imprimé spécialement pour des petits composants CMS comme cette EEPROM. Les trous sont percés et le composant est soudé dessus. | ||
+ | |||
+ | [[Fichier:carte_test.jpg | centre | vignette | Carte de test]] | ||
+ | |||
+ | [[Fichier:montage.jpg | centre | vignette | Montage avec la Beaglebone Black ]] | ||
+ | |||
+ | = Première partie : Lecture et écriture de l'EEPROM = | ||
+ | |||
+ | ==Liens utiles== | ||
+ | * [http://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&sqi=2&ved=0CDoQFjAA&url=http%3A%2F%2Fwww.micron.com%2F~%2Fmedia%2FDocuments%2FProducts%2FData%2520Sheet%2FNOR%2520Flash%2FSerial%2520NOR%2FM25P%2FM25P80.pdf&ei=co8YU_6QEdSu7AaDoICgCQ&usg=AFQjCNEtGo583vxY52sXq8rMf9bREKpRTg&sig2=ddWnZ4caiiuh0_O2DUKhkg&bvm=bv.62577051,d.bGE&cad=rja Datasheet de la M25P80] | ||
*[https://www.linux.com/learn/tutorials/746860-how-to-access-chips-over-the-spi-on-beaglebone-black Tutoriel en anglais sur SPI, EEPROM et BBB] | *[https://www.linux.com/learn/tutorials/746860-how-to-access-chips-over-the-spi-on-beaglebone-black Tutoriel en anglais sur SPI, EEPROM et BBB] | ||
*[http://fr.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus Page wikipedia sur le SPI] | *[http://fr.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus Page wikipedia sur le SPI] | ||
Ligne 77 : | Ligne 118 : | ||
*[https://github.com/jadonk/validation-scripts/tree/master/test-capemgr Tutoriel sur les pins sous linux] | *[https://github.com/jadonk/validation-scripts/tree/master/test-capemgr Tutoriel sur les pins sous linux] | ||
− | == | + | ==Interface SPI de la BBB== |
Afin de pouvoir écrire et lire avec read() et write() en C directement, il faut activer le(s) périphérique(s) spidev*. Une série de commandes permet de les créer. Tout est expliqué [http://elinux.org/BeagleBone_Black_Enable_SPIDEV ici]. | Afin de pouvoir écrire et lire avec read() et write() en C directement, il faut activer le(s) périphérique(s) spidev*. Une série de commandes permet de les créer. Tout est expliqué [http://elinux.org/BeagleBone_Black_Enable_SPIDEV ici]. | ||
Ligne 86 : | Ligne 127 : | ||
19/02 : résolu, le fichier uDev.txt était mal modifié (toutes les commandes doivent être sur la même ligne). | 19/02 : résolu, le fichier uDev.txt était mal modifié (toutes les commandes doivent être sur la même ligne). | ||
− | == | + | == Communication avec l'EEPROM en C == |
− | L'EEPROM | + | Branchement de la mémoire avec des fils directement sur la beaglebone black. Les trous destinés à l'interface SPI sont disponibles [http://www.elinux.org/Beagleboard:Cape_Expansion_Headers ici]. |
+ | |||
+ | Le tutoriel trouvé sur internet fourni des exemples de programmes en C utilisant l'interface SPI : spidev_fdx.c et spidev.c. | ||
+ | |||
+ | tentative de lecture directement avec les fonctions fournies par spidev_fdx.c, mais rien n'est lu. D'après la datasheet, il faut envoyer des commandes avant de pouvoir lire. Par exemple, pour lire le nom du fabriquant il faut envoyer la commande READ DESCRIPTION dont le code de commande est 69h. | ||
+ | |||
+ | ''' 12/03 '''En s'inspirant des fonctions de spidev_fdx.c, écriture d'un programme de lecture de la description de l'EEPROM. Mais aucune valeur n'est reçue. Il faut vérifier les signaux SPI générés par la BBB, ainsi que les signaux envoyés par l'EEPROM grâce à un oscilloscope. | ||
+ | |||
+ | L'analyseur logique confirme que le programme fonctionne. Les trames correspondent au comportement voulu. Vérification des pistes de cuivres de la carte, recherche de court-circuit. Rien de concluant. Un ampèremètre est branché en série avec l'alimentation pour vérifier que l'EEPROM fonctionne et n'a pas été endommagée lors de la soudure des broches. Observation d'une augmentation de la consommation lors d'une tentative d'écriture. Cette consommation est supérieure à la consommation de repos de la mémoire (d'après la datasheet), mais inférieure à la consommation en lecture ou en écriture. Le problème vient donc du programme et non de la carte. | ||
+ | |||
+ | '''19/03''' : Finalement, après avoir lu en détail la datasheet, l'EEPROM était en DEEP DOWN STATE et n'acceptait aucune commande autre que celle de réveil. Après l'envoi de celle-ci, les autres commandes de lecture fonctionnent et renvoient bien des données . | ||
+ | |||
+ | La commande READ DESCRIPTION renvoie bien les données concernant le fabricant et la taille de la mémoire. Données vérifiées par la datasheet. | ||
+ | |||
+ | '''26/03''' : Écriture d'une fonction de lecture. Afin de lire des données, il faut envoyer la commande READ DATA puis une addresse sur 3 octets. Tant que l'EEPROM est sélectionnée (Chip select à 0), l'EEPROM renvoie les données contenues à partir de l'adresse transmise. Pour l'instant, l'EEPROM est vide et ne transmet que des 1, car les informations écrites sont des 0. Par exemple la commande BULK ERASE met tous les bits de l'EEPROM à 1. | ||
+ | |||
+ | '''30-31/03''' : J'écris différentes fonctions pour lire le registre de description, lire et écrire dans le registre d'état et lire et écrire dans la mémoire. La fonction d'écriture ne semblait ne pas fonctionner, puisque la lecture de la mémoire ne renvoyait que des 1. Or après analyse à l'analyseur logique, le problème venait de la fonction de lecture, qui envoyait mal la commande de lecture. Le programme envoyait l'octet de commande et les 3 octets d'adresse sous la forme d'un unsigned long. Lors du transfert SPI, le premier octet envoyé était le 3ème octet d'adresse, au lieu d'être la commande. La séparation en plusieurs unsigned char (1 octet) a résolu le problème. | ||
+ | |||
+ | '''Depuis le 31/03 et jusqu'au 14/04''' : Après avoir passé du temps sur l'interface web, je me rends compte que mes fonctions de lecture et d'écriture ne fonctionnent plus. Je passe du temps à analyser mes trames SPI à l'analyseur logique, sans trouver pourquoi je n'arrive pas à lire ce que j'écris. Je ne sais pas si c'est la lecture qui ne fonctionne pas, ou l'écriture, ce qui ne facilite pas la tâche. Après des heures de recherches, je me rends compte de plusieurs chose : Je n'ai pas bien saisi le fonctionnement d'une EEPROM. Comme son nom l'indique, c'est une READ-ONLY memory. C'est à dire qu'une fois écrite, elle ne peut être ré-écrite sans être effacée grâce à un courant électrique. Concrètement, la commande PAGE PROGRAMM, qui permet d'écrire, met les bits à 0, alors qu'un BULK ERASE, la commande d'effacement complet, remet tous les bits à 1. | ||
+ | |||
+ | Ainsi il est nécessaire d'effacer la mémoire avant d'écrire le moindre bit. Dans le cas contraire, écraser les données donne petit à petit une mémoire remplie de 0. C'est ce que j'obtenais au fur et à mesure de mes écritures successives. La deuxième incompréhension est le système d'adressage. J'ai confondu pages et secteur. Je pensais donc qu'il n'y avait que 16 pages de 256 octets chacune. En fait, il existe bien 16 secteurs de 256 pages chacuns, elles-même contenant 256 octets chacune. | ||
+ | |||
+ | Je me concentre donc sur la partie effacement de mémoire grâce à BULK ERASE, je vérifie que seul des 1 (0xFF) subsistent dans la mémoire. Ensuite j'écris dans la mémoire puis vérifie les données écrites avec des printf. Quand la commande BULK ERASE fonctionne, l'EEPROM positionne le bit 1 du registre de statut à 1, c'est le write in progress bit (WIP). On peut donc vérifier si la mémoire est prête à être écrite ou non. L'effacement complet de la mémoire peut durer jusqu'à 10 secondes (d'après la datasheet, en pratique cela dure environ 6 secondes). | ||
+ | |||
+ | Voilà l'ensemble des commandes utilisées, dans l'ordre chronologique, afin d'écrire dans la mémoire : | ||
+ | * WRITE ENABLE : activation du bit d'écriture, indispensable avant un BULK ERASE | ||
+ | * BULK ERASE : Effacement complet de la mémoire (positionnement de tous les bits à 1) | ||
+ | * READ STATUS REGISTER : Lecture en boucle du bit d'écriture en cours (WIP), afin d'attendre que la mémoire soit prête | ||
+ | * WRITE ENABLE : Avant l'écriture | ||
+ | * PAGE PROGRAM : Permet d'écrire dans une des pages de la mémoire (limité à 256 octets donc). | ||
+ | |||
+ | Le programme fonctionne parfaitement jusqu'à ce que je débranche par inadvertance le fil d'alimentation de la mémoire. Impossible de faire un nouveau BULK ERASE après ça, le WIP est très rapidement mis à 0 et l'effacement ne semble pas fait. Pourtant toutes les autres commandes marchent : READ DESCRIPTION, READ STATUS REGISTER, même la mise en veille fonctionne (DEEP POWER MODE). Ce doit être aussi la cause du non fonctionnement après les tests fructueux du 30 Mars. Je décide de vérifier l'alimentation. Même après avoir utilisé diverses alimentations externes (Adaptateur 12V avec pont diviseur pour obtenir du 3,3 V, puis alimentation par le 3,3 V de l'Arduino) et ajouté la capacité de découplage (100 nF comme précisé dans la documentation), rien ne permet de rétablir le comportement du 14/04 au matin. | ||
+ | |||
+ | Voici les trames récupérées à l'analyseur logique pour différentes commandes : | ||
+ | [[Fichier:Scope1_modif.png | centre | 600px ]] | ||
+ | [[Fichier:Scope2_modif.png | centre | 600px ]] | ||
+ | |||
+ | = Interface web (à partir du 7 Avril) = | ||
+ | |||
+ | L'interface web comporte, dans un premier temps, un formulaire d'upload pour le bitstream, qui redirige vers une page de traitement php exécutant le programme d’écriture en C, grâce à la fonction PHP exec(); | ||
+ | |||
+ | == Liens == | ||
+ | |||
+ | * [http://www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/11/20/beaglebone-web-server--setup Tutoriel très complet sur l'installation d'un serveur web sur BBB] | ||
+ | |||
+ | == Installation du serveur web Lighttpd et PHP == | ||
+ | |||
+ | '''07/04''' : Pour pouvoir installer le serveur, il faut d'abord connecter la BBB à internet, ce que je n'avais pas fait depuis le début du projet. 2 fichiers sont à modifier : | ||
− | + | /etc/network/interfaces : Fichier inexistant, il faut le créer pour configurer l'interface ethernet (eth0) en auto et activer DHCP. Le fichier contient donc après modification : | |
+ | auto eth0 | ||
+ | iface eth0 inet dhcp | ||
− | = | + | Le second fichier, /etc/resolv.conf, sert à spécifier les serveurs DNS qui permet de faire la conversion nom de domaine <=> adresse IP. J'utilise 8.8.8.8, le serveur DNS OpenDNS. |
− | + | Bien sûr, cette configuration est propre au mode de connexion de mon domicile (une simple box Free). La configuration serait différente pour se connecter au réseau de l'école. | |
− | |||
− | + | Après s'être assuré de la bonne connexion à internet (par un ping), je commence à mettre à jour la BBB avant d'installer le paquet, ce qui prend de longues minutes. | |
− | + | Le paquet à installer est lighttpd, un serveur web léger équivalent à Apache. Son module fast-CGI est ajouté, afin d'activer PHP. L'installation commence bien, jusqu'au lancement du service web, qui échoue. Le tutoriel précise la source du problème : un autre service utilise le port 80, en l'occurence l'IDE Cloud 9, qui est un environnement de développement sous le forme d'une interface web. Toute une série de services doivent être désactivés par la même occasion, comme par exemple Bonescript, qui est un langage basé sur Javascript permettant d'écrire des programmes pour la BBB. | |
− | + | Après un redémarrage du BBB, les services sont effectivement arrêtés et lighttpd est lancé. Il suffit ensuite d'installer PHP et PHP-CGI, ce dernier permettant d'éxecuter le programme directement via une fonction PHP. | |
− | + | '''14/04''' : Je m'attelle ensuite aux pages web. La structure de l'interface web est très simple : La page d'accueil contient un formulaire d'upload, qui renvoie sur une page de traitement où le serveur vérifie que le transfert de fichier s'est bien passé. Il exécute ensuite le programme en C en passant le fichier en argument, et affiche les éventuels messages d'erreurs. Afin de reconnaître le message d'erreur, je modifie le programme en C pour que chaque erreur commence par une ligne contenant la chaîne de caractère "erreur". La fonction exec() de PHP est très pratique : Elle permet d'éxecuter n'importe quel programme comme si on le lancait en ligne de commande, et il est même possible de récupérer la sortie standard via un tableau de caractère. La première case du tableau de résultat contient donc la chaine "erreur" si l'écriture dans l'EEPROM a mal fonctionné | |
− | + | La page de traitement exécute aussi le programme "cmp" qui permet de comparer deux fichiers. Il est utilisé sur le fichier image de la mémoire créé par le programme en C. | |
− | + | [[Fichier:Index_php.png | centre | 600px | Page d'accueil de l'interface ]] | |
+ | [[Fichier:Traitement_php.png | centre | 600px | Page de traitement après une écriture réussie ]] | ||
− | + | = Bilan = | |
− | + | L'écriture n'est pas fonctionnelle le 15/04 au soir, bien que l'algorithme soit complet et l'interface web finie. Il faudrait un peu plus de temps pour déterminer la source du problème d'alimentation (si c'est bien la cause du dysfonctionnement de l'effacement de la mémoire). | |
− | + | Il y a plusieurs axes d'amélioration : | |
+ | * Accéder à toutes les fonctions du programme avec des arguments (comme pour la fonction d'écriture) : Lecture de la description, du registre de statut, effacement de la mémoire, lecture avec passage de l'adresse en paramètre, etc. | ||
+ | * améliorer l'interface web avec gestion des bitstreams déjà uploadés | ||
+ | * Ajouter du CSS pour la rendre plus esthétique | ||
+ | * Sécuriser l'application web pour éviter l'upload de fichier non autorisé sur le serveur ou l'écriture de fichier pouvant compromettre le FPGA | ||
− | + | Archive contenant le programme d'écriture final en C ainsi que les deux pages web en PHP : [[Fichier:projet_malthieu.zip]] | |
− | + | Rapport : [[Fichier:Rapport_malthieu.pdf]] |
Version actuelle datée du 6 juin 2014 à 11:02
Sommaire
Wiki du projet de reconfiguration d'un FPGA.
Le wiki est classé par thème mais chronologique : La prise en main de la Beaglebone Black a commencé avant la carte de test, etc.
Cahier des charges
Projet réalisé par Simon Malthieu.
Tuteurs : Alexandre Boé, Thomas Vantroy, Mickaël Coronado.
Suite à la réunion avec Mickaël Coronado, gérant de Inodesign, le cahier des charges suivant a été établi :
Description du projet
Le but du projet est de permettre une mise à jour aisé d'un FPGA. Il y a deux manières de programmer un FPGA. Soit directement via une liaison J-TAG. Dans ce cas-ci, le FPGA doit être reprogrammé à chaque mise sous tension. Il existe cependant une autre solution, qui consiste à associer une mémoire de type EEPROM au FPGA. Ainsi, il suffit d'écrire le bitstream dans la mémoire, et le FPGA va lire l'EEPROM à chaque mise sous tension.
Les deux manières devront être développées. (obsolète au 02/04)
L'interface devra aussi pouvoir vérifier l'intégrité des données, afin d'éviter un chargement de bitstream corrompu.
L'autre partie du projet consiste à gérer la partie récupération du bitstream par FTP, ou mieux par SFTP. L'ensemble devra donc être autonome, de la récupération du bitstream à programmation du FPGA. (obsolète au 02/04)
EDIT 02/04 : Suite à une réunion avec Mickael Coronado à propos de l'avancement de projet, il a été décidé d'abandonner la transmission par J-TAG et de se concentrer sur une interface web permettant l'upload de bitstream et le contrôle du programme.
Objectifs du projet au 02/04
- Concevoir un programme, exécuté par un ordinateur embarqué de type Beaglebone Black, permettant d'écrire dans une EEPROM de type M25P80 un fichier bitstream de FPGA
- Le programme devra aussi pouvoir vérifier l'intégrité des données écrites dans la mémoire
- Développer une interface web permettant de contrôler le programme : Elle doit permettre de téléverser un fichier sur l'ordinateur et exécuter le programme d'écriture avec ce fichier
Spécifications techniques
Materiel
La plateforme choisie pour piloter l'EEPROM est la Beaglebone black. C'est un micro-ordinateur miniature embarquant un processeur Texas Instrument, modèle Sitara XAM3359AZCZ100 Cortex A8 ARM cadencé à 1 GHz. Une exemplaire de cette plateforme est prêté par Mickaël Coronado pour les besoins du projet. Cet ordinateur est adapté au prototypage car, contrairement au Raspberry Pi, son processeur peut être acheté séparément et placé sur une carte personnalisée. C'est ce que compte faire Mr Coronado pour le futur du projet.
L'EEPROM choisie est la M25P80 de chez Micron, notamment parce qu'elle est adapté aux FPGA de la marque Xilinx. Le FPGA connaît les commandes de lecture de cette EEPROM. Sa taille est 1 Mo, et elle possède une interface SPI qui servira à communiquer avec la BBB.
Logiciel
Un système d'exploitation est inclus de base dans la eMMC de la beaglebone. Il faudra vérifier si cela suffit pour développer le programme, ou s'il faut installer un autre OS.
Le langage choisi pour le programme est le C, principalement parce que c'est le langage que je maîtrise le mieux. Il est aussi tout à fait adapté à la programmation embarquée
L'interface web sera en HTML et PHP, là aussi parce que le PHP est le langage serveur que je connais le mieux.
Étapes de la première partie : Ecriture dans l'EEPROM
- Prise en main de la Beaglebone black (OS, interface de développement, ...)
- Conception d'une carte de test avec une EEPROM et une interface SPI pour tester le programme. La création de la carte est effectué par Inodesign grâce à un schéma qu'il faudra dessiner, à la main ou grâce à un logiciel comme Altium.
- Lire les registres de l'EEPROM : Le début de l'EEPROM est constitué de registres contenant des informations diverses comme sa taille, sa date de fabrication ou son constructeur. Le but est de pouvoir lire ces registres depuis la beaglebone.
- Écrire dans l'EEPROM via SPI
- Écrire un fichier dans l'EEPROM
- Lire les données écrites et vérifier leur intégrité
Etapes de la seconde partie : Interface Web
- Installation et configuration d'un serveur web sur le BBB
- Écriture de la page web en HTML
- Écriture de la page de traitement en PHP
Prise en main de la BBB
Liens hypertextes destinés à la prise en main
- Site internet de la distribution linux Angstrom
- Tutoriel de prise en main de la BBB (eng)
- Flashage d'une carte SD en ligne de commande
- Dernières versions de Angstrom pour BBB
Mise à jour de la distribution
La BBB possède une mémoire interne : une eMMC de 2Go, ce qui est amplement suffisant pour le projet. D'office, une distribution linux spécialement créée pour la programmation embarquée est installée sur la eMMC : Angstrom distribution. Afin d'avoir le dernier noyau et les dernières optimisations, une mise à jour est nécessaire.
Les étapes pour mettre à jour la BBB sont :
- Décompresser l'image téléchargé sur le site de la beagleboard
- Flasher une carte SD (> 4Go) avec l'image. Ligne de commande utilisée :
sudo dd bs=4M if=~/Documents/Projet/BBB-eMMC-flasher-2013.09.04.img of=/dev/sdc
bs indique le nombre d'octets maximum à transmettre en même temps.
- Débrancher la BBB et insérer la carte SD à l'interieur.
- Rester appuyé sur le bouton BOOT (le plus prêt de la carte SD) et alimenter la BBB. Le flashage devrait commencer. Cela peut durer jusqu'à 45 minutes. Une fois terminé, les LEDs à droite du port Ethernet restent allumées. Il suffit alors de débrancher la BBB puis de la rebrancher EN AYANT RETIRÉ LA CARTE SD ! Sinon le flashage recommence.
Accéder à la BBB
Une interface réseau est simulé lorsqu'on branche la BBB par USB sur un ordinateur. Sous Ubuntu 13.10, aucun driver spécifique n'est nécessaire, l'interface est immédiatement reconnue. Une interface web est disponible avec une page de présentation à l'adresse 192.168.7.2 . L'IDE cloud 9 en web-application est aussi préinstallé et disponible sur le port 3000. Malgré de riches fonctionnalités, cloud 9 ne semble pas convenir au développement en langage C : Pas de debugeur ni de compilateur disponible d'après le site internet.
La meilleure solution reste SSH. On y accède par la commande ssh root@beaglebone.local
. Aucun mot de passe par défaut. Gcc et Vim sont déjà installés.
Il est aussi possible de s'y connecter via minicom directement (9600 bauds, sans contrôle de flux sur /dev/ttyACM0)
Réalisation de la carte de test
L'EEPROM utilisé est une M25P80 de chez Micron. Il faut les empreintes de ces composants au format Altium pour créer le PCB. Elles sont disponibles sur le site Altium après création d'un compte. PCB créé, mais la carte ne peut pas être réalisée à l'école pour l'instant, car les machines permettant de créer les circuits sont hors-services.
En attendant, Mr Thierry Flamen possède des circuits pré-imprimé spécialement pour des petits composants CMS comme cette EEPROM. Les trous sont percés et le composant est soudé dessus.
Première partie : Lecture et écriture de l'EEPROM
Liens utiles
- Datasheet de la M25P80
- Tutoriel en anglais sur SPI, EEPROM et BBB
- Page wikipedia sur le SPI
- Doc du noyau sur SPI
- Tutoriel sur les pins sous linux
Interface SPI de la BBB
Afin de pouvoir écrire et lire avec read() et write() en C directement, il faut activer le(s) périphérique(s) spidev*. Une série de commandes permet de les créer. Tout est expliqué ici.
Plusieurs fichiers de test sont disponible sur internet : ici et là.
Problème du lundi 17/02 : spidev1.0 est effectivement créé, mais il disparaît à chaque redémarrage. 19/02 : résolu, le fichier uDev.txt était mal modifié (toutes les commandes doivent être sur la même ligne).
Communication avec l'EEPROM en C
Branchement de la mémoire avec des fils directement sur la beaglebone black. Les trous destinés à l'interface SPI sont disponibles ici.
Le tutoriel trouvé sur internet fourni des exemples de programmes en C utilisant l'interface SPI : spidev_fdx.c et spidev.c.
tentative de lecture directement avec les fonctions fournies par spidev_fdx.c, mais rien n'est lu. D'après la datasheet, il faut envoyer des commandes avant de pouvoir lire. Par exemple, pour lire le nom du fabriquant il faut envoyer la commande READ DESCRIPTION dont le code de commande est 69h.
12/03 En s'inspirant des fonctions de spidev_fdx.c, écriture d'un programme de lecture de la description de l'EEPROM. Mais aucune valeur n'est reçue. Il faut vérifier les signaux SPI générés par la BBB, ainsi que les signaux envoyés par l'EEPROM grâce à un oscilloscope.
L'analyseur logique confirme que le programme fonctionne. Les trames correspondent au comportement voulu. Vérification des pistes de cuivres de la carte, recherche de court-circuit. Rien de concluant. Un ampèremètre est branché en série avec l'alimentation pour vérifier que l'EEPROM fonctionne et n'a pas été endommagée lors de la soudure des broches. Observation d'une augmentation de la consommation lors d'une tentative d'écriture. Cette consommation est supérieure à la consommation de repos de la mémoire (d'après la datasheet), mais inférieure à la consommation en lecture ou en écriture. Le problème vient donc du programme et non de la carte.
19/03 : Finalement, après avoir lu en détail la datasheet, l'EEPROM était en DEEP DOWN STATE et n'acceptait aucune commande autre que celle de réveil. Après l'envoi de celle-ci, les autres commandes de lecture fonctionnent et renvoient bien des données .
La commande READ DESCRIPTION renvoie bien les données concernant le fabricant et la taille de la mémoire. Données vérifiées par la datasheet.
26/03 : Écriture d'une fonction de lecture. Afin de lire des données, il faut envoyer la commande READ DATA puis une addresse sur 3 octets. Tant que l'EEPROM est sélectionnée (Chip select à 0), l'EEPROM renvoie les données contenues à partir de l'adresse transmise. Pour l'instant, l'EEPROM est vide et ne transmet que des 1, car les informations écrites sont des 0. Par exemple la commande BULK ERASE met tous les bits de l'EEPROM à 1.
30-31/03 : J'écris différentes fonctions pour lire le registre de description, lire et écrire dans le registre d'état et lire et écrire dans la mémoire. La fonction d'écriture ne semblait ne pas fonctionner, puisque la lecture de la mémoire ne renvoyait que des 1. Or après analyse à l'analyseur logique, le problème venait de la fonction de lecture, qui envoyait mal la commande de lecture. Le programme envoyait l'octet de commande et les 3 octets d'adresse sous la forme d'un unsigned long. Lors du transfert SPI, le premier octet envoyé était le 3ème octet d'adresse, au lieu d'être la commande. La séparation en plusieurs unsigned char (1 octet) a résolu le problème.
Depuis le 31/03 et jusqu'au 14/04 : Après avoir passé du temps sur l'interface web, je me rends compte que mes fonctions de lecture et d'écriture ne fonctionnent plus. Je passe du temps à analyser mes trames SPI à l'analyseur logique, sans trouver pourquoi je n'arrive pas à lire ce que j'écris. Je ne sais pas si c'est la lecture qui ne fonctionne pas, ou l'écriture, ce qui ne facilite pas la tâche. Après des heures de recherches, je me rends compte de plusieurs chose : Je n'ai pas bien saisi le fonctionnement d'une EEPROM. Comme son nom l'indique, c'est une READ-ONLY memory. C'est à dire qu'une fois écrite, elle ne peut être ré-écrite sans être effacée grâce à un courant électrique. Concrètement, la commande PAGE PROGRAMM, qui permet d'écrire, met les bits à 0, alors qu'un BULK ERASE, la commande d'effacement complet, remet tous les bits à 1.
Ainsi il est nécessaire d'effacer la mémoire avant d'écrire le moindre bit. Dans le cas contraire, écraser les données donne petit à petit une mémoire remplie de 0. C'est ce que j'obtenais au fur et à mesure de mes écritures successives. La deuxième incompréhension est le système d'adressage. J'ai confondu pages et secteur. Je pensais donc qu'il n'y avait que 16 pages de 256 octets chacune. En fait, il existe bien 16 secteurs de 256 pages chacuns, elles-même contenant 256 octets chacune.
Je me concentre donc sur la partie effacement de mémoire grâce à BULK ERASE, je vérifie que seul des 1 (0xFF) subsistent dans la mémoire. Ensuite j'écris dans la mémoire puis vérifie les données écrites avec des printf. Quand la commande BULK ERASE fonctionne, l'EEPROM positionne le bit 1 du registre de statut à 1, c'est le write in progress bit (WIP). On peut donc vérifier si la mémoire est prête à être écrite ou non. L'effacement complet de la mémoire peut durer jusqu'à 10 secondes (d'après la datasheet, en pratique cela dure environ 6 secondes).
Voilà l'ensemble des commandes utilisées, dans l'ordre chronologique, afin d'écrire dans la mémoire :
* WRITE ENABLE : activation du bit d'écriture, indispensable avant un BULK ERASE * BULK ERASE : Effacement complet de la mémoire (positionnement de tous les bits à 1) * READ STATUS REGISTER : Lecture en boucle du bit d'écriture en cours (WIP), afin d'attendre que la mémoire soit prête * WRITE ENABLE : Avant l'écriture * PAGE PROGRAM : Permet d'écrire dans une des pages de la mémoire (limité à 256 octets donc).
Le programme fonctionne parfaitement jusqu'à ce que je débranche par inadvertance le fil d'alimentation de la mémoire. Impossible de faire un nouveau BULK ERASE après ça, le WIP est très rapidement mis à 0 et l'effacement ne semble pas fait. Pourtant toutes les autres commandes marchent : READ DESCRIPTION, READ STATUS REGISTER, même la mise en veille fonctionne (DEEP POWER MODE). Ce doit être aussi la cause du non fonctionnement après les tests fructueux du 30 Mars. Je décide de vérifier l'alimentation. Même après avoir utilisé diverses alimentations externes (Adaptateur 12V avec pont diviseur pour obtenir du 3,3 V, puis alimentation par le 3,3 V de l'Arduino) et ajouté la capacité de découplage (100 nF comme précisé dans la documentation), rien ne permet de rétablir le comportement du 14/04 au matin.
Voici les trames récupérées à l'analyseur logique pour différentes commandes :
Interface web (à partir du 7 Avril)
L'interface web comporte, dans un premier temps, un formulaire d'upload pour le bitstream, qui redirige vers une page de traitement php exécutant le programme d’écriture en C, grâce à la fonction PHP exec();
Liens
Installation du serveur web Lighttpd et PHP
07/04 : Pour pouvoir installer le serveur, il faut d'abord connecter la BBB à internet, ce que je n'avais pas fait depuis le début du projet. 2 fichiers sont à modifier :
/etc/network/interfaces : Fichier inexistant, il faut le créer pour configurer l'interface ethernet (eth0) en auto et activer DHCP. Le fichier contient donc après modification : auto eth0 iface eth0 inet dhcp
Le second fichier, /etc/resolv.conf, sert à spécifier les serveurs DNS qui permet de faire la conversion nom de domaine <=> adresse IP. J'utilise 8.8.8.8, le serveur DNS OpenDNS.
Bien sûr, cette configuration est propre au mode de connexion de mon domicile (une simple box Free). La configuration serait différente pour se connecter au réseau de l'école.
Après s'être assuré de la bonne connexion à internet (par un ping), je commence à mettre à jour la BBB avant d'installer le paquet, ce qui prend de longues minutes.
Le paquet à installer est lighttpd, un serveur web léger équivalent à Apache. Son module fast-CGI est ajouté, afin d'activer PHP. L'installation commence bien, jusqu'au lancement du service web, qui échoue. Le tutoriel précise la source du problème : un autre service utilise le port 80, en l'occurence l'IDE Cloud 9, qui est un environnement de développement sous le forme d'une interface web. Toute une série de services doivent être désactivés par la même occasion, comme par exemple Bonescript, qui est un langage basé sur Javascript permettant d'écrire des programmes pour la BBB.
Après un redémarrage du BBB, les services sont effectivement arrêtés et lighttpd est lancé. Il suffit ensuite d'installer PHP et PHP-CGI, ce dernier permettant d'éxecuter le programme directement via une fonction PHP.
14/04 : Je m'attelle ensuite aux pages web. La structure de l'interface web est très simple : La page d'accueil contient un formulaire d'upload, qui renvoie sur une page de traitement où le serveur vérifie que le transfert de fichier s'est bien passé. Il exécute ensuite le programme en C en passant le fichier en argument, et affiche les éventuels messages d'erreurs. Afin de reconnaître le message d'erreur, je modifie le programme en C pour que chaque erreur commence par une ligne contenant la chaîne de caractère "erreur". La fonction exec() de PHP est très pratique : Elle permet d'éxecuter n'importe quel programme comme si on le lancait en ligne de commande, et il est même possible de récupérer la sortie standard via un tableau de caractère. La première case du tableau de résultat contient donc la chaine "erreur" si l'écriture dans l'EEPROM a mal fonctionné
La page de traitement exécute aussi le programme "cmp" qui permet de comparer deux fichiers. Il est utilisé sur le fichier image de la mémoire créé par le programme en C.
Bilan
L'écriture n'est pas fonctionnelle le 15/04 au soir, bien que l'algorithme soit complet et l'interface web finie. Il faudrait un peu plus de temps pour déterminer la source du problème d'alimentation (si c'est bien la cause du dysfonctionnement de l'effacement de la mémoire).
Il y a plusieurs axes d'amélioration :
- Accéder à toutes les fonctions du programme avec des arguments (comme pour la fonction d'écriture) : Lecture de la description, du registre de statut, effacement de la mémoire, lecture avec passage de l'adresse en paramètre, etc.
- améliorer l'interface web avec gestion des bitstreams déjà uploadés
- Ajouter du CSS pour la rendre plus esthétique
- Sécuriser l'application web pour éviter l'upload de fichier non autorisé sur le serveur ou l'écriture de fichier pouvant compromettre le FPGA
Archive contenant le programme d'écriture final en C ainsi que les deux pages web en PHP : Fichier:Projet malthieu.zip Rapport : Fichier:Rapport malthieu.pdf