Question

J'essaie d'exécuter une fonction depuis la RAM sur un processeur Cortex-M3 (STM32).La fonction efface et réécrit le flash interne, donc je dois absolument être en RAM, mais comment faire ?

Ce que j'ai essayé, c'est ceci :Copiez la fonction dans un tableau d'octets dans la RAM à l'aide de memcpy (en vérifiant qu'elle est correctement alignée), en définissant un pointeur de fonction pour qu'il pointe vers le tableau d'octets, puis en appelant la fonction (pointeur).

Cela fonctionne bien pour peut-être 10 instructions (je peux suivre l'exécution avec le débogueur) mais j'obtiens ensuite une erreur de bus et le processeur se réinitialise.L'erreur de bus se produit lors du deuxième passage dans une boucle, le code devrait donc fonctionner correctement (car il fonctionne lors du premier passage).Je pense que l'accès plus rapide à la RAM perturbe d'une manière ou d'une autre le timing du bus...

Quoi qu'il en soit, existe-t-il une façon correcte de procéder ?À quoi ressemblerait un fichier scatter qui place automatiquement une fonction dans la RAM (j'utilise Keil uVision pour Cortex-M3) ?

Modifier:Plus d'informations:Chaîne d'outils :RealView MDK-Arm V 4.10 Compiler:Assembleur ARMCC V4.0.0.728:AMMASM V4.0.0.728 LIGNEUR:Processeur Armlink V4.0.0.728:STM32F103ZE

Le bit IMPRECISERR est défini dans le registre des défauts du bus lorsque la réinitialisation se produit.

Était-ce utile?

La solution

Le crash lors de l'itération de la boucle est probablement parce que la fonction est essaimer à une adresse absolue et n'est pas par rapport au nouvel emplacement de la fonction dans la RAM. Would accéder à l'emplacement de code d'origine à ce moment la cause d'une erreur de bus en raison de l'opération d'effacement flash?

Je crois que vous pouvez marquer une fonction à compiler et copiée dans la RAM correctement avec CARM par la directive annexant __ram à la définition de la fonction. Pour obtenir des instructions sur la façon de faire la même chose avec le compilateur RealView voir FONCTIONS eN RAM EXECUTION article de support technique:

  

μVision vous permet de localiser les modules   aux zones de mémoire spécifiques qui sont   entré dans la boîte de dialogue Projet -   Options - cible . Pour ce faire, à droite   cliquez sur un fichier source (ou groupe de fichiers)   et ouvrir la boîte de dialogue Options -   Propriétés . Sélectionnez ensuite la mémoire   régions sous Affectation de mémoire .

     

Il y a un exemple dans le dossier ARMExamplesRAM_Function .

Cela devrait générer le code de démarrage pour prendre soin de copier la fonction de RAM et de relier les appels à cet endroit correctement. Dans le cas contraire, si vous avez besoin de copier dynamiquement des fonctions arbitraires de RAM, puis regardez dans la compilation position de code indépendant (PIC) avec RealView.

Autres conseils

Sans en savoir plus sur votre situation, je ne peux que suggérer quelques choses générales...assurez-vous d'avoir une pile valide pour cette fonction (ou évitez toutes les opérations de pile dans la fonction), que vos interruptions sont désactivées et qu'aucun vecteur de la table des vecteurs système ne pointe vers du code qui disparaît lorsque vous effacez le flash.Enfin, assurez-vous que votre fonction est lié pour courir à l'adresse que vous l'avez indiquée...le code peut ne pas être relocalisable et peut sauter à un emplacement de son ancien emplacement.

Parce que l'ARM a une capacité limitée de charger des données immédiates, les services publics qui génèrent du code pour ARM fréquemment le code Juxtapose et des données. Par exemple, une déclaration comme

void myRoutine(void)
{
  myVar1=0x12345678;
  myVar2=0x87654321;
}

pourrait finir par quelque chose comme:

myRoutine:        
    ldr r0,=myVar1; Load the address of _myVar
    ldr r1,=0x12345678
    str r1,[r0]
    ldr r0,=myVar1; Load the address of _myVar
    ldr r1,=0x87654321
    str r1,[r0]
    bx  lr

which would get translated into:
    ldr r0,dat1
    ldr r1,dat2
    str r1,[r0]
    ldr r0,dat3
    ldr r1,dat4
    str r1,[r0]
    bx  lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678

or perhaps even something like:
    mar  r0,dat1
    ldrm r0,[r1,r2,r3,r4]
    str r2,[r1]
    str r4,[r3]
    bx  lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678

Notez que _myVar et 0x12345678 peuvent être placés immédiatement après le code de la routine dans lequel ils apparaissent; si vous essayez de déterminer la longueur de la routine en utilisant une étiquette qui suit la dernière instruction, une telle longueur ne parviendra pas à inclure les données supplémentaires.

Une chose à prendre note avec l'ARM est que pour des raisons historiques, les adresses de code ont souvent leur moins bit significatif, même si le code commence réellement sur les limites demi-mot. Ainsi, une instruction dont l'adresse est 0x12345679 occupera deux ou quatre octets à partir de 0x12345678. Cela peut compliquer le calcul d'adresse pour des choses comme memcpy.

Ma recommandation serait d'écrire une petite routine en langage assembleur pour faire ce que vous avez besoin. Il est seulement quelques instructions, vous pouvez savoir exactement ce que fait le code et quelle adresse les dépendances qu'il pourrait avoir, et vous ne serez pas à vous soucier de futures versions du compilateur changer votre code de telle façon que de casser quelque chose [par exemple la troisième version du code ci-dessus aurait pas de problème, même si dat1 a atterri sur une limite de demi-mot étrange puisque l'instruction LDR M3 peut gérer unaligned lit, mais le quatrième (un peu plus rapide et plus compact) version à l'aide LDRM échouerait dans ce cas; même si la version actuelle d'un compilateur utilise quatre instructions LDR, une version future pourrait utiliser LDRM].

Avec le compilateur IAR (je sais que votre question porte sur Keil mais je ne l'ai pas jouer avec), vous pouvez marquer soit l'ensemble du projet ou un fichier individuel pour être « indépendant de position ». De l'aide dans le passé avec d'autres processeurs, cela signifie que vous pouvez le déplacer « partout » et il sera toujours ok de travail

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top