Asservissement-Positionnement

SOFT


Présentation
DSP TMS320VC31
Carte d'évaluation TI DSP Starter Kit
Carte d'Extension - Asservissement Positionnement
Soft

Usine à gaz - Utilisation
Usine à gaz - Historique


Introduction

Le seul mot qui convient pour caractériser le soft gérant cette carte, aussi bien côté PC, que côté DSP est : usine à gaz ....
Loin de tout développement dans les règles de l'art, il a évolué et n'a cessé de changer et de s'engraisser ...

Documentations

Documentation compilateur : Optimizing C Compiler User Guide.pdf

Code sur la carte Starter Kit seule

La carte StarterKit utilisée seule permet de faire tourner du code sur le DSP. Il y'a un certain nombre de cas, où il est utile de refaire marcher la carte Starter Kit seule.
En ayant uniquement cette carte StarterKit :

  • Le programme est en mémoire interne du DSP (donc pas d'aléas dûs à la mémoire externe)
  • Les interruptions sont gérées par la carte, donc pas de risque de ce côté là au démarrage.
  • Le PCB de la carte DSK est plus fiable que celui de la carte d'extension.

Côté hard :

  • Alimenter la carte (un connecteur a été rajouté sur le côté, l'alim est régulée par la suite sur la carte. Y mettre quelquechose entre 7 et 15V environ ...
  • S'assurer qu'il est possible de charger du code dedans cf : modif
  • Relier la carte au port parallèle d'un PC par un cable droit.

Code sur l'ensemble

Ici, on est soumis à tous les aléas possibles de l'assemblage.

Côté hard :

  • Verifier l'assemblage du sandwich. Certaines pattes des connecteurs d'extension (entre la carte StarterKit et l'extension), peuvent faire mauvais contact
  • Alimenter la carte par le connecteur sur le dessus (tension d'alim 7 à 8V), la carte consomme 500 à 600 mA
  • S'assurer qu'il est possible de charger du code dedans cf : modif
  • Vérifier que la carte n'est pas en mode autonome (jumper enlevé)
  • Relier la carte au port parallèle d'un PC par un cable droit.

 

Coté soft

Les outils
  • Les outils fournis pour la carte StarterKit.
    DSPTMS320VC\ti_dsp\BIN_carteStarterKit (sur le CD). Il ne sont pas détaillés. Il y'a un assembleur (mais pas de compilo C), un loader. Un debuggeur (qui peut tjrs servir, mais avec des restrictions lorsqu'on n'utilise pas l'assembleur),etc.
    Attention
    ! Tous ces outils fournis par TI, sont fournis pour DOS. Il fonctionnent donc sous DOS, et sous 95 et 98 (enfin normallement), par contre il ne fonctionnent PAS sous NT, 2K, XP, à moins d'utiliser un soft permettant à un programme 16 bits, d'accéder aux registres du port parallèle.
    Ces outils sont décrit dans la doc du StarterKit.
  • Les outils officiels TI. TI fournit (dans le rep \DSPTMS320VC\ti_dsp\BIN sur le CD):
    • Un assembleur : ASM30.EXE
    • Un compilateur C : CL30.EXE
    • Un Linker : LNK30.EXE
    • Plus quelques autres utilitaires.

Apercu de l'utilisation des outils officiels TI

Pour générer du code qui pourra ensuite être envoyé dans la carte, il se passe :

  • Ecriture du code C/et ou Assembleur dans un éditeur quelconque, enregistrer les fichiers sur le disque.
  • Assemblage par asm30.exe des fichiers .asm (moyennant palette d'options sur la ligne de commande)
  • Compilation par CL30.exe des fichiers .c (moyennant palette d'options sur la ligne de commande)
  • Link de l'ensemble. A ce moment, il est nécessaire que le linker soit informé du mapping mémoire (c'est à dire, à quelle adresse se trouve la mémoire). Ceci ce fait dans les options du linker. Pour éclaircir la chose, les options du linker (avec donc dedans le mapping mémoire) sont regroupées dans un fichier.
  • On a, à ce moment une image de ce qui devra se trouver en mémoire(ici dans un fichier .out). Cette image peut :
    • être envoyée en mémoire moyennant un soft permettant de charger l'image.
    • être convertie au format permettant d'effectuer un bootload (cf ici). Ensuite cette image sera flashée dans la flash.

     

    A partir de ça, ce qu'il reste à disserter ...

  • La phase d'écriture/assemblage/compilation/link
  • L'envoi à la carte
  • Le flashage
  • ... et l'application.

La phase d'écriture/assemblage/compilation/link

Globallement, il y'a 2 solutions :

  • Soit on utilise notepad pour écrire son code et des batchs pour compiler, permettant de réaliser tant bien que mal ce qu'on veut (il en reste quelques vestiges dans Asservissement-balisees\asser_dsp\Asser_DSP)
  • Soit on s'énerve, et on essaye d'inclure tout ce b** dans un éditeur de code et prenant en charge l'appel des différents outils. C'est cette deuxième solution qui a été utilisée. C'est celle-ci qui sera décrite. La première pouvant en être déduite à partir des infos données pour la 2ème. (commencer ici - paramètres -ATTENTION dans le cas d'une utilisation sans MAKE-TI, il y'a moyen de faire plus court qu'en utilisant les paramètres décrit en dessous - Il faut aussi ignorer les paramètres '-q', qui réduisent la quantité d'infos générées par les outils)

    Avant propos

Le désavantage de cette deuxième solution est de faire appel à un programme que j'ai écrit : Make_TI.(enfin massacré/trucidé vu les conditions de vitesse de développement et d'impératif de fonctionnement rapide). Ce soft vient remplacer le 'make' d'un éditeur de C : Wedit (faisant partie de LCC-Win32). Le désavantage ? C'est que l'évolution de ce truc est limitée. Et son fonctionnement n'est pas guaranti avec les futures versions de LCC-Win32.

Installation

Installer LCC-Win32 (LCC\lccwin32.exe sur le CD).
Executer Make-TI (LCC\install.exe), cliquer sur installer Make-TI. Le soft va alors renommer le make.exe (répertoire bin de LCC) en make_first.exe
Il va ensuite mettre un nouveau make.exe,et le fichier help.txt

Utilisation

LCC-Win32 (par la suite abrégé en LCC) est à la base un compilateur Win32 (C sous Windows quoi). Ici est décrit très très sommairement la création d'un nouveau projet, pour une utilisation en ligne de commande.
La création d'un projet pour compiler avec les outils TI (en utilisation make TI) est identique.

  • Commencer par créer un projet (en s'arrêtant à Bon maintenant un petit essai .... )
  • Fermer le projet, puis le rouvrir (project - close, projet - open)
  • Pour configurer les paramètres de compilation,etc dans Make-TI, il faut
    • Allumer ScrollLock( avec la touche - Arrêt Défil)
    • Lancer une compilation (compiler - make ou F9).
  • On obtient une boite de configuration



Boite de configuration de Make-TI

Dans cette boite, on choisit le projet à configurer (ici test_dsp).Il est indiqué qu'il s'agit d'un projet LCC C. On le change en cliquant droit dessus

Changement de type de projet

On choisit alors TI-DSP TMS320. Une fois ça fait, en double cliquant sur le nom du projet (ici, test_dsp), on peut configurer l'ensemble des paramètres de compilation.

Configuration propre à l'environnement TI

Les (...) permettent de chosir un répertoire ou un fichier via une boite de choix de win. Les boutons aide permettent d'afficher de l'aide sur les paramètres. Il va falloir quasiment tout remplir :

  • Répertoire principal. Il s'agit du répertoire où se trouvent tous les outils TI. Ce répertoire doit être une copie du répertoire DSPTMS320VC\ti_dsp\BIN du CD
  • Assembleur
    • Executable : choisir ASM30.exe
    • Options : (en faisant aide, on a la liste) la seule indispensable est '-q'
  • C
    • Executable : choisir cl30.exe
    • Options : les seules indispensables sont : '-c -q'
    • Pour le projet, il faut/on peut rajouter
      • '-k' (pas obligatoire), permet de garder les fichiers .asm utilisés lors de la compilation (et voir ce qu'à pondu le compilo ...)
      • '-s' (pas obligatoire), qui permet d'afficher dans les fichiers .asm générés, le code C (pour savoir quoi correspond à quoi)
      • '-mx', qui coûte pas cher et peu rapporter gros : nommé avoid TMX silicon bugs (oui, il existe un certain nombre de bugs dans les DSP TMS320VC). Attention cependant, à ne pas les accuser à tort. Dans le cadre de l'asservissement, on a trouvé qu'un seul bug imputable au compilo. Aucun imputable directement au DSP. (par contre des bug dûs à des conn*, la doc mal foutue,etc)
  • Linker
    • Exécutable : Lnk30.exe
    • Options (une par ligne, l'ordre peut jouer une importance)
      • -m "asser.map",(indispensable) indique que l'on veut un fichier '.map' détaillant l'utilisation de la mémoire et l'@ mémoire des variables statiques. Rappel, on peut grâce à la com' DSP<->PC, récupérer n'importe quelle adresse mémoire. On peut donc avec l'utilisation de ce fichier, récupérer n'importe quelle variable.
      • -stack 0x200 indique la taille de la pile. Il n'a pas clairement été mis en évidence que ce paramètre était responsable de quelconques plantages. Cependant, vu la place dispo, autant ne pas risquer.(ATTENTION : Le mapping mémoire faux par la suite peut venir contredire ce fait)
      • -q (indispensable)
      • -c (indispensable)
      • -l "%%rts30.lib", indique qu'il faut linker aussi la librairie rts30.lib. Cette librairie contient TOUTES les fonctions C standard et les fonctions d'initialisation. Le %% est un code reconnu par Make-TI, il est remplacé par le chemin du répertoire principal (choisi au dessus)
      • mem.def qui va indiquer tout le mapping mémoire. mem.def va être un fichier à créer, son contenu va être explicité par la suite.

     

  • On obtient au final quelquechose du genre (tout n'est pas identique)

 

Mapping mémoire

Ici, il a été choisi de le stocker dans mem.def. Ce choix est arbitraire. Ce fichier est un fichier texte. Il est situé dans le répertoire lcc du projet (ici : dsp_test\lcc)

Voilà un exemple du contenu de ce fichier

MEMORY{
IRAM0 : origin = 00809826h length = 03cah /* Int 0, 1k */
PAGE 0 : IRAM1 : origin = 00809C00h length = 0400h /* Int 1, 1k */
PAGE 1 : IVECT1 : origin = 00809FC2h length = 1
PAGE 2 : IVECT2 : origin = 00809FC4h length = 1
PAGE 4 : IVECT3 : origin = 00809FC9h length = 1
PAGE 3 : RAM_EXT : origin = 00900000h length = 20000h /* */
}

SECTIONS{
.sect "cinit" : load = IRAM0
.stack : load = IRAM1, page = 0
.text : load = RAM_EXT , page =3
.data : load = RAM_EXT , page =3
.bss : load = RAM_EXT , page =3

vectors : load = IVECT1,page = 1 {helper.obj(.servec1)}
/* INT 1*/
vectors : load = IVECT2,page = 2 {helper.obj(.servec2)}
/* INT 3*/
vectors : load = IVECT3,page = 4 {helper.obj(.servec3)}
/* INT TIMER*/
it_stub : load = IRAM1,page = 0 {helper.obj(.it_wra)}
}

  • MEMORY indique le 'découpage' de la mémoire. On indique/ou non (pourquoi ça ???) un N° de page et un Nom pour chaque zone de mémoire. On indique ensuite l'adresse de départ et la taille. Ici
    • IRAM0 : origin = 00809826h length = 03cah /* Int 0, 1k */
      correspond au 1er morceau des 1KMots internes (cf mapping mémoire carte). Cette zone ne commence pas tout à fait au début de la RAM, pour laisser au debut une zone, que le LINKER n'utilisera PAS.
      Le linker ne connait pas la zone située entre 809800h et 809826h. Il ne va donc pas mettre ni de code, ni de données dedans. Par contre, ça n'interdit en AUCUN CAS au programme que l'utilisateur a écrit, de venir écrire dans cette zone (et ailleurs où y'a pas de mémoire ni rien, si ça lui chante, voire même en plein milieu du code si il veut finir de tout planter).
      L' idée, derrière tout ça, est d'empêcher le linker d'utiliser cette zone, et de venir mettre ce qu'on veut dedans (dans le prog DSP). On est donc sûr quelquesoit le programme que la zone n'est pas utilisée par le prog. On peut venir y mettre les données de debug, qui seront toujours à la même adresse. Il est possible donc, à partir de la communication PC <-> DSP, de venir récupérer ces données puisqu'on sait où elles sont.
      Il est à noter, que cette méthode n'a été utilisée que pour les variables de debug créées au debut (asservissement, position, ordre,etc).
      Par la suite, pour les autres variables, il a été utilisée l'autre méthode qui consiste à :
      • Mettre les variables, à récupérer depuis le PC, en statique pour que, une fois que le linker a fait son boulot, les variables aient une adresse fixe (qui ne varie pas pendant l'execution du programme mais qui peut varier d'une compilation à l'autre)
      • Laisser donc le linker faire sa tambouille, par contre lui demander un fichier .map, indiquant les adresses.
      • Lire ce .map et déterminer l'adresse de ce qui nous interesse (la variable ou la structure que l'on recherche).
      • Lire le contenu de cette adresse.
    • PAGE 0 : IRAM1 : origin = 00809C00h length = 0400h /* Int 1, 1k */
      2ème morceau de la mémoire interne.Qui utilise A TORT le contenu ENTIER de ce 2ème morceau !!!.
    • PAGE 1 : IVECT1 : origin = 00809FC2h length = 1
      Petit morceau de la 2ème zone mémoire, qui correpond à un morceau de la table des vecteur d'IT
    • PAGE 2 : IVECT2 : origin = 00809FC4h length = 1
      Petit morceau de la 2ème zone mémoire, qui correpond à un morceau de la table des vecteur d'IT
    • PAGE 4 : IVECT3 : origin = 00809FC9h length = 1
      Petit morceau de la 2ème zone mémoire, qui correpond à un morceau de la table des vecteur d'IT
    • PAGE 3 : RAM_EXT : origin = 00900000h length = 20000h /* */
      Ensemble de la RAM externe.
  • SECTIONS, va indiquer à quel endroit on va mettre le code/les données,les variables,etc
    • .sect "cinit" est le code que le compilateur C va générer pour initiliser le programme (ex pour initialiser les variables statiques au démarrage du programme), cette section est mise dans IRAM0 c'est à dire le premier bloc de mémoire interne du DSP
    • .stack est la pile du programme. Elle sera mise dans le 2ème morceau de mémoire (ici défini trop grand !). Le soft pourrait donc planter si la pile vient à être trop utilisée (il viendrait écrire dans la table des vecteurs d'interruption)
    • .text correspond au code. Il est mis en RAM externe.
    • .data correspond aux données, en RAM externe aussi.
    • .bss correpond au 'tas' (utilisé par malloc par ex),.RAM externe
  • Vient ensuite dans SECTIONS, toujours, la déclaration des vecteurs d'interruptions. Lorsqu'une IT survient, si elle n'est pas masquée, le DSP va exécuter le code situé à une adresse qui dépend de l'IT.

.

  • On va donc venir mettre aux adresses qui correpondent aux IT intéressantes (INT1,INT3 et Timer), ici, une instruction permettant de continuer l'exécution du code à la routine d'IT. On a défini au dessus 3 zones IVECT1, IVECT2, IVECT3 que l'on vient remplir grâce à :
    vectors : load = IVECT1,page = 1 {helper.obj(.servec1)}

    On met le code situé dans la zone référencée .servec1 (dans le fichier helper.obj -- issu de la compilation de helper.asm) dans la zone IVECT1. le code de servec1 est donc un branchement. Lorsque ce branchement pointe vers une routine en mémoire interne, il n'y a pas de problème. Par contre lorsque ce branchement pointe vers une routine en mémoire externe, a priori, ça ne fonctionnait pas (pq ? la question n'a pas été approfondie).
    La solution a été de faire pointer le branchement vers une autre routine en mémoire interne qui va, elle, effectuer le branchement vers la routine en mémoire externe.
  • On a donc l'explication de la dernière zone it_stub qui est logée en mémoire interne.
  • Lorsqu'une IT tombe (ex : IT Timer), on a donc :
    • L'IT du Timer tombe
    • Le DSP s'interrompt, et lit dans sa table située en ROM l'@ de la prochaine instruction. Il va trouver 809FC9h (IVECT3)
    • Le code situé dans IVECT3 est celui qui a été chargé depuis .servec3 dans helper.obj
    • Le DSP execute le code situé à cette adresse. Il y trouve un branchement vers une routine dans la zone it_stub.
    • Cette routine sauvegarde tous les registres, et effectue un appel à la routine d'IT.
    • La routine d'IT s'execute.
    • Elle retourne à la routine située dans it_stub.
    • it_stub retourne et le DSP continue sa tambouille principale.
  • Il y'a moyen de faire beaucoup plus propre (autant pour la définition des zones mémoires que pour le mécanisme des IT, cependant, en partant du principe que l'important dans ce cas était d'avoir une solution qui marche, la chose n'a pas été débattue plus loin).

L'envoi à la carte, le flashage et l'application

Une fois compilé et linké (on obtient un fichier .out), il faut envoyer le soft à la carte. Il est possible de faire appel au soft de chargement fourni avec le StarterKit. Cette solution a été utilisée au début. TI fournit les routines qui permettent de communiquer avec la carte DSP (et d'envoyer du code aussi). Ces routines fonctionnant sous DOS, elles ont été plus ou moins portées sous Windows. (bah un peu rapidement portées, ça se ressent d'ailleurs dans la fiabilité de la chose qui de temps en temps oublie de refermer un fichier par exemple).

Tout cet ensemble de code a été mis dans un soft lm629_dsp qui fait énormément de choses (usine à gaz - presse purée). Il s'agit en fait d'un soft qui aura servi au debug complet de la carte ET de l'asservissement, du recalage de ligne, du debug I2C, etc. Le code amoncelé dans ce soft est énorme. Il est donc impossible de décrire tout le code. Mais aussi impossible de décrire toutes les fonctions utilisées. Il est toutefois possible de reprendre ce soft pour effectuer juste le chargement du code.

Le soft est : Asservissement-balisees\asser_dsp\Asser_DSP\lcc\lm629_dsp.exe. Il a été développé entièrement sous Win95, et ne fonctionnera en l'état que sur Win95,Win98,WinMe. Il fonctionnera aussi sous 2K,NT,XP à condition de recompiler le source avec quelques modifs.