Ich hoffe, mein Titel ist terminologisch korrekt. Ich arbeite (lerne) mit dem STM32F4 Discovery Board, auf dem sich ein STM32F407VGTx-Mikrocontroller befindet. Ich versuche wirklich, die Antworten im Referenzhandbuch zu finden , aber manchmal ist es wirklich schwer zu finden, wo ich suchen soll. Vielleicht liegt es daran, dass es über 1700 Seiten lang ist ...
Also, hier die Situation, während meiner Tests (C-Code, Compiler ist arm-none-eabi-size), habe ich festgestellt, dass ich jeden Wert in Peripherieregister schreiben kann, zum Beispiel in GPIOD-Register. Aber wenn ich denselben Code verwende (um an eine Adresse zu schreiben), kann ich beispielsweise nicht an die Adresse 0x58 (tatsächlich 0x00000058) schreiben. Im Falle von peripheren Registern gibt das Dokument eindeutig an, welche Register/Bits schreibgeschützt sind und welche schreibgeschützt sind, mit Notationen wie „r“, „rw“. Für die Adresse 0x58 konnte ich jedoch den Grund nicht finden, warum ich nicht darauf schreiben kann.
Jede Anleitung oder Erklärung wäre willkommen, danke.
aktualisieren:
Gegenfrage: Warum sollten Sie an diese Adresse schreiben können? Ist dem etwas zugeordnet? – Markus Müller
Okay, es ist ein bisschen interessant. Ich habe gerade angefangen, etwas über externe Interrupts zu lernen, und ich möchte während meines Lernens alles (also einschließlich externer Interrupts) auf Registerebene tun. Deshalb habe ich keine Funktionen von HAL, SPL oder CMSIS verwendet und auch keine dieser Dateien ist im Projektverzeichnis vorhanden. Ich habe es irgendwie geschafft, also hatte ich das EXTI-Pending-Register korrekt gestartet, aber ich konnte keine Möglichkeit finden, eine Callback-Funktion mit dem Interrupt zu verknüpfen, die den Prozess definiert, der im Falle des Interrupts ausgeführt werden soll. Die Untersuchung der NVIC-Tabelle (Seite 372) aus dem Referenzhandbuch ergab, dass jeder Interrupt mit einer Speicheradresse in der letzten Spalte verbunden ist. Also dachte ich, vielleicht nur eine Idee, diese Orte enthalten die Speicheradresse (Zeiger) zu den Interrupt-Handler-Funktionen. So, Ich dachte dann daran, eine Funktion zu definieren und dann die Adresse dieser Funktion in den Speicherplatz 0x58 zu schreiben. Wenn also der Interrupt kommt, schaut der Mikrocontroller auf 0x58, was ihn an die Stelle der interessierenden Funktion umleitet.
Ja, dieses Update hätte eine ganz andere Frage für sich sein können. Entschuldigung für das Chaos. Ich denke, die Frage kann ohne diese Geschichte beantwortet werden, aber ein Kommentar hat mich dazu veranlasst, dies auch anzuhängen ...
Sie müssen sich die Speicherkonfiguration des Prozessors ansehen. Der Cortex-M4 implementiert die ARMv7-M-Architektur. Hier ist ein Schnappschuss der oberen Hälfte der Speicherkarte (ärgerlicherweise ist diese im Referenzhandbuch des M4 auf zwei Seiten aufgeteilt ).
Wie Sie sehen können, 0x00000000 - 0x1FFFFFFF
ist der Bereich zugewiesen Code
. Die STM-Implementierung enthält keinen zugänglichen Pfad auf dem System-AHB-Bus zu diesem Bereich, daher können Sie nicht an diese Adresse schreiben.
Eventuell wird die Vektortabelle verschoben ; Es gibt ein Register, das die "0"-Adresse dieser Tabelle speichert und das angepasst werden kann. Das ist eigentlich ein ziemlich praktisches Feature: Es ermöglicht Ihnen, eine Interrupt-Handler-Tabelle irgendwo im RAM einzurichten, und dann mit einem Schreibvorgang VTOR
(der sich bei Adresse 0x08 befindet, glaube ich) zu dieser neuen Tabelle umzuschalten.
Siehe Seite 218 des stm32f4-Programmierhandbuchs .
0x00000058
und seine Umgebung darf ich nicht ändern, sagen wir, 0x50000000
die Adresse ist in Ordnung, damit zu arbeiten. Dann schreibe ich 0x50000000
an VTOR
. Jetzt beginnt die NVIC-Tabelle mit dieser Adresse. Wenn ich dann die Adresse meiner Interrupt-Handler-Funktion an schreibe, 0x50000058
würde ich erreichen, was ich beabsichtigt habe? Ich werde es jetzt versuchen und warte in der Zwischenzeit auf Ihren Kommentar. Danke für die Antwort btw.Also dachte ich, vielleicht nur eine Idee, diese Orte enthalten die Speicheradresse (Zeiger) zu den Interrupt-Handler-Funktionen.
So funktioniert das. Es gibt auch VTOR, wie Marcus es beschrieben hat. Einfache Projekte verwenden jedoch eine sogenannte Start-Assembler-Datei, startup.s
in der normalerweise der Stapel, der Heap und die Vektortabelle an ihrer Position abgelegt werden.
Die Vektortabelle in startup.s
ist schwach mit einem Standardhandler verknüpft, der nichts tut.
Wenn Sie an anderer Stelle eine Funktion mit genau demselben Namen definieren, überschreibt sie diese Standardeinstellung.
Dabei spielt es für den Cortex M4 noch keine Rolle, dass Ihr Chip von ST ist.
Ich weiß nicht, welchen Compiler Sie verwenden, aber hier ist eine ausführliche Beschreibung der Startdatei von ARM: https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/ posts/decodierung-der-startdatei-für-arm-cortex-m4
Diese Adresse ist Programm-Flash. Wenn Sie in Flash schreiben möchten, ist es möglich, Sie müssen es zuerst mit dem Flash-Peripheriegerät löschen, und Sie können das Programm, das Sie ausführen, nicht wirklich löschen, also tun Sie das nicht. Es gibt zwei Möglichkeiten, dies richtig zu machen. Sie können die Vektortabelle in den SRAM kopieren und das NVIC anweisen, auf die Vektortabelle im SRAM zu zeigen, sodass Sie den Vektor frei ändern können. Eine häufigere Lösung wäre die Verwendung eines festen Interrupt-Codes, der eine Adresse von einer Variablen nimmt und zu dieser Adresse springt, sodass Sie einfach ändern können, wohin die Variable zeigt.
Markus Müller
Mujustan
Markus Müller
Mujustan