Nous Ă©crivons le chargeur FPGA dans LabVIEW. 2e partie

Téléchargez la configuration sur FPGA via USB ou démontez FTDI MPSSE
Nous Ă©crivons le chargeur FPGA dans LabVIEW. Partie 1




Dans le premier article, nous avons testé l'algorithme de chargement sur le bon vieux C, dans le deuxième article, nous avons compris comment organiser un programme dans LabVIEW et implémenter une interface utilisateur simple. Cette fois, nous nous familiariserons avec les nouvelles méthodes de travail dans LabVIEW, analyserons les caractéristiques de la gestion des erreurs et terminerons le projet: nous implémentons le protocole de chargement du fichier de configuration dans le FPGA.

Gestion des erreurs


Ouvrez le code source, analysez la fonction MPSSE_open. Malgré la simplicité algorithmique (les fonctions sont appelées les unes après les autres), de nombreux éléments de l'API D2XX doivent être importés: FT_ResetDevice , FT_Purge , FT_SetUSBParameters , FT_SetChars , FT_SetTimeouts , FT_SetLatencyTimer , FT_SetFlowControl , FT_SetBitMode Comme indiqué dans l' article précédent , l'importation de fonctions est effectuée à l'aide du nœud Call library Function . Ce nœud possède des terminaux dédiés pour le contrôle des erreurs. LabVIEW a une règle simple: tous les VIs doivent suivre les erreurs et signaler les erreurs renvoyées par les terminaux d'erreur. La plupart des VIs intégrés la suivent strictement. J'espère que tout le monde comprend à quel point il est important de contrôler et de gérer les erreurs, en particulier au stade du débogage, mais il y a une autre raison pour laquelle c'est si important qui n'est pas évident pour les programmeurs "classiques". LabVIEW n'a pas de séquence stricte de périphériques dans le diagramme: le périphérique est exécuté lorsque les données sont prêtes à ses entrées. Si les données de la sortie d'un VI sont transférées vers l'entrée d'un autre VI, alors il est clair qu'au début le premier VI fonctionnera, seulement après le second. Mais que faire s'il n'y a pas de transfert de données et que les VIs effectuent des actions indépendantes? Bien sûr, vous pouvez utiliser la lourde "Flat Sequence Structure", mais il est beaucoup plus pratique de connecter les appareils les uns aux autres par un flux d'erreurs.


Lors de l'importation de fonctions D2XX, nous rencontrons deux types d'erreurs. Le premier - il s'agit d'une erreur d'importation directe - renvoie le bloc Call library Function lui-même. La seconde est une erreur de la bibliothèque elle-même; elle est renvoyée par presque toutes les fonctions via FT_STATUS . Toutes les valeurs possibles sont décrites comme enum dans le fichier d'en-tête ftd2xx.h. Bien qu'il soit suffisant de savoir que la valeur FT_OK est l'absence d'erreur et que toutes les autres valeurs sont des codes d'erreur, je voudrais suivre non seulement le fait de l'erreur elle-même, mais aussi quelle erreur s'est produite et où exactement elle s'est produite.


Dans LabVIEW, les données d'erreur sont propagées via error clusters d' error . Il s'agit d'un type de données dédié spécial; LabVIEW possède de nombreux VIs et fonctions pour travailler avec. Le cluster d'erreur se compose de trois éléments: une variable logique - affiche l'état, un nombre entier signé - un code d'erreur, une chaîne - la source de l'erreur. L'état indique si une erreur s'est produite, le code d'erreur détermine son type et est utilisé par des VIs spéciaux pour générer un rapport. La ligne donne une idée plus détaillée de l'endroit exact où l'erreur s'est produite. LabVIEW a accepté que si le statut est TRUE , alors c'est une erreur, si le statut est FALSE , mais le code n'est pas nul et la ligne de description n'est pas vide, alors c'est un avertissement , si le statut est FALSE , le code est nul et la ligne est vide - il n'y a pas d'erreur.




LabVIEW contient une base de données interne dans laquelle chaque code d'erreur est associé à sa description. Pour chaque type d'erreur, une plage spéciale de valeurs de code est allouée. Par exemple, pour les erreurs liées au fonctionnement du réseau, plusieurs plages sont allouées: de –2147467263 à –1967390460, de 61 à 65, de 116 à 118 et 122, 1101, 1114, 1115, 1132 à 1134, de 1139 à 1143 et de 1178 à 1185 Pour les erreurs définies par l'utilisateur, deux plages sont réservées de –8999 à –8000 et de 5000 à 9999. À partir de ces plages, nous pouvons choisir des valeurs pour les codes d'erreur de la bibliothèque D2XX.


Créons un VI qui reçoit le statut de la fonction D2XX en entrée et convertit ce statut en un cluster d'erreur LabVIEW. La plupart des fonctions et VIs de LabVIEW, ayant reçu le statut TRUE à l'entrée Error In , n'exécutent pas leur code, mais transmettent les informations d' Error Out terminal Error Out . Cela vous permet de transférer efficacement des informations sur la source tout au long de la chaîne vers le gestionnaire d'erreurs, éliminant ainsi l'exécution de code en mode d'urgence. Il est souhaitable que nos VIs se comportent de la même manière.


Organisons la liste des statuts D2XX sous forme d' enum et plaçons-la dans un type distinct (dans l'article précédent, nous l'avons fait avec les types FTDI).


énumération FT_Status

Nous enregistrons le nouveau VI sous le nom FT_error.vi. Nous ajoutons deux clusters Error In et Error Out panneau avant, vous pouvez les trouver dans le panneau "Array, Matrix & Cluster". Nous les connectons aux bornes du panneau de connexion dans les coins inférieur gauche et inférieur droit, respectivement, comme déjà mentionné dans l'article précédent, c'est l'emplacement des bornes de flux d'erreur adoptées par LabVIEW. Nous ajoutons la structure Case au diagramme, donnons le cluster Error In à l'entrée du Case selector , après quoi la structure Case change de couleur et divise deux sous-diagrammes: "No Error" - couleur verte et "Error" - couleur rouge. À l'intérieur du cas d'erreur, nous transférons le cluster d'erreurs du terminal de sélection directement au tunnel de sortie sur la bordure droite. Et dans le cas vert, nous ajoutons un autre Case , selon le statut, il déterminera s'il faut créer une erreur (le statut n'est pas égal à FT_OK), ou le laisser tel quel: ignorer le cluster d'erreur d'entrée pour quitter sans changer.


Afin de convertir techniquement le code d'erreur en cluster, vous pouvez utiliser le VI VI Error Cluster From Error Code VI . Ce sous- VI ajoute une chaîne d'appels à la description de l'erreur, afin que nous puissions déterminer non seulement ce qui s'est produit, mais aussi où cela s'est produit.


Pour sélectionner le texte correspondant à l'état d'entrée (FT_Status), utilisez le bloc de propriétés: sélectionnez "RingText.Text". Le texte d'erreur est envoyé à l'entrée du error message d' Error Cluster From Error Code VI .
N'oubliez pas de dessiner une icĂ´ne "parlante".


FT_error.vi


Tableau de bord avant (avant)



Schéma fonctionnel. Erreur d'entrée



Schéma fonctionnel. Il n'y a pas d'erreur à l'entrée et l'état est FT_OK



Schéma fonctionnel. Il n'y a pas d'erreur à l'entrée, mais l'état est différent de FT_OK



Pour tester FT_error, vous pouvez créer un VI vide, y ajouter le VI créé et voir comment la valeur changera au démarrage si différents statuts sont appliqués.


Test FT_error.vi


Panneau avant (avant) de l'appareil



Schéma fonctionnel


Maintenant, après tout appel de fonction de l'API D2XX, nous utiliserons SubVI FT_error.vi. Un groupe d'erreurs passera par tous les VIs de la hiérarchie des appels.


Dans les VIs de niveau supérieur, nous devons décider quoi faire avec l'erreur détectée: vous pouvez afficher un message dans la boîte de dialogue, l'écrire dans le fichier de rapport, l'ignorer ou simplement mettre fin à l'application «en silence». La boîte de dialogue est le moyen le plus simple et le plus populaire de signaler des erreurs. C'est également pratique pour un programmeur débutant, car il n'y a rien à faire. Dans chaque VI, le mode de gestion automatique des erreurs est activé par défaut ( Activer la gestion automatique des erreurs , situé dans la catégorie Exécution du menu Propriétés du VI). Cela fonctionne comme ceci: si dans un nœud, le terminal de sortie Error Out n'est connecté nulle part et qu'une erreur se produit dans ce nœud, LabVIEW met en pause l'application et affiche une boîte de dialogue. Si la borne de Error Out du nœud est connectée, le flux d'erreur se propage comme programmé et aucune action supplémentaire ne se produit. Cependant, la fenêtre de message peut être appelée par programme, pour cela, vous devez utiliser les VIs General Error Handler et Simple Error Handler (situés dans le panneau Dialog & User Interface). Dans ce cas, nous pouvons utiliser les informations d'erreur pour terminer le programme. Dans un diagramme, cela ressemble à ceci:



Image cliquable


Lorsqu'une erreur se produit, le programme sera suspendu, une fenêtre de rapport apparaîtra, après avoir fermé la fenêtre, le programme se fermera correctement.


FenĂŞtre de rapport


Ouvrir et fermer FTDI


Revenons donc à la fonction MPSSE_open . Créez un nouveau VI . Tout d'abord, ajoutez les terminaux pour le flux d'erreur. Ajoutez une structure de sélection et sélectionnez Entrée d' Error In dans le sélecteur. Dans le cas vert, nous importons les fonctions dans l'ordre et avec les paramètres comme dans le prototype Sishny. Tous les nœuds du nœud de Call Library Function Node connectés en chaîne par un flux d'erreur. Dans le cas rouge à travers le tunnel, nous connectons Error In avec la borne de sortie de l'erreur.



Image cliquable



VI MPSSE_open.vi


Une ligne avec la description de FTDI ( Description ) est fournie à l'entrée de SubVI, à la sortie se trouve Handle et une puce FTDI initialisée en mode MPSSE.


Créons un VP qui finit de travailler avec FTDI et vous pouvez déjà vérifier les performances sur le matériel.


FT_Close.vi


Schéma fonctionnel



Face avant


Dans l'article précédent, pour le débogage de l'interface, nous avons créé le stub VI SP_FT_MPSSE_FPGA.vi, il est maintenant temps de le remplir. Ajoutez MPSSE_open.vi et FT_Close.vi à son diagramme. À ce stade, il est assez difficile d'évaluer si l'initialisation était correcte, cependant, une valeur Handle non nulle à la sortie de MPSSE_open.vi et l'absence d'erreur nous en dira beaucoup.



Organigramme SP_FT_MPSSE_FPGA.vi


Pour voir la valeur de Handle vous pouvez utiliser la "fenêtre de surveillance de sonde". Il s'agit d'un outil de débogage pratique qui vous permet d'afficher la valeur des données sur n'importe quel (presque n'importe quel) fil pendant l'exécution de l'appareil. Afin de placer l'échantillon sur la ligne, vous devez sélectionner "Sonde" dans le menu contextuel de cette ligne. La fenêtre "Probe Watch Window" s'ouvre et un numéro avec le numéro d'échantillon apparaît sur la ligne. Dans l'image ci-dessus, c'est "3".


FenĂŞtre de surveillance de sonde


Sur la ligne Handle, la valeur 698389336


Super! Nous démarrons les VIs de niveau supérieur, connectons la carte de débogage à l'ordinateur. Une description de la puce FTDI connectée apparaît dans la liste "Sélectionner un appareil", cliquez sur le bouton "Programmer" et ... rien ne se passe. La valeur Handle n'est apparue que dans la fenêtre "Probe Watch". Et c'est bien.


Nous éteignons la carte, la liste des appareils est effacée. Cliquez sur "Programme". C'est là que la fenêtre de rapport d'erreur apparaît.


FenĂŞtre de rapport


Après avoir cliqué sur le bouton "Continuer", le VI termine son travail.


Il est interdit d'appuyer sur le bouton si aucun appareil n'est trouvé. Nous modifions le gestionnaire d'événements "Timeout". Permettez-moi de vous rappeler que les puces FTDI connectées à un PC sont analysées deux fois par seconde, si elles sont détectées et peuvent être utilisées pour programmer des FPGA, leurs descripteurs sont ajoutés à la Devices list via la propriété Strings[] . Nous créons la propriété Disabled pour "Programming", et si aucun périphérique approprié n'est trouvé, puis éteignez et assombrissez le bouton.


DĂ©lai d'expiration du cas


Image cliquable


Maîtriser GPIO


Une fois MPSSE activé, son utilisation s'effectue via le soi-disant "code d'opération", et seuls FT_Write , FT_Read et FT_Queue sont utilisés à partir des fonctions API FT_Write (pour connaître l'état de la mémoire tampon du récepteur). Nous créons le VI correspondant le long de la piste que nous avons créée: FT_Write.vi, FT_Read.vi, FT_Queue.vi.


Un peu de routine


FT_Write.vi



Schéma fonctionnel. FT_Write.vi



FT_Read.vi



Schéma fonctionnel. FT_Read.vi



FT_Queue.vi



Schéma fonctionnel. FT_Queue.vi


À partir de ces trois briques, nous présentons les VIs pour lire le port parallèle et y écrire. La valeur est commodément représentée sous la forme d'un tableau de variables booléennes.


MPSSE_Set_LByte.vi et MPSSE_Get_LByte.vi


MPSSE_Set_LByte.vi



Schéma fonctionnel. MPSSE_Set_LByte.vi



MPSSE_Get_LByte.vi



Schéma fonctionnel. MPSSE_Get_LByte.vi


J'avoue que j'étais paresseux pour créer une liste nommée pour tous les op-codes, alors je les ai laissés sous la forme de numéros magiques.


Comme indiqué dans le tout premier article , le protocole d'amorçage FPGA série passif n'est rien de plus qu'un SPI avec une manipulation de drapeau supplémentaire. Cinq branches au total sont utilisées: les lignes DCLK , DATA [0] , nCONFIG doivent être configurées comme sorties, les lignes nSTATUS , CONF_DONE comme entrées.


Brochage de la disposition du tableau
Broche FPGANom de brochePinMPSSEDirectiondéfaut
DCLKBDBUS038TCK / SKOut0
DONNÉES [0]BDBUS139TDI / DOOut1
nCONFIGBDBUS240TDO / DIOut1
nSTATUSBDBUS341TMS / CSDans1
CONF_DONEBDBUS443GPIOL0Dans1

Nous avons besoin d'un VP qui peut changer la valeur de la jambe sélectionnée sans affecter toutes les autres. Tout d'abord, créez Enum avec les numéros de série des jambes dans le port, enregistrez-le sous "Strict Type Def" dans le fichier SP_LBYTE_BITS.ctl. Nous créons un nouveau VI, ajoutons les terminaux de flux d'erreurs familiers. Nous lisons la valeur actuelle du port parallèle à l'aide de MPSSE_Get_LByte.vi, utilisons la fonction Replace Array Subset pour modifier le bit souhaité et réécrivons la valeur sur le port (MPSSE_Set_LByte.vi).


SP_Set_Flag.vi


SP_Set_Flag.vi



Schéma fonctionnel. SP_Set_Flag.vi



Enum SP_LBYTE_BITS.ctl


Pour commencer la configuration, le MPSSE doit générer une transition basse à haute sur la ligne nCONFIG . Dès que le FPGA est prêt à recevoir des données, il formera un niveau élevé sur la ligne nSTATUS . A ce stade, tout est prêt pour l'expérience en fer. Sur le schéma fonctionnel SP_FT_MPSSE_FPGA.v nous ajoutons la ligne de contrôle nCONFIG - après l'initialisation du MPSSE nous donnons un niveau bas, puis haut. Après chaque opération (pour le débogage), nous lisons l'état des jambes de port.


SP_FT_MPSSE_FPGA.vi


Au démarrage



Schéma fonctionnel


En général, lors du lancement du VI, il est clair que le FPGA répond à la transition sur la ligne nCONFIG - zéro est défini sur la branche nSTATUS , puis un. Mais il ne sera pas superflu de surveiller cela avec un oscilloscope. Presque tout oscilloscope à deux canaux avec déclenchement par déclenchement (veille) convient. Canal A (piste bleue) Je mets dans le point de contrôle du circuit nCONFIG , canal B (piste rouge) - chaîne nSTATUS . Le déclencheur est réglé sur le front descendant du canal A.



L'image est cliquable. Avec les détails!


Travailler avec un fichier


FPGA est prêt à accepter le fichier de configuration. Sommes-nous prêts à transférer le fichier sur le FPGA?


LabVIEW contient un ensemble complet d'outils pour travailler avec des fichiers. Je ne peux pas dire que la fonctionnalité est suffisante pour absolument toute la gamme des tâches, cependant, les opérations de base telles que la lecture et l' écriture sont effectuées facilement et agréablement. Le jeu de base de VIs pour travailler avec des fichiers se trouve dans le panneau "File I / O". Pour résoudre le problème, vous devez ouvrir le fichier de configuration, évaluer sa taille (nous devons savoir combien d'octets envoyer le FPGA), le lire et le fermer. Tout est simple et l'un après l'autre. Nous utilisons les refnum Open/Create/Replace File , Get File Size , Read from Binary File , Close File , les combiner avec la chaîne de flux d'erreurs et refnum - un numéro, tel qu'un descripteur de fichier, est créé lorsque le fichier est ouvert et doit être transféré à l'entrée d'autres VIs travaillant avec ce fichier.


Jusqu'à présent, nous n'avons nulle part où disposer des données lues, mais si vous voulez vraiment vérifier l'opérabilité de la chaîne, vous pouvez créer un indicateur de type String et le configurer un peu. Dans le menu contextuel, activez l'option "Affichage hexadécimal", activez la barre de défilement verticale (Éléments visibles -> Barre de défilement verticale) et après le lancement, nous observons le contenu du fichier de configuration binaire.


SP_FT_MPSSE_FPGA.vi


Face avant Nous regardons le contenu du fichier



Schéma fonctionnel. Karinka cliquable


Deux lignes de code parallèles indépendantes formées sur le diagramme du VI, par conséquent, des chaînes d'erreur distinctes sont utilisées pour elles. Afin de réduire les flux parallèles dans un terminal Error Out , la fonction Merge Errors est utilisée. Cette fonction recherche les erreurs d'entrée de haut en bas (oui, il peut y avoir plus de deux terminaux d'entrée, elle est étirée par la souris) et retourne le premier qu'elle trouve. S'il n'y a pas d'erreur, il renvoie le premier message d'avertissement. S'il n'y a pas d'avertissement, il n'y a pas d'erreur sur la sortie. Il est important de noter que l'ordre de connexion des entrées Merge Errors détermine la priorité des erreurs, et si une erreur se produit dans deux chaînes à la fois, l'erreur inférieure sera ignorée. Cela doit être traité avec soin.


Si nous essayons d'appuyer sur le bouton "Programme" dans le VI de niveau supérieur sans sélectionner de fichier, l'entrée SP_FT_MPSSE_FPGA.vi recevra un chemin vide, ce qui provoquera l'erreur "Erreur 1430. LabVIEW: (Hex 0x596) Le chemin est vide ou relatif. Vous devez utiliser un chemin absolu. " Comme le dit mon ami d'enfance: "Bagatelles, c'est quelque chose de mondain!" Et cette erreur n'est pas du tout une erreur, mais l'inattention de l'utilisateur. Nous n'arrêterons pas le programme et ne le jurerons qu'avec une fenêtre avec une croix rouge, nous supprimons simplement l'erreur avec ce code du flux et dans la boîte de dialogue, nous recommandons à l'utilisateur de décider du fichier. Pour filtrer l'erreur, utilisez le VI "Effacer les erreurs" de la palette "Boîte de dialogue et interface utilisateur". Pour afficher le message - "Boîte de dialogue à un bouton".



Schéma fonctionnel


Image cliquable


Télécharger la configuration


Pour le transfert de données série, le processeur MPSSE doit envoyer l'op-code 0x18, les arguments de commande seront la longueur de la séquence transmise (deux octets, en commençant par le plus bas), et la séquence de données elle-même. La longueur est codée moins un. Envoyons le bloc de données en tant que VI MPSSE_send.


MPSSE_Send.vi


MPSSE_Send.vi



Schéma fonctionnel


La taille du tampon d'entrée ( Array Size ) est convertie en un type à double octet U16 , nous soustrayons un, échangeons les octets bas et hauts ( Swap Bytes ) - vous devez envoyer la longueur en commençant par la plus basse et convertir le nombre à deux octets en un tableau à un octet ( Type Cast ).


La fonction Type Cast mérite une attention particulière. Il s'agit d'un tel convertisseur de type universel, dont l'ingéniosité est parfois très surprenante. Bref, alors:



Visuellement pour le programmeur


Cependant, il ne s'agit pas simplement de convertir des données dans un type différent, c'est également une interprétation heuristique. Cette fonction vous permet d'effectuer une conversion entre des types de données incompatibles, tandis que la fonction n'hésite pas à aligner les données d'entrée et même à supprimer les parties "supplémentaires". Si le type de données demandé nécessite plus de mémoire que les données d'entrée, la fonction allouera la quantité manquante. Pour un développeur novice, LabVIEW Type Cast peut devenir une bouée de sauvetage, mais en grandissant, il vaut mieux refuser un tel convertisseur - il est très caché aux yeux et peut devenir une source d'erreurs inattendues. Il est préférable d'utiliser des méthodes de conversion plus explicites, telles que Coerce To Type .


Lors de l'initialisation du processeur MPSSE, nous avons défini la taille maximale autorisée du tampon pour le transfert de données à 65536 octets, nous devons donc diviser le fichier de configuration en fragments dont la taille ne dépasse pas la taille spécifiée. Nous utiliserons la fonction Array Subset , cette fonction sélectionne un sous-tableau dans le tableau en commençant par l'élément d' index et une longue length . Nous allons le casser dans une boucle While , nous augmenterons chaque itération de l'index de 65536, entre les itérations nous passerons la valeur à travers le registre à décalage. Dès qu'il n'est pas possible de pincer 65536 octets du tableau principal, nous prenons tout ce qui reste, l'envoyons et arrêtons le cycle.


Selon le protocole de téléchargement, une fois toutes les données transférées, deux impulsions d'horloge supplémentaires doivent être appliquées pour démarrer l'initialisation du FPGA. Pour ce faire, après la boucle, nous envoyons un autre octet "vide".


SP_FT_MPSSE_FPGA.vi


Image cliquable


Afin de comprendre le succès du firmware, nous considérons les drapeaux, et si CONF_DONE est défini sur un, nous signalons au VI de niveau supérieur que tout est OK.


Le programme est terminé. Il reste à s'assurer que le FPGA clignote correctement et que la carte clignote joyeusement avec des LED.


Ă€ propos de VP Naming


, , LabVIEW, , SubVI. . :


  • — , FTDI, API D2XX. "FT", FT_Close.vi FT_Read.vi.
  • — MPSSE. "MPSSE". : MPSSE_open.vi, MPSSE_Set_LByte.vi, MPSSE_Get_LByte.vi.
  • — "Passive Serial" MPSSE. "S". , SP_FT_MPSSE_FPGA.vi ( , ) SP_LBYTE_BITS.ctl.
  • . . , .

( ), . subVI .


Conclusion


, , .



, LabVIEW, . , , , ( ). .


Matériel connexe


  1. . LabVIEW: . Per. de l'anglais . .– .:
    , 2008 – 400 .: .
  2. labview_mpsse . .
  3. .
  4. Software Application Development D2XX Programmer's Guide . API D2XX.

Source: https://habr.com/ru/post/fr429448/


All Articles