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 (genannt NVIC), 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 möglich ist, für jede Art von Interrupt eine Callback-Funktion anzuhängen, und ich vermute, dass die an jedem Interrupt angehängte Adresse mit der Adresse des Callbacks zusammenhängt.
Was genau ist die Adresse, die an einen bestimmten Interrupt angehängt ist? Wie kann ich (sagen wir in C) die Callback-Funktion für einen bestimmten Interrupt definieren?
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 im Programmspeicher an einer vordefinierten Stelle gespeichert. Wenn ein Interrupt auftritt, weiß der Prozessor, wo in der Tabelle der Eintrag dieses Interrupts ist, greift ihn und verzweigt zu der dort gespeicherten Adresse.
Wie füllt man diese Tabelle? Normalerweise sind alle diese Informationen in einer Startdatei enthalten. Normalerweise definieren Sie einfach ein konstantes Array von Zeigern und füllen es mit den Adressen der Callbacks, die Sie verwenden möchten. Hier ist eine Website, die beschreibt, wie man eine Startdatei für einen bestimmten ARM-Mikrocontroller erstellt. Das Knifflige daran ist, dass fast alle Einzelheiten zum Erstellen der Datei stark von dem verwendeten Linker, Compiler und Chip abhängen, sodass Sie entweder ein Beispiel finden oder Ihr eigenes erstellen müssen.
der cortex-m3 ist sehr unterbrechungsfreundlich. Sie brauchen kein Trampolin in asm oder müssen eine nicht standardmäßige Compiler-Syntax hinzufügen, damit der Compiler dies für Sie erledigt. Die Hardware passt sich einem abi an, indem sie eine bestimmte Anzahl von Registern für Sie beibehält und den Modus ändert. Das Verknüpfungsregister 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. All die Dinge, die Sie an einem Arm und vielen anderen Prozessoren tun mussten, müssen Sie also nicht tun.
Ebenso haben der Cortex-m (und andere neuere Arme) bis zu einem gewissen Schmerzniveau eine Zillion Vektoren in der Vektortabelle, Dutzende bis Hunderte von Unterbrechungen usw., wie in einem Kommentar oben erwähnt, siehe http://github.com/ dwelch67/stm32f4d Das blinker05-Beispiel verwendet Interrupts mit einem Timer. Sie können in vectors.s sehen, dass Sie lediglich den Namen der Funktion eingeben:
.word hang
.word tim5_handler
.word hang
Und dann schreiben Sie den C-Code:
//-------------------------------------------------------------------
volatile unsigned int intcounter;
//-------------------------------------------------------------------
// CAREFUL, THIS IS AN INTERRUPT HANDLER
void tim5_handler ( void )
{
intcounter++;
PUT32(TIM5BASE+0x10,0x00000000);
}
// CAREFUL, THIS IS AN INTERRUPT HANDLER
//------------------------------------------------------------------
Wie bei jedem Interrupt von einem Peripheriegerät/Gerät müssen Sie jetzt wahrscheinlich im Handler dem Gerät sagen, dass es den Interrupt löschen soll, sonst könnten Sie beim ständigen erneuten Betreten des Handlers hängen bleiben.
Meine Beispiele verwenden keine IDE, sie verwenden Open-Source-Tools (gnu gcc und binutils und den Clang-Compiler von llvm). Entfernen Sie die Clang-Binärdateien aus der all:-Zeile im Makefile, wenn Sie llvm nicht verwenden/verwenden möchten. Die GNU-Tools sind leicht zu bekommen, sowohl aus Quellen zu bauen (ich habe Anweisungen irgendwo bei github, wahrscheinlich an einigen Stellen) oder einfach die Lite-Version von Codesourcery (jetzt Mentor-Grafiken) zu bekommen. Meine Beispiele wurden unter Linux entwickelt und getestet, aber das sollte Windows-Benutzer nicht davon abhalten, ein paar Dinge wie rm -f *.o in del *.o oder ähnliches zu ändern oder einfach eine Batch-Datei aus den Assembler-/Compiler-/Linker-Befehlen zu erstellen im Makefile.
Ich empfehle dringend, Ihre Binärdatei zu zerlegen, insbesondere wenn Sie versuchen, einen Handler in die Vektortabelle zu platzieren. Bei so vielen ist es leicht, sich zu verzählen und ihn nicht an der richtigen Adresse zu haben. Sie müssen die Adresse aus den Armdokumenten kennen und dann die Demontage überprüfen. das blinker05 Beispiel im zerlegten Zustand:
8000100: 0800014f stmdaeq r0, {r0, r1, r2, r3, r6, r8}
8000104: 0800014f stmdaeq r0, {r0, r1, r2, r3, r6, r8}
8000108: 08000179 stmdaeq r0, {r0, r3, r4, r5, r6, r8}
800010c: 0800014f stmdaeq r0, {r0, r1, r2, r3, r6, r8}
8000110: 0800014f stmdaeq r0, {r0, r1, r2, r3, r6, r8}
Offset 0x108 ist der gezielte Eintrag. Beachten Sie, dass die Adressen in der Tabelle ungerade sein sollten. 0x178 ist die tatsächliche Adresse. Arm möchte, dass das lsbit gesetzt ist, um anzuzeigen, dass es sich um eine Thumb-Befehlssatzadresse handelt (der Cortex-m3 kennt nur Thumb und die Thumb2-Erweiterungen, er kann keine Arm-Anweisungen ausführen).
Nur Jeff
Zufallsblau
Nur Jeff
WütendEE
Nur Jeff
Oldtimer