2013-06-12 18 views
6

Sto eseguendo il kernel Linux 3.3 su Microblaze di Xilinx con MMU completo. il compito che sto facendo richiede che io sappia quanto segue: Ho bisogno di creare un file di testo (buffer) e localizzare l'indirizzo fisico di questo buffer e non voglio che il kernel scriva questo file in regioni di memoria discontinue.ottiene l'indirizzo fisico di un buffer sotto Linux

la ragione per cui ho bisogno di questo perché ho un motore DMA che flussi di dati da un indirizzo di memoria fisica di preselezione, quindi ho bisogno di forzare Linux per creare il file di buffer in quella posizione di memoria esatta, in modo che quando scrivo i dati in questo File sua immediatamente trasmessa dal motore DMA ad un altro nucleo Hardware

Maggiori dettagli:.

mio sistema ha un MB di RAM DDR3 512 collegato al sistema tramite "multiregolatore memoria porta Xilinx'(MPMC) l'indirizzo di base di questo controller di memoria è 0x90000000, tutte le unità nella memoria di accesso del sistema attraverso questo controller, incluso MicroBlaze, l'unità DMA che ho utilizza un'interfaccia speciale chiamata Native Perso nality Interface (NPI) per comunicare con la memoria ad un livello molto basso, risultando così una prestazione ad altissima velocità.

Questa unità DMA NPI è stata originariamente progettata per essere utilizzata in un kernel embedded di base chiamato "xilkernel" che non supportava la memoria virtuale, né MMU faceva parte di MicroBlaze, quindi il programmatore poteva vedere dove risiederà il codice OS e seleziona un indirizzo di memoria fisico come 0x91800000 come indirizzo sorgente da cui verrà eseguito lo streaming DMA, quindi il programmatore può posizionare un file con quell'indirizzo esatto ed eseguire il sistema

quando è necessario migrare il progetto per utilizzare Linux invece di xilkernel ci siamo imbattuti in questo problema, ho dei file su un dispositivo di archiviazione esterno a cui posso accedere come dispositivo a blocchi da Linux e ho bisogno di spostare ciascun file nella memoria principale (RAM DDR3) e fare in modo che il DMA trasmetta il file in streaming. attualmente gli stream DMA da un indirizzo fisso ma posso renderlo generico se necessario.

+2

Dai un'occhiata a questo PDF di un capitolo che spiega come il kernel Linux gestisce la memoria virtuale e fisica. Fornisce esempi su come mappare e appuntare la memoria fisica per vari scenari. http://lwn.net/images/pdf/LDD3/ch15.pdf –

+1

@bromanous Hai sviluppato questo dispositivo da solo o è un core IP di terze parti che non puoi modificare? Se è possibile modificarlo, consiglio vivamente di configurare il software di indirizzi DMA in modo che sia possibile utilizzare le funzioni DMA standard di cui parla tian_yufen. –

+0

@BenjaminLeinweber, sì, ho il codice sorgente per il core DMA e posso configurare l'indirizzo da cui passa DMA e renderlo un parametro generico. – bromanous

risposta

5

Per gestire i buffer per l'interfaccia con il controller DMA, esistono funzioni specifiche. Queste funzioni si occupano non solo della traduzione degli indirizzi, ma anche della coerenza della cache con la memoria, ad esempio lo svuotamento della cache (scrivere i dati nella memoria prima dell'invio) e la cache invalidata (invalidare la cache prima di ricevere).

(1) Per allocare un buffer, ottenere sia l'indirizzo virtuale e l'indirizzo fisico:

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

il valore di ritorno della funzione è l'indirizzo virtuale del buffer allocato, mentre il puntatore dma_handle salva il fisico indirizzo del buffer assegnato.

(2) Per passare un buffer allocato al dispositivo:

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

Il valore di ritorno è l'indirizzo fisico del buffer, e il parametro dir è DMA_TO_DEVICE, ptr è l'indirizzo virtuale del buffer;

(3) Per ricevere un buffer dalla periferica:

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

Il parametro dir è DMA_FROM_DEVICE.

Nota: Per utilizzare le tre funzioni relative a dma, è necessario registrare un dispositivo su un bus specifico con dma_map_ops oppure non è possibile utilizzare queste tre funzioni.

+2

Questo non risponde alla domanda dell'OP. L'OP vuole creare un buffer dma in una posizione fissa in memoria. Nessuna di queste API è in grado di farlo. –

4

ho bisogno per forza di Linux per creare il file di buffer in quella posizione esatta di memoria

Questo non è possibile. (In realtà si è creato un domanda XY.)

Dal momento che si dispone di hardware che "flussi di dati provenienti da un indirizzo di memoria fisica preset", quindi è necessario assicurarsi che il kernel Linux non utilizza questa regione di memoria come parte di il suo pool di memoria. È necessario informare il kernel quando si avvia per non utilizzare questa area di memoria. Non sarà possibile "reclamare" o allocare i buffer in questa specifica area di memoria fisica una volta che diventa parte dello spazio di memoria controllato dal kernel.

Il metodo più generico per escludere un'area di memoria consiste nell'utilizzare il parametro memmap= nella riga di comando del kernel.

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 

Alcune architetture, come ARM con i suoi ATAGs, hanno altri metodi meno visibili e più sicure di riservare regioni di memoria fisica.

In qualche modo è quindi necessario fornire l'indirizzo e le dimensioni di questa regione di memoria al driver del dispositivo. Questo può essere ottenuto analizzando la riga di comando o (pollice giù) con hardcoded utilizzando #define s.

Il driver deve dichiarare l'utilizzo dell'area di memoria chiamando request_mem_region().
Il driver può mappare questa area di memoria nello spazio degli indirizzi virtuali chiamando ioreamp().

Poiché il driver è fornito o conosce già l'indirizzo fisico, è fatto. Poiché la memoria fisica è stata assegnata, la memoria è quindi contigua. Dovrai configurare la MMU per disabilitare il caching su questa area di memoria. La regione di memoria sarà quindi "DMAable".

+2

+1 per la risposta diretta alla domanda. Un altro metodo simile è quello di fare in modo che il dispositivo usi la parte superiore della memoria e dica a Linux che c'è meno memoria di quella che effettivamente usa il parametro mem = boot. Ad esempio, se hai 64 MB di memoria, puoi passare mem = 63M per riservare un meg per il dispositivo a partire da 0x3F00000. –

+0

@sawdust Non ho capito come "Dovrai configurare la MMU per disabilitare il caching su questa area di memoria", ho osservato i parametri regolabili di MicroBlaze e quell'opzione non c'era. Non è sufficiente impostare memmap? – bromanous

+1

@bromanous - L'ho incluso come ripensamento per completezza. Probabilmente non devi fare nulla di esplicito. Speriamo che la specifica 'memmap =' e la chiamata a 'ioremap()' per il tuo arch/board/proc configurerà gli attributi appropriati per quella regione di memoria. – sawdust