2013-06-12 4 views
6

Ich betreibe Linux Kernel 3.3 auf Xilinx Microblaze mit voller MMU. Die Aufgabe, die ich tue, verlangt von mir Folgendes: Ich muss eine Textdatei (Puffer) erstellen und die physikalische Adresse dieses Puffers lokalisieren, und ich möchte nicht, dass der Kernel diese Datei in diskontinuierliche Bereiche des Speichers schreibt.bekomme die physikalische Adresse eines Puffers unter Linux

der Grund, warum ich das brauche, weil ich eine DMA-Engine habe, die Daten von einer voreingestellten physikalischen Speicheradresse streamt, also muss ich Linux erzwingen, um die Pufferdatei an genau diesem Speicherort zu erstellen, so dass ich Daten in diese schreiben Datei ihre sofort durch die DMA-Maschine auf eine andere Hardware-Kern übertragen

Weitere Einzelheiten:.

mein System hat ein 512 MB DDR3 RAM mit dem System verbunden über „Multi-Port-Speicher-Controller‚Xilinx (MPMC) die Basisadresse von diesem Speichercontroller ist 0x90000000, alle Einheiten im Systemzugriffsspeicher über diesen Controller, einschließlich MicroBlaze, Die DMA-Einheit, die ich eine spezielle Schnittstelle namens Native Perso verwendet nality Interface (NPI), um mit dem Speicher auf einem sehr niedrigen Niveau zu kommunizieren, was zu einer sehr hohen Geschwindigkeit führt.

Diese NPI-DMA-Einheit wurde ursprünglich für die Verwendung unter einem sehr einfachen eingebetteten Kernel namens "xilkernel" entwickelt, der keinen virtuellen Speicher unterstützte, weder MMU noch MicroBlaze, sodass der Programmierer sehen konnte, wo sich der Betriebssystemcode befindet Wählen Sie eine physikalische Speicheradresse wie 0x91800000 als Quelladresse aus, von der DMA streamen wird, dann kann der Programmierer eine Datei unter dieser genauen Adresse ablegen und das System ausführen, wenn wir das Projekt für die Verwendung von Linux migrieren mussten xilkernel Wir sind auf dieses Problem gestoßen, ich habe Dateien auf einem externen Speichergerät, auf das ich als Blockgerät von Linux zugreifen kann und ich muss jede Datei in den Hauptspeicher (DDR3 RAM) verschieben und den DMA die Datei streamen lassen. derzeit die DMA-Streams von einer festen Adresse, aber ich kann es generisch, wenn nötig.

+2

Werfen Sie einen Blick auf dieses PDF eines Kapitels, das erklärt, wie der Linux-Kernel virtuellen und physischen Speicher verwaltet. Es enthält Beispiele zum Zuordnen und Anordnen von physischem Speicher für verschiedene Szenarien. http://lwn.net/images/pdf/LDD3/ch15.pdf –

+1

@bromanous Haben Sie dieses Gerät selbst entwickelt oder handelt es sich um einen IP-Kern eines Drittanbieters, den Sie nicht ändern können? Wenn Sie es ändern können, dann empfehle ich dringend, dass Sie die DMA-Adress-Software so konfigurierbar machen, dass Sie die Standard-DMA-Funktionen nutzen können, von denen tian_yufen spricht. –

+0

@BenjaminLeinweber, ja, ich habe den Quellcode für den DMA-Kern und ich kann die Adresse, von der DMA streamt, konfigurieren und zu einem generischen Parameter machen. – bromanous

Antwort

5

Um die Puffer für die Schnittstelle zum DMA-Controller zu verwalten, gibt es bestimmte Funktionen. Diese Funktionen kümmern sich nicht nur um die Adressumsetzung, sondern auch um die Cache-Kohärenz mit dem Speicher, beispielsweise Cache-Flush (Schreiben von Daten in den Speicher vor dem Senden) und Cache-Invalidieren (den Cache vor dem Empfangen ungültig machen).

(1) einen Puffer zu reservieren, erhalten sowohl die virtuelle Adresse und die physische Adresse:

void *dma_alloc_coherent(struct device *dev, size_t size, 
         dma_addr_t *dma_handle, gfp_t flag) 

der Rückgabewert der Funktion ist die virtuelle Adresse des zugewiesenen Puffer, während der dma_handle Zeiger die physische spart Adresse des zugewiesenen Puffers.

(2) ein Puffer zum Gerät zugeordnet geben müssen:

dma_addr_t dma_map_single(struct device *dev, void *ptr, 
          size_t size, 
          enum dma_data_direction dir) 

Der Rückgabewert physikalische Adresse des Puffers ist, und Parameter dir ist DMA_TO_DEVICE, PTR ist die virtuelle Adresse des Puffers;

(3) Für den Empfang eines Puffers von Gerät:

void dma_unmap_single(struct device *dev, dma_addr_t addr, 
          size_t size, 
          enum dma_data_direction dir) 

Der Parameter DIR ist DMA_FROM_DEVICE.

Hinweis: Um die drei Funktionen im Zusammenhang mit dma zu verwenden, sollte man ein Gerät an einen bestimmten Bus mit dma_map_ops registrieren, sonst können diese drei Funktionen nicht verwendet werden.

+2

Dies beantwortet die Frage des OP nicht. Das OP möchte einen DMA-Puffer an einem festen Ort im Speicher erzeugen. Keine dieser APIs ist dazu in der Lage. –

4

Ich brauche Linux zu zwingen, die Pufferdatei genau in diesem Speicherplatz

Dies ist nicht möglich zu erstellen. (Eigentlich haben Sie eine XY-Frage erstellt.)

Da Sie Hardware haben, "Streams Daten von einem voreingestellten physischen Speicheradresse", dann müssen Sie sicherstellen, dass der Linux-Kernel diese Speicherregion nicht als Teil verwendet sein Speicherpool. Sie müssen den Kernel informieren, wenn er startet, um diesen Speicherbereich nicht zu verwenden. Sie können keine Puffer in diesem bestimmten physischen Speicherbereich "zurückgewinnen" oder zuordnen, sobald er Teil des vom Kernel gesteuerten Speicherplatzes wird.

Die allgemeinste Methode, eine Speicherregion auszuschließen, ist die Verwendung des Parameters memmap= in der Kernel-Befehlszeile.

memmap=nn[KMG]$ss[KMG] 
     [KNL,ACPI] Mark specific memory as reserved. 
     Region of memory to be used, from ss to ss+nn. 
     Example: Exclude memory from 0x18690000-0x1869ffff 
       memmap=64K$0x18690000 
       or 
       memmap=0x10000$0x18690000 

Einige Architekturen wie ARM mit seinem ATAGs, haben andere weniger sichtbar und sicherere Methoden der Regionen des physischen Speichers zu reservieren.

Irgendwie müssen Sie dann die Adresse und Größe dieses Speicherbereichs dem Gerätetreiber angeben. Dies kann durch syntaktische Analyse der Befehlszeile erreicht werden, oder (nach unten) unter Verwendung von #define s fest codiert.

Der Treiber sollte die Verwendung des Speicherbereichs durch Aufruf von request_mem_region() deklarieren.
Der Treiber kann diesen Speicherbereich in virtuellen Adressraum abbilden, indem er ioreamp() aufruft.

Da der Treiber zur Verfügung gestellt wird oder die physikalische Adresse bereits kennt, ist das erledigt. Da der physische Speicher zugewiesen wurde, ist der Speicher daher zusammenhängend. Sie müssen die MMU konfigurieren, um das Zwischenspeichern für diesen Speicherbereich zu deaktivieren. Der Speicherbereich ist dann "DMAable".

+2

+1 für die direkte Antwort auf die Frage. Eine andere ähnliche Methode besteht darin, dass das Gerät den oberen Speicherbereich verwendet und Linux mitteilt, dass weniger Arbeitsspeicher zur Verfügung steht als dort, wo der mem = boot-Parameter verwendet wird. Wenn Sie beispielsweise 64 MB Arbeitsspeicher haben, können Sie mem = 63M übergeben, um eine Meg für Ihr Gerät ab 0x3F00000 zu reservieren. –

+0

@sawdust Ich habe nicht verstanden, wie man "Sie müssen die MMU konfigurieren, um die Zwischenspeicherung auf dieser Speicherregion zu deaktivieren", schaute ich MicroBlaze anpassbare Parameter und diese Option war nicht da. Ist Memmap nicht ausreichend? – bromanous

+1

@bromanous - Ich habe das als Nachtrag für die Vollständigkeit aufgenommen. Sie müssen wahrscheinlich nichts explizit machen. Hoffentlich werden die 'memmap =' Spezifikation und der Aufruf von 'ioremap()' für Ihr arch/board/proc die richtigen Attribute für diesen Speicherbereich einstellen. – sawdust

Verwandte Themen