Comment puis-je exécuter une fonction à partir de la RAM sur un Cortex-M3 (STM32)?
Je suis en train d'exécuter une fonction à partir de la RAM sur un processeur Cortex-M3 (STM32). La fonction efface et réécrit le flash interne, donc j'ai vraiment besoin d'être dans la RAM, mais comment dois-je faire?
Ce que j'ai essayé est présente: Copie de la fonction à un tableau d'octets dans la mémoire RAM à l'aide de memcpy (en vérifiant qu'il est aligné correctement), la définition d'une fonction pointeur sur le tableau d'octets en une, puis l'appel de la fonction(pointeur).
Cela fonctionne très bien pour peut-être 10 instructions (je peux suivre l'exécution avec le débogueur) mais puis-je obtenir un bus d'erreur et le processeur de la réinitialisation. Le buss erreur se produit lors du deuxième passage dans une boucle de sorte que le code doit être fine (comme il fonctionne de la première passe). Je pense que le plus rapide l'accès à la RAM fou jusqu'au bus de timing, d'une certaine façon...
De toute façon est-il une bonne façon de le faire? Comment un scatter fichier ressemble qui place une fonction dans la RAM automatiquement (je suis en utilisant Keil uVision pour Cortex-M3)?
Edit: Plus d'infos:
Suite d'outils: RealView MDK-ARM V 4.10
Compilateur: Armcc v4.0.0.728
Assembleur: Armasm v4.0.0.728
Linker: ArmLink v4.0.0.728
Processeur: STM32F103ZE
La IMPRECISERR bit est défini dans le bus, faute de s'inscrire lors de la réinitialisation se produit.
Mais je vous aime les gars plus!
OriginalL'auteur c0m4 | 2010-06-15
Vous devez vous connecter pour publier un commentaire.
Le crash lors de l'itération de boucle est probablement parce que la fonction de branchement à une adresse absolue et non relative à la nouvelle fonction de l'emplacement dans la mémoire RAM. Permettrait d'accéder au code d'origine est l'endroit et le point de provoquer une erreur de bus à cause du flash de l'opération d'effacement?
Je crois que vous pouvez marquer une fonction de compilation et copiée dans la mémoire vive correctement avec la GCRA, en ajoutant le
__ram
directive à la définition de la fonction. Pour des instructions sur la façon de faire de même avec le RealView compilateur voir le L'EXÉCUTION DES FONCTIONS DANS LA RAM article de l'assistance technique:Que devrait générer le code de démarrage pour prendre soin de la copie de la fonction de mémoire vive et de relier les appels à l'emplacement correctement. Sinon, si vous avez besoin d'dynamiquement une copie de fonctions arbitraires de RAM, puis regardez dans la compilation code indépendant de la position (PIC) avec RealView.
J'ai le même problème sauf que je ne suis pas en utilisant RTX ou toutes les bibliothèques, donc je ne comprend pas le compilateur de code qui charge automatiquement de RAM fonctions dans la RAM. J'aimerais avoir une charge de la région ou de l'exécution de la région dans la RAM où mon code sera effectivement lié mais j'ai besoin de le JTAG programmeur pour charger le code dans une autre adresse (en flash). Idéalement dans le .sct fichier (je suis en utilisant Keil MDK) j'aurais une section où je spécifier le stockage de liaison et d'adresse. Mais je n'ai pas travaillé sur la façon de le faire encore.
Vous souhaitez peut-être envisager d'ouvrir une nouvelle question à vos spécificités. Cependant, je crois que la solution ci-dessus s'applique à votre situation.
OriginalL'auteur Judge Maygarden
Sans en savoir plus sur votre situation je ne peux que suggérer quelques choses... assurez-vous que vous avez une pile valide pour cette fonction (ou d'éviter tous les pile opérations dans la fonction), que les interruptions sont désactivées, et que tous les vecteurs dans le système de vecteur de la table n'a pas de point de code, qui s'en va lorsque vous effacez flash. Enfin, assurez-vous que votre fonction est lié à exécuter à l'adresse que vous avez mis... le code ne peut pas être transférables et peuvent sauter à un endroit dans qui est ancien emplacement.
OriginalL'auteur Amardeep AC9MF
Parce que le BRAS a une capacité limitée à charge immédiate des données, des utilitaires pour générer du code pour le BRAS fréquemment juxtaposent le code et les données. Par exemple, un énoncé comme
pourrait finir comme quelque chose comme:
Noter que _myVar et 0x12345678 peut être placé immédiatement après le code de la routine dans laquelle ils apparaissent; si vous essayez de déterminer la longueur de la routine à l'aide d'une étiquette qui suit la dernière instruction, telle longueur n'arrivent pas à inclure des données supplémentaires.
Une chose supplémentaire à la note avec le BRAS que pour des raisons historiques, le code des adresses souvent ont leur bit le moins significatif même si le code commence réellement à demi-mot les limites. Ainsi, une instruction dont l'adresse est 0x12345679 va occuper deux ou quatre octets commençant à 0x12345678. Cela peut compliquer le calcul des adresses pour des choses comme memcpy.
Ma recommandation serait d'écrire une petite routine en langage d'assemblage pour faire ce que vous avez besoin. C'est à seulement quelques instructions, vous pouvez savoir exactement ce que fait le code et ce que l'adresse de dépendances, et vous n'aurez pas à vous soucier de l'avenir des versions de compilateur de changer votre code de manière à casser quelque chose [par exemple, la troisième version du code ci-dessus aurait pas de problème même si
dat1
atterri sur une étrange halfword frontière depuis la M3, l'instruction LDR peut gérer non alignés lit, mais le quatrième (légèrement plus rapide et plus compact) version à l'aide de LDRM échouerait dans de tels cas; même si, aujourd'hui, la version du compilateur utilise quatre LDR instructions, une future version pourrait utiliser LDRM].OriginalL'auteur supercat
Avec l'IAR compilateur (je sais que votre question est à propos de Keil, mais je n'ai pas de jouer avec), vous pouvez marquer l'ensemble du projet ou d'un fichier individuel pour être "indépendant de la position". De l'aide dans le passé avec d'autres processeurs cela signifie que vous pouvez le déplacer n'importe où" et il fonctionnera toujours ok
OriginalL'auteur peter_mcc