Ich arbeite mit einem STM32 und bin etwas verwirrt über Interrupts, insbesondere die Nested Vectored Interrupts (NVI). Soweit ich weiß , gibt es einen NVI- Vektor (NVIC genannt), bei dem jeder Interrupt eine Priorität (manchmal einstellbar) und eine Adresse hat (siehe Seite 157 des ARM-Referenzhandbuchs hier ).
Jetzt gehe ich davon aus, dass es für jede Art von Interrupt möglich ist, eine Rückruffunktion anzuhängen, und ich vermute, dass die an jeden Interrupt angehängte Adresse mit der Adresse des Rückrufs zusammenhängt.
Was genau ist die Adresse, die einem bestimmten Interrupt zugeordnet ist? Wie kann ich (beispielsweise in C) die Rückruffunktion für einen bestimmten Interrupt definieren?
arm
c
interrupts
stm32
Zufälliges Blau
quelle
quelle
Antworten:
Die ARMs implementieren eine Interrupt-Tabelle, um die Adresse für jeden Interrupt-Handler (oder Rückruf, im Grunde dasselbe) zu speichern. Grundsätzlich werden alle Adressen der Interrupt-Handler an einem vordefinierten Ort im Programmspeicher gespeichert. Wenn ein Interrupt auftritt, weiß der Prozessor, wo sich der Eintrag des Interrupts in der Tabelle befindet, greift danach und verzweigt zu der dort gespeicherten Adresse.
Wie füllen Sie diese Tabelle? Normalerweise sind alle diese Informationen in einer Startdatei enthalten. Normalerweise definieren Sie nur ein konstantes Array von Zeigern und füllen es mit den Adressen der Rückrufe, die Sie verwenden möchten. Auf dieser Website erfahren Sie, wie Sie eine Startdatei für einen bestimmten ARM-Mikrocontroller erstellen. Das Knifflige dabei ist, dass fast alle Einzelheiten der Erstellung der Datei stark von dem Linker, Compiler und Chip abhängen, den Sie verwenden. Sie müssen also entweder ein Beispiel finden oder Ihre eigenen durcheinander bringen.
quelle
Der Cortex-M3 ist sehr Interrupt-freundlich. Sie benötigen kein Trampolin in asm oder müssen eine nicht standardmäßige Compilersyntax hinzufügen, damit der Compiler dies für Sie erledigt. Die Hardware entspricht einem Abi, indem eine bestimmte Anzahl von Registern für Sie beibehalten und die Modi geändert werden. Das Verbindungsregister ist so codiert, dass die Hardware bei der Rückkehr von der Funktion weiß, dass es sich tatsächlich um eine Rückkehr vom Interrupt handelt. Also all die Dinge, die Sie an einem Arm und vielen anderen Prozessoren tun mussten, müssen Sie nicht tun.
Ebenso haben der Cortex-m (und andere neuere Arme) bis zu einem gewissen Schmerzniveau zig Vektoren in der Vektortabelle, Dutzende bis Hunderte von Interrupts usw., wie in einem Kommentar oben erwähnt, siehe http://github.com/ dwelch67 / stm32f4d Das Beispiel blinker05 verwendet Interrupts mit einem Timer. Sie können in vectors.s sehen, dass Sie nur den Namen der Funktion eingeben:
Und dann schreiben Sie den C-Code:
Wie bei jedem Interrupt von einem Peripheriegerät / Gerät müssen Sie das Gerät wahrscheinlich im Handler anweisen, den Interrupt zu löschen, da Sie sonst möglicherweise stecken bleiben und ständig in den Handler zurückkehren.
Meine Beispiele verwenden keine IDE, sondern Open-Source-Tools (gnu gcc und binutils sowie der clang-Compiler von llvm). Entfernen Sie die Clang-Binärdateien aus der Zeile all: im Makefile, wenn Sie llvm nicht verwenden möchten / möchten. Die Gnu-Tools sind leicht zu bekommen, sowohl aus Quellen (ich habe Anweisungen irgendwo bei Github, wahrscheinlich an mehreren Stellen) als auch einfach die Lite-Version von Codesourcery (jetzt Mentor-Grafiken). Meine Beispiele wurden unter Linux entwickelt und getestet, aber das sollte Windows-Benutzer nicht entmutigen, ein paar Dinge wie rm -f * .o in del * .o ändern, solche Dinge oder einfach eine Batch-Datei aus den Assembler / Compiler / Linker-Befehlen erstellen im Makefile.
Ich empfehle dringend, Ihre Binärdatei zu zerlegen, insbesondere wenn Sie versuchen, einen Handler in die Vektortabelle einzufügen. Bei so vielen ist es leicht, falsch zu zählen und nicht an der richtigen Adresse zu haben. Sie müssen die Adresse aus den Armdokumenten kennen und dann die Demontage überprüfen. Das Beispiel blinker05 bei Demontage:
Offset 0x108 ist der Zieleintrag. Beachten Sie, dass die Adressen in der Tabelle ungerade sein sollten. 0x178 ist die tatsächliche Adresse. Arm möchte, dass der lsbit-Satz anzeigt, dass es sich um eine Daumenanweisungssatzadresse handelt (der cortex-m3 kennt nur thumb und die thumb2-Erweiterungen, die er nicht ausführen kann).
quelle