Reconfiguration d'un FPGA

De Wiki de Projets IMA


Vidéo HD


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.

Image du Beaglebone Black

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

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.

Carte de test
Montage avec la Beaglebone Black

Première partie : Lecture et écriture de l'EEPROM

Liens utiles

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 .

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 :

Scope1 modif.png
Scope2 modif.png

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.

Page d'accueil de l'interface
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