Asservissement-Positionnement

Bootload, Interface, Code PC et Flash


Introduction

Le but est de détailler un peu plus spéciallement le processus de bootlad (chargement du code).

Documentations

Site web TI : www.ti.com
Ressource principale (datasheet complète de la famille TMS320VC3x) : TMS320C3x User guide.pdf
Spécificités du C31 : tms320c31.pdf
Carte d'évaluation : DSP Starter Kit User Guide.pdf

Aperçu détaillé et nominatif des opérations :

Comprendre le processus de bootload permet souvent de gagner un temps bien précieux par la suite.

On distingue 3cas :

  • Le chargement et execution du code en RAM (debug)
  • Il est lancé par . A ce moment, la carte ne contient rien. Les opérations suivantes sont effectuées :

    • Reset du DSP.


    • Chargement du Kernel de communication/debug (fichier C3x.dsk). Dès que le Reset est terminé le DSP exécute un petit bout de programme en ROM (cf page 718 C3x User Guide). Ce bout de programme vient demander élément par élément le contenu du fichier à charger sur le port // (si le jumper n'est pas mis, ce jumper change l'@ utilisée). Ce fichier est le Kernel. Il est placé dans le 2 ème bloc de la RAM Interne.

    • Une fois le chargement terminé, le Kernel (qui est un bout de soft comme un autre) s'execute.



    • A ce moment le Kernel ne fait qu'attendre une interruption. Cette interruption engage la reception d'une commande via le port //. Cette comande peut être une lecture, une écriture en mémoire, etc ...
      Le soft sur le PC, va donc générer plusieurs de ces interruptions pour venir écrire le programme 'utilisateur' ('asser_dsp.out' défini par #define PROG_NAME "..\\..\\asser_dsp\\lcc\\asser_dsp.out" dans flash.h) en mémoire RAM.



    • Une fois le chargement terminé, pour vérifier que tout marche, le soft PC va écrire (via commande d'écriture envoyée de la même façon qu'à l'étape précédente) dans une zone mémoire réservée (tout début du premier bloc de RAM Interne). Il va ensuite relire (idem via une autre commande), ce qu'il vient d'écrire et s'assurer que c'est bien identique. On s'assure que le programme a été chargé correctement. A ce moment le programme utilisateur ne s'execute pas encore.


    • L'execution du code utilisateur est lancée (via une autre commande idem au dessus).


    • Pour vérifier que tout marche encore, une ecriture et une relecture de la même valeur que précemment est lancée, pour s'assurer que tout fonctionne toujours.

  • Le Flashage du code
    • Le flashage du code est lancé par
    • Le fichier asser_dsp.out (celui défini par PROG_NAME dans flash.h), est convertit en données brutes pour pouvoir être flashé (boot.raw).
      Load_File(PROG_NAME,FILE2HEX);
    • Le flashage est lancé. Le flashage est effectué en faisant des écritures/lectures en mémoire du DSP (sur l'@ correespondant à la flash) (même chose que lors du chargement depuis le PC cf wait_it)

  • L'execution du code flashé
    • Lorsque le jumper est mis et que la carte est mise sous tension ou resetée


    • Dès que le Reset est terminé le DSP exécute un petit bout de programme en ROM (cf page 718 C3x User Guide). Ce bout de programme vient demander élément par élément le contenu des données à charger depuis la flash. Ces données sont directement le programme utilisateur.



    • L'exécution du programme utilisateur est lancée automatiquement à la fin du chargement.



Intrerface Hard

L'interface hard DSP/Port //, extérieure suit ce schéma.

Interface Port // (gauche)/ carte Starter Kit (droite)

Entre cette interface et l'interface simple présentée sur le schéma de l'extension, les points suivants diffèrent :

  • Le traitement du signal RESET. Ici, en plus d'un pullup, un filtrage est ajouté (C11)
  • Le traitement du signal ERROR (filtrage par C10 R9)
  • Les 8 signaux de données D1/D7 (filtrage R/C)
  • Par rapport à l'interface initilae, la différence principale est la longueur des fils transportant les signaux.

Code PC, points clés

Les points clés/ étapes dans l'usine à gaz, du processus de bootload sont :

  • Click sur
  • Dans "com_dsp.c" : BOOL CALLBACK DspCallBack(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    • Appel de init_DSK3(); // Cet appel sert à charger le Kernel d'office. Cette étape est inutile car le Kernel est chargé après
    • Appel de init_user_part();
    • Dans "com_dsp.c" : int init_user_part(void);
      • Appel de Init_Communication(10);
      • Dans "object.c" : MSGS Init_Communication(int loops)

        • get_buswidth(); // Query target for current bus mode
          getmem(TESTLOC,1,&orig); // If communications fails the port is
          putmem(TESTLOC,1,&babe); // reset to the default conditions
          getmem(TESTLOC,1,&temp);
          if(putmem(TESTLOC,1,&orig) == NO_ERR)
          if(temp == babe)
          if(set_buswidth() == NO_ERR) break;
        • Cette première partie permet de tester si le Kernel est correctement chargé. C'est à dire si :
          • il est possible de faire appel à la fonction 'écriture en mémoire'
          • puis 'lecture en mémoire'.
          • Que ce qui a été écrit est correctement relu (temp==babe)
          • Qu'il est possible d'indiquer au Kernel si il est en mode 4 bits ou en mode 8 bits (ie : patcher le Kernel)
          • Si tout ceci est OK, alors c'est que le Kernel est correctement chargé

        • // If read/write fails, try bootloading
          if((err=Load_File(PATH,BOOT))!=NO_ERR) // BOOT also loads symbols
          enable_Mtask();
        • Cette 2ème partie charge le Kernel (le test sera recommencé au tour de boucle suivant)
        • Appel de Load_File(PATH_BOOT);
          • Dans "dsk_coff.c" : MSGS Load_File(char *file,TASK task)
          • if(strstr(filename,".DSK")!=NULL) err = LOADDSKA(filename, task);
            else err = LOADCOFF(filename, task);
          • Appel de LOADDSKA(filename, task);
            • Dans "dsk_coff.c" : MSGS LOADDSKA(char *lst_file, TASK task)

            • if((err=DSK_reset(0))!=NO_ERR)
            • Appel de la routine de Reset du DSP. Vérifie que le DSP commence bien à demander son code juste après le Reset.

            • xmit_byte(0x08);
              xmit_byte(0x00);
            • Envoi de l'en tête

            • data2target(0x00000008L,0x00000000L,task,"Bus Width");
              data2target(0x00001058L,0x00000000L,task,"Bus Control");
              data2target(0x00000001L,0x00000000L,task,"Dummy Section size");
              data2target( ENTRY,0x00000000L,task,"Dummy Start Address");
              err=data2target(0x00000000L,0x00000000L,task,"Dummy Data");
            • Envoi d'une section de test

            • { data2target(length , 0x00000000L, task,"Section Size");
              data2target(section_start, 0x00000000L, task,"Start Address");
              }
              if((err=write_seg_val(lst_file, task))!=NO_ERR)
            • Ecriture du Kernel proprement dit

Lorsque le Kernel a réussi à se charger correctement (vérifié par le test ecriture/lkecture en mem du DSP), l'inteface est fonctionnelle.