Montag, Mai 25, 2020

Wie führe ich eine Funktion aus dem RAM auf einem Cortex-M3 (STM32)?

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

Was ich versucht habe ist dieser: Kopiere die Funktion in ein byte-array im RAM mit memcpy (überprüfung, dass es korrekt ausgerichtet), die Einstellung der Funktion-Zeiger auf den byte array ein, dann das aufrufen der Funktion(pointer).

Dies funktioniert gut für vielleicht 10 Anleitungen (die ich Folgen kann die Ausführung mit dem debugger), aber dann bekomme ich eine buss-Fehler und der Prozessor wird zurückgesetzt. Die buss-Fehler tritt auf den zweiten Durchgang durch eine Schleife, so dass der code sollte in Ordnung sein (da es den ersten pass). Ich denke, dass die schnelleren RAM-Zugriff mucks bis der buss timing in gewisser Weise…

Jedenfalls gibt es einen richtigen Weg, dies zu tun? Wie wäre es mit einer scatter-Datei so Aussehen, dass Orte, die eine Funktion im RAM automatisch (ich verwende Keil uVision für Cortex-M3)?

Edit: Mehr info:
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

Den IMPRECISERR bit gesetzt ist, in der buss-Fehler registrieren, wenn Sie die reset passiert.

  • Ähmm ich denke, Sie sollten mehr oder weniger post, die der Hersteller dem forum, wie Sie mit Hilfe einer bestimmten hardware-Komponente, dennoch kann man mehr details, welchen compiler benutzt du, wie sind Sie Debuggen, alle code-Beispiele, vielleicht einer person, die wissen könnte in der Lage sein, diese zu beantworten, als die anderen….
  • Aber ich mag Sie Jungs mehr!
InformationsquelleAutor c0m4 | 2010-06-15

4 Kommentare

  1. 7

    Den crash auf loop-iteration ist wahrscheinlich, weil die Funktion Verzweigung in eine absolute Adresse und nicht bezogen auf die neue Funktion Speicherort im RAM. Würde auf den ursprünglichen code Lage an diesem Punkt die Ursache bus-Fehler, da der flash erase operation?

    Ich glaube, Sie können markieren Sie eine Funktion kompiliert werden und in den RAM kopiert, richtig mit CARM durch anfügen der __ram Richtlinie zur definition der Funktion. Für Anleitung, wie Sie das gleiche zu tun mit den RealView-compiler finden Sie in der AUSFÜHRUNG VON FUNKTIONEN IM RAM technische support-Artikel:

    µVision ermöglicht es Ihnen, zu lokalisieren Module
    auf bestimmte Speicherbereiche sind
    im dialog eingetragen Projekt –
    Optionen – Ziel
    . So zu tun, richtig
    klicken Sie auf eine source-Datei (oder Datei-Gruppe)
    und öffnen Sie den dialog Optionen –
    Eigenschaften
    . Dann wählen Sie den Speicher,
    Regionen unter der Zuordnung von Speicher.

    Es ist ein Beispiel im Ordner ARMExamplesRAM_Function.

    Sollte generieren startup-code zu kümmern kopieren Sie die Funktion RAM und die Verknüpfung Aufrufe, die Lage richtig. Ansonsten, wenn Sie brauchen, um dynamisch kopieren von beliebigen Funktionen an RAM, dann schauen Sie in die Kompilierung position independent code (PIC) mit RealView.

    • Ausgezeichnete Antwort!
    • Ich habe das gleiche problem, außer dass ich bin nicht mit RTX oder irgendwelche Bibliotheken also ich weiß nicht der compiler code, der automatisch lädt, RAM-Funktionen in den Arbeitsspeicher. Ich hätte gerne einen laden, der region oder der Ausführung region im RAM, wo mein code wird tatsächlich verknüpft werden, aber ich brauche die JTAG-programmer zu laden, den code in eine andere Adresse (in flash). Im Idealfall in der .sct-Datei (ich verwende Keil MDK), würde ich einen Abschnitt, wo ich angeben, die Speicherung und Verknüpfung Adresse. Aber ich habe nicht herausgefunden, wie man das doch machen.
    • Möchten Sie vielleicht zu prüfen, öffnen Sie eine neue Frage mit Ihren Besonderheiten. Allerdings glaube ich, dass die Lösung oben gilt Ihre Lage als gut.
  2. 2

    Ohne zu wissen, mehr über Ihre situation, kann ich nur empfehlen, ein paar Allgemeine Dinge… stellen Sie sicher, Sie haben einen gültigen stack für diese Funktion (oder vermeiden Sie alle stack-Operationen in der Funktion), dass deine interrupts deaktiviert sind, und dass alle Vektoren in der system-Vektor-Tabelle zeigen Sie nicht, um code, der geht Weg, wenn Sie erase flash. Schließlich, stellen Sie sicher, Ihre Funktion ist verbunden laufen an die Adresse, die Sie setzen es… der code darf nicht verschiebbar und kann springen zu einer Stelle in alt-Lage.

  3. 2

    Weil der ARM hat eine begrenzte Fähigkeit, zu laden, sofortige Daten, Programme, das generieren von code für die ARM-Häufig Gegenüberstellung von code und Daten. Zum Beispiel, eine Aussage wie

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

    könnte am Ende so etwas 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 abgelegt werden darf, sofort nach dem code für die routine, in der Sie angezeigt, wenn Sie versuchen, um zu bestimmen, die Länge der routine mit einem label, das folgt die Letzte Anweisung, eine solche Länge nicht enthalten die zusätzlichen Daten.

    Eine weitere Sache zu beachten, der ARM ist, dass aus historischen Gründen, code-Adressen haben oft Ihre “ least significant bit gesetzt ist, obwohl der code eigentlich beginnt auf Halbwort-Grenzen. So, eine Instruktion, deren Adresse ist 0x12345679 belegen entweder zwei oder vier bytes, beginnend bei 0x12345678. Dies kann erschweren Adresse Berechnungen für Dinge wie memcpy.

    Meine Empfehlung wäre zu schreiben Sie eine kleine routine, in Assembler 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 haben könnten, und Sie nicht haben, um sorgen über zukünftige compiler Versionen ändern Sie den code in einer solchen Weise, als etwas kaputt zu machen [z.B. die Dritte version der obige code würde kein problem haben, auch wenn dat1 landete auf einer ungeraden halfword Grenze, da der M3 ist LDR-Anweisung verarbeiten kann, nicht liest, aber die vierte (etwas kompakter und schneller) version mit LDRM scheitern würde in einem solchen Fall; auch wenn heute die version eines Compilers verwendet vier LDR-Anweisungen, eine zukünftige version verwenden könnte LDRM].

  4. 1

    Mit dem IAR-compiler (ich weiß, Ihre Frage ist über Keil aber ich habe es nicht zum spielen) Sie können markieren Sie entweder das gesamte Projekt oder eine einzelne Datei sein, „position independent“. Mit dieser in der Vergangenheit mit anderen Prozessoren es heißt, Sie können verschieben Sie es „irgendwo“ und es wird immer noch funktionieren ok

Kostenlose Online-Tests