Ich arbeite mit einem ARM Cortex M4-Mikrocontroller mit DMA oder peripherem DMA-Controller. Eine Anforderung des DMA besteht darin, dass er nicht auf Zeiger auf Adressen zugreifen kann, die in Flash vorhanden sind, sondern nur auf Zeiger auf Adressen, die sich im RAM befinden. Gibt es eine Möglichkeit festzustellen, ob ein bestimmter Zeiger auf Flash oder RAM zeigt?
Wenn nicht, muss ich einen Puffer im RAM initialisieren und dann strcpy oder ähnliches, um das, was sich im Flash befindet, in den RAM zu übertragen, damit der DMA es lesen kann. Kennt jemand einen besseren Weg, um keine CPU-Zeit zu verschwenden, wenn nicht festgestellt werden kann, ob der Zeiger auf Flash oder RAM zeigt?
Dies ist auf einem Atmel SAM4S.
microcontroller
memory
dma
Pugz
quelle
quelle
Antworten:
Sie kennen die Speicherzuordnung Ihres Mikrocontrollers, sodass Sie Ihren Zeiger einfach anhand der Start- und End-RAM-Adressen testen können. In den meisten Fällen stellt Ihr Linkerscript diese Adressen bereit, sodass Sie sie nicht selbst eingeben müssen (Details hängen von Ihrem Linkerscript ab). Beachten Sie, dass bei Verwendung des Linkerskripts die Werte zum Zeitpunkt der Kompilierung nicht bekannt sind, sodass der Compiler die Vergleiche mit bekannten Zeigern nicht optimieren kann.
quelle
Das Hauptproblem bei der Überprüfung, ob sich ein Zeiger in einem bestimmten Bereich befindet, ist leider der C-Standard selbst. Zeigerarithmetik hat nur dann ein definiertes Verhalten , wenn sie an Zeigern desselben Typs innerhalb des Speicherbereichs desselben Objekts (dh innerhalb desselben zugewiesenen Arraybereichs) ausgeführt wird. Wenn die Vergleichsoperatoren als arithmetische Operationen definiert sind, gilt diese Einschränkung auch für sie. Eine Problemumgehung für dieses Problem wäre das Umwandeln der Zeiger in den in
uintptr_t
definierten Typ, beistdint.h
dem es sich um einen ganzzahligen Typ handelt, der garantiert einen Zeigerwert enthält. Und dann führen Sie Ihre Vergleiche durch.Nun zum Teil, die richtigen Grenzen zu erreichen. Normalerweise enthält ein C-Projekt eine Art Linker-Skript, das Speicherbereiche der spezifischen Architektur definiert. Im Allgemeinen enthält es Zeilen ähnlich den folgenden:
Im selben Skript können dann die folgenden Definitionen hinzugefügt werden:
Und dann können Sie im C-Code auf diese Symbole zugreifen, indem Sie:
Und dann ein kniffliger Teil: Die Adresse von
_flash_start
entspricht der Flash-Startadresse, und die Adresse von_flash_end
entspricht der Flash-Endadresse. Dh die&_flash_start
und&_flash_end
geben Ihnen die gewünschte Reichweite.quelle
Wenn Ihre MCU den ARM Cortex-Konventionen entspricht, können Sie sich das oberste Halbbyte der betreffenden Adresse ansehen:
quelle
0x10000000
-0x2fffffff
oder anders gesagt, jede Adresse, die mit knabbern1
oder beginnt2
.Sie können den Zeiger auf eine Ganzzahl umwandeln und dann seinen Wert mit dem Flash-Adressraum vergleichen, der in der Speicherzuordnung Ihrer MCU definiert ist. Wenn sich Ihr Flash-Speicher beispielsweise unter den Adressen 0x10000000 - 0x1001ffff befindet, können Sie Folgendes tun:
Natürlich ist es im eigentlichen Code besser, Konstanten anstelle von fest codierten Adressen zu verwenden - beispielsweise FLASH_START_ADDR und FLASH_END_ADDR. Wenn Sie besonders flexibel sein möchten, können Sie Linkervariablen für die Flash-Adressen definieren, wodurch die Adressen nicht in Ihrem Quellcode enthalten sind.
quelle