1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juin 2016
    Messages : 3
    Points : 1
    Points
    1

    Par défaut [STM32] Réception et exécution de code en RAM

    Bonjour à tous,

    Je suis étudiant et je travaille actuellement sur un projet dont une des fonctionnalités est de recevoir du code exécutable via une UART en RAM et être capable de l'exécuter.

    J'ai pas mal recherché sur les forums sans trouver de réponses convenables, je ne sais pas si c'est possible également.

    Je sais qu'il est possible d'écrire des fonctions de façon à ce qu'elle s'exécutent en RAM mais les fonctions sont d'abord placées en ROM. Ma question est de savoir si il est possible d'écrire du code exécutable de façon à ce qu'il soit "portable" et de le télécharger sur ma RAM via une UART ?

    J'ai lu des choses intéressantes sur l'option -fpic de gcc sans vraiment trop comprendre comment je pourrais l'utiliser dans mon projet.

    Est que quelqu'un aurait une suggestion, des idées de pistes ou bien des liens intéressants ?

    Merci par avance

  2. #2
    Modérateur
    Avatar de Vincent PETIT
    Homme Profil pro
    Ancien développeur matériel électronique (Hard/Soft)
    Inscrit en
    avril 2002
    Messages
    1 595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ancien développeur matériel électronique (Hard/Soft)
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 1 595
    Points : 4 928
    Points
    4 928

    Par défaut

    Salut,
    Le document AN4296 de chez ST montre comment placer du code dans une partie de la RAM. Visiblement ça ne concerne pas tous les micro de la gamme STM32.

    Je me demande s'il suffit pas simplement d'installer un bootloader UART standard et lui envoyer un programme que tu aura compilé avec les astuces qui sont dans le document AN4296.

    A+

  3. #3
    Membre habitué Avatar de cedd70
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    mars 2012
    Messages
    98
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : mars 2012
    Messages : 98
    Points : 168
    Points
    168

    Par défaut

    Salut,

    Tu dois pouvoirs charger ta RAM, regarde du coté de la configuration de la DMA. En revanche pour exécuter c'est pas faisable.

  4. #4
    Modérateur
    Avatar de Vincent PETIT
    Homme Profil pro
    Ancien développeur matériel électronique (Hard/Soft)
    Inscrit en
    avril 2002
    Messages
    1 595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ancien développeur matériel électronique (Hard/Soft)
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 1 595
    Points : 4 928
    Points
    4 928

    Par défaut

    En complément de la remarque de cedd70 sur le DMA qui te permettra de réaliser des tâches sans solliciter le processeur.

    Ce que tu souhaites faire est possible.
    - Voir l'AN4296 : http://www.st.com/content/ccc/resour...DM00083249.pdf
    - Uniquement sur des micros intégrants une RAM CCM (core coupled memory) comme le STM32F303 : http://www.st.com/content/ccc/resour...DM00092070.pdf

    C'est un micro de compète ! Je crois que je vais bientôt essayer du ST.

    De ce que j'ai compris, lorsque tu utilises la RAM CCM (pour le programme) avec la RAM classique (pour les données) tu te retrouves avec une mémoire données et une mémoire programme sur des bus séparés mais ultra rapides car tous les deux des RAM. L'utilisation de cette configuration est réservé à des choses très particulières comme du calcul intensif ou traitement du signal. J'ai l'impression que toi, tu souhaites y mettre un programme quelconque et d'une utilisation générale mais sache que tu seras limité en taille car la RAM CCM ne fait que 4k ici contre 64k pour la mémoire Flash classique.

    Sur le dernier dessin, en rouge et en orange, c'est le chemin qu'emprunte le système bootloader classique. Il faut aussi lire la doc pour comprendre comment régler la broche BOOT0 et la bit BOOT1 pour que le compteur programme aille où il faut au démarrage.

    Nom : Capture30.png
Affichages : 53
Taille : 126,1 Ko

    Nom : Capture31.png
Affichages : 55
Taille : 101,2 Ko

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juin 2016
    Messages : 3
    Points : 1
    Points
    1

    Par défaut

    Je vous remercie de vos réponses, effectivement le micro que j'utilise (STM32F746ZG) semble avoir ce type de mémoire (TCM RAM), le problème de ça c'est que si jamais je dois utiliser un micro sans ce type de mémoire je ne peux pas charger et exécuter du code RAM (si j'ai bien compris) et ça m'embête un peu puisque le programme que j'écris dépendra de mon micro.

    Ce que je ne comprend pas c'est que j'arrive à déclarer une section de ma RAM dans le fichier de link et écrire des fonctions pour qu'elles s'exécutent en RAM dans cette section(le code des fonctions réside lui dans la ROM) avec des directives du style ; "
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    __attributes__ ( ( long_call, section(".ma_section") ) )
    ". J'ai bien observé que les fonctions que je déclare s'exécutent en RAM et lorsque je fais un reset du micro, les fonctions s'exécutent toujours en RAM (donc le code est bien mémorisé quelque part en ROM).

    Pour essayer de résoudre mon problème (charger un code exécutable directement en RAM puis pouvoir l'exécuter) j'ai d'abord crée un programme simple (hello world par exemple) que je désassemble avec "objdump" de façon à obtenir le code assembleur pour ma cible.

    Je récupère ensuite ce code que j'envoie sur mon micro en faisant attention à l'"endianess" et au format de mes données. Et je viens écrire ce code directement en RAM. Jusque la je n'ai pas de problème.

    Le problème arrive lorsque je souhaite exécuter mon code, je déclare un pointeur de fonction (
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void(*ma_fonction)(void) = (void *) 0x20005000;
    ) sur l'adresse de mon code située en RAM puis je saute dessus (). Lorsque je debug mon pc se retrouve à l'adresse de la première instruction de ma fonction mais l'exécution crashe.

    Je n'ai pas compilé mon programme (chargé via l'uart) avec l'option -fpic et je me dis que je devrais continuer à chercher dans ce sens. De plus, je devrais être capable d'exécuter du code depuis cette partie de la RAM puisque j'y arrive avec des fonctions mémorisées en ROM.

    Est ce que vous avez un avis sur la question ?

  6. #6
    Modérateur
    Avatar de Vincent PETIT
    Homme Profil pro
    Ancien développeur matériel électronique (Hard/Soft)
    Inscrit en
    avril 2002
    Messages
    1 595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ancien développeur matériel électronique (Hard/Soft)
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 1 595
    Points : 4 928
    Points
    4 928

    Par défaut

    Citation Envoyé par tunroc Voir le message
    le problème de ça c'est que si jamais je dois utiliser un micro sans ce type de mémoire je ne peux pas charger et exécuter du code RAM (si j'ai bien compris) et ça m'embête un peu puisque le programme que j'écris dépendra de mon micro.
    En effet si le micro n'a pas ce type de mémoire, autrement dit la majorité des micros, alors ça ne fonctionne pas. Dans ce cas il te faut un simple bootloader UART qui te permettra de mettre à jour un programme dans la mémoire Flash (c'est le grand classique)

    De toi à moi, je ne comprends pas pourquoi tu veux charger un programme en RAM pour l'exécuter ? C'est vraiment très très très particulier comme cas de figure. On fait ça lorsqu'on veut rivaliser avec un DSP ou s'approcher un peu des perfs d'un FPGA en terme de rapidité de calcul.

    Les seuls fois où j'ai été amené à faire un tel truc c'était il y a 17 ans, à l'école sur le légendaire et mythique 68HC11.... (c'était déjà un dinosaure à l'époque ) mais la raison était très simple, ce micro n'avait pas de Flash mais une ROM programmable une seule fois (emmerdant pour faire des essais) ! Donc dans la ROM j'ai programmé un bootloader et son rôle était de prendre les données (un programme) qui arrivaient dans l'UART et les mettre dans la RAM (utilisation illimitée). A chaque démarrage du micro, il attendait qu'on lui charge un programme. Ça fonctionnait aussi parce que ce micro avait une architecture Von Neumann (en terme de bus interne d'adresses et de données la ROM était à la suite de la RAM) et le compteur programme pouvait aller en RAM. bref....

    Mais aujourd'hui tout le monde charge son programme en Flash, c'est reprogrammable et c'est garantie pour un très grand nombre de cycle (10 000 fois) ça veut dire que tu peux reprgrammer la flash de ton micro avec un nouveau programme via l'UART à raison de 1 fois par jour pendant 27 ans avant que le micro commence à souffrir.


    Si vraiment c'est ce que tu souhaites faire, mais je suis curieux de connaître la vraie raison, alors as tu essayé simplement ce qui est écrit au chapitre 4.2 du document AN4296 (le lien est dans mon précédent message) ?

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juin 2016
    Messages : 3
    Points : 1
    Points
    1

    Par défaut

    Citation Envoyé par Vincent PETIT Voir le message
    Si vraiment c'est ce que tu souhaites faire, mais je suis curieux de connaître la vraie raison, alors as tu essayé simplement ce qui est écrit au chapitre 4.2 du document AN4296 (le lien est dans mon précédent message) ?
    Le chapitre 4.2 parle d'exécution en RAM mais j'ai bien l'impression que le code se trouve en ROM. Je ne comprend pas très bien ce qui exprimé dans le code. Est ce que le fichier .o est mémorisé en ROM, est ce que je peux charger un fichier .o contenant mes fonctions ? Pour la raison, disons que je ne veux pas que mon code se retrouve en mémoire non volatile de façon à ce qu'il ne soit pas traçable, qu'il soit irrécupérable.

    Quoi qu'il en soit j'ai réussi à exécuter du code machine écrit directement à une adresse fixe de la RAM en suivant la méthode de mon dernier post. J'ai lu la documentation ARM et j'ai découvert que le premier bit de l'adresse d'une instruction doit toujours commencer par 1 ! J'ai donc simplement incrémenté de 1 mon pointeur de fonction.

    Mon problème maintenant est que le code machine que j’introduis via l'UART dans ma RAM est "linéaire" c'est à dire que la fonction n'effectue aucun appel à d'autres fonctions, il n'y a donc pas d'instruction de type "Branch", pas de "jump". Je dois actuellement trouver une solution pour que le code machine que j'exécute en RAM puisse être capable d'appeler des fonctions déjà présentes en mémoire ROM ou RAM par exemple.

    A ce sujet, je me demande s'il est possible d'accéder à la table de symbole d'un programme lors de son exécution ? Je me dis que ça doit être possible car lorsque j'appelle une fonction (par ex printf) le programme sait à quelle adresse se trouve la fonction et elle est exécutée. Je pense aussi qu'en jouant avec le fichier de link ça doit être faisable.

  8. #8
    Modérateur
    Avatar de Vincent PETIT
    Homme Profil pro
    Ancien développeur matériel électronique (Hard/Soft)
    Inscrit en
    avril 2002
    Messages
    1 595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ancien développeur matériel électronique (Hard/Soft)
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 1 595
    Points : 4 928
    Points
    4 928

    Par défaut

    Citation Envoyé par tunroc Voir le message
    Le chapitre 4.2 parle d'exécution en RAM mais j'ai bien l'impression que le code se trouve en ROM. Je ne comprend pas très bien ce qui exprimé dans le code. Est ce que le fichier .o est mémorisé en ROM, est ce que je peux charger un fichier .o contenant mes fonctions ?
    Je n'ai pas ton micro pour essayer mais je trouve le document assez explicite.

    Pour placer une ou plusieurs fonctions dans la CCM RAM, sous entendu les autres fonctions iront naturellement dans la Flash.

    1. Trouver le fichier linker de ton projet (.ld) pour le modifier et ajouter dedans l'adresse de départ et la taille de ta CCM RAM (les modifications a apporter sont encadrer en rouge)
      Nom : Capture du 2017-05-17 22-31-39.png
Affichages : 35
Taille : 51,1 Ko
    2. Visiblement dans le même fichier (.ld) ajouter dedans que les sections de code avec l'attribut ccmram doivent être placées dans CCM RAM, préalablement définie en 1 (les modifications a apporter sont encadrer en rouge)
      Nom : Capture du 2017-05-17 22-32-08.png
Affichages : 34
Taille : 63,4 Ko
    3. Trouver le fichier startup pour le modifier et ajouter dedans l'initialisation des données qui seront placées dans la CCM RAM (les modifications a apporter sont en rouge)
      Nom : Capture du 2017-05-17 22-32-09.png
Affichages : 35
Taille : 55,9 Ko
    4. Pour placer une fonction dans la RAM, donner l'attribut ccmram à son prototype comme ceci : void MaFonction (int x, int y) __attribute__ ((section, (".ccmram")));
    5. Compiler et envoyer le programme dans le micro.


    Pour mettre tout ton programme en CCM RAM (donc rien en Flash) alors c'est le chapitre 4.2 qu'il faut voir.

    Citation Envoyé par tunroc Voir le message
    Pour la raison, disons que je ne veux pas que mon code se retrouve en mémoire non volatile de façon à ce qu'il ne soit pas traçable, qu'il soit irrécupérable.
    Tous les micro peuvent être verrouillés en lecture même les plus petits. Tu peux écraser la Flash mais tu ne peux pas la lire et ça consiste en une simple configuration lors de la programmation.

    Citation Envoyé par tunroc Voir le message
    Mon problème maintenant est que le code machine que j’introduis via l'UART dans ma RAM est "linéaire" c'est à dire que la fonction n'effectue aucun appel à d'autres fonctions, il n'y a donc pas d'instruction de type "Branch", pas de "jump". Je dois actuellement trouver une solution pour que le code machine que j'exécute en RAM puisse être capable d'appeler des fonctions déjà présentes en mémoire ROM ou RAM par exemple.
    Normalement ça fonctionne sans problème, je veux dire sans que tu te préoccupes de quoi que ce soit.
    Si dans la définition de ce prototype de fonction void MaFonction (int x, int y) __attribute__ ((section, (".ccmram"))); donc en CCM RAM, tu appelles une fonction qui a été déclarée comme ça void MaFonctionEnFlash (int z); donc une fonction classique en Flash alors il n'y a pas de soucis car le Linker a su mettre tout le monde aux bons endroits.

Discussions similaires

  1. Réponses: 44
    Dernier message: 02/08/2006, 16h12
  2. Erreur 3141 dans exécution de code
    Par zoom61 dans le forum Access
    Réponses: 13
    Dernier message: 23/03/2006, 17h31
  3. [RosASM] Tracer l'exécution du code
    Par aumeunier dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 14/03/2006, 18h26
  4. Réponses: 3
    Dernier message: 20/04/2005, 12h30
  5. Réponses: 7
    Dernier message: 03/02/2005, 17h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo