Wie kann ich auf einem Cortex-M3 (STM32) eine Funktion aus dem RAM ausgeführt werden?

StackOverflow https://stackoverflow.com/questions/3044010

  •  27-09-2019
  •  | 
  •  

Frage

Ich versuche, eine Funktion von RAM auf einem Cortex-M3-Prozessor (STM32) auszuführen. Die Funktion löscht die und schreibt den internen Blitz, so dass ich muß auf jeden Fall in RAM sein, aber wie mache ich das?

Was habe ich versucht, ist dies: Kopieren Sie die Funktion auf ein Byte-Array im RAM Memcpy mit (Überprüfung, dass es richtig ausgerichtet wird), einen Funktionszeiger auf Punkt auf die Byte-Array-Einstellung ein dann die die Funktion (Zeiger) aufrufen.

Dies funktioniert gut für vielleicht 10 Anweisungen (I die Ausführung mit dem Debugger folgen kann), aber dann bekomme ich einen Fehler Buss und der Prozessor setzt. Der Buss Fehler tritt auf dem zweiten Durchlauf durch eine Schleife, so sollte der Code in Ordnung sein (wie es den ersten Durchlauf arbeitet). Ich denke, dass die schnelleren RAM-Zugriff mucks bis der Bus Timing in irgendeiner Weise ...

Auf jeden Fall ist es ein richtiger Weg, dies zu tun? Wie würde eine Scatter-Datei aussehen, die Orte eine Funktion im RAM automatisch (Ich bin mit Keil uVision für Cortex-M3)?

Edit: Weitere Informationen: Toolchain: Realview MDK-ARM V 4.10 Compiler: Armcc v4.0.0.728 Assembler: Armasm v4.0.0.728 Linker: ArmLink v4.0.0.728 Prozessor: STM32F103ZE

Das IMPRECISERR Bit im Buss Fehlerregister gesetzt, wenn die Reset geschieht.

War es hilfreich?

Lösung

Der Absturz bei Schleifeniterationslatenzzeit ist wahrscheinlich, weil die Funktion in eine absolute Adresse verzweigt und ist auf die neue Funktion Stelle im RAM nicht relativ. Würde die ursprüngliche Code Lage an diesem Punkt verursacht einen Bus Fehler beim Zugriff auf wegen der Flash-Löschoperation?

Ich glaube, dass Sie eine Funktion markieren können kompiliert und korrekt mit CARM kopiert werden in den RAM durch die __ram Richtlinie auf die Funktionsdefinition anhängen. Für Anleitung, wie man das gleiche zu tun mit den Realview-Compiler die EXECUTING FUNKTIONEN RAM technischer Support-Artikel:

  

µVision können Sie Module lokalisieren   auf bestimmte Speicherbereiche, die   im Dialog eingegeben Projekt -   Optionen - Ziel . Um dies zu tun, nicht wahr   klicken Sie auf eine Quelldatei (oder Dateigruppe)   und öffnen Sie den Dialog Optionen -   Eigenschaften . Wählen Sie dann den Speicher   Regionen unter Speicherbelegung .

     

Es gibt ein Beispiel in dem Ordner ARMExamplesRAM_Function .

Das sollte Startup-Code generieren zu kümmern, die Funktion des Kopierens auf RAM und Verknüpfung Anrufe an dieser Stelle richtig. Andernfalls, wenn Sie dynamisch Exemplares benötigen, beliebige Funktionen auf RAM, dann schauen Sie in die Erstellung Position unabhängigen Code (PIC) mit Realview.

Andere Tipps

Ohne mehr über Ihre Situation zu wissen, kann ich nur ein paar allgemeinen Dinge vorschlagen ... sicherstellen, dass Sie für diese Funktion einen gültigen Stapel (oder alle Stack-Operationen in der Funktion vermeiden), dass Ihre Interrupts deaktiviert sind, und dass jeder Vektoren im System Vektortabelle weisen nicht auf Code, der weggeht, wenn Sie Flash löschen. Schließlich, stellen Sie sicher, dass Ihre Funktion ist verknüpft an der Adresse laufen Sie es nennen ... der Code nicht versetzbar sein kann und auf einen Punkt springen kann in alten Standort ist.

Da die ARM hat eine begrenzte Fähigkeit, sofort Daten zu laden, Dienstprogramme, den Code für die ARM häufig juxtapose Code und Daten erzeugen. Zum Beispiel kann eine Anweisung wie

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

könnte sich als etwas enden wie:

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

Beachten Sie, dass _myVar und 0x12345678 sofort platziert werden kann nach dem Code für die Routine, in der sie erscheinen; wenn Sie versuchen, die Länge der Routine mit einem Etikett, um zu bestimmen, welche die letzte Anweisung folgt, wird eine solche Länge nicht die zusätzlichen Daten aufzunehmen.

Eine weitere Sache zu Notiz mit der ARM ist, dass aus historischen Gründen, Code-Adressen werden oft ihre niedrigstwertigen Bit gesetzt haben, obwohl Code tatsächlich beginnt, auf Halbwortgrenzen. Somit wird ein Befehl, deren Adresse 0x12345679 wird besetzen entweder zwei oder vier Bytes bei 0x12345678 starten. Dies kann Adressenberechnung für Dinge wie memcpy erschweren.

Meine Empfehlung wäre, eine kleine Routine in Assembler-Sprache zu schreiben, zu tun, was Sie brauchen. Es ist nur ein paar Anweisungen, können Sie genau wissen, was der Code tut und was Adresse Abhängigkeiten könnte es haben, und Sie müssen sich keine Sorgen machen über die zukünftigen Compiler-Versionen der Code in einer solchen Art und Weise zu brechen, etwas zu ändern [z die dritte Version des obigen Code würde kein Problem haben, auch wenn dat1 auf einer ungeraden Halbwortgrenze landete seit der LDR-Befehls des M3 liest unaligned umgehen kann, aber der vierte (etwas schneller und kompakter) Version LDRM Verwendung in einem solchen Fall scheitern würde; auch wenn die heutige Version eines Compilers vier LDR Anweisungen verwendet, kann eine zukünftige Version verwenden LDRM].

Mit dem IAR-Compiler (Ich weiß, dass Ihre Frage über Keil ist, aber ich habe es nicht mit spielen) können Sie entweder das gesamte Projekt oder eine einzelne Datei zu sein „Position unabhängig“ markieren. Von der Nutzung in der Vergangenheit mit anderen Prozessoren bedeutet es Sie es „überall“ bewegen können, und es wird immer noch funktioniert ok

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top