2013-06-12 27 views
6

Używam jądra Linux 3.3 na Xilinx's Microblaze z pełnym MMU. zadanie, które wykonuję, wymaga ode mnie zrozumienia: muszę utworzyć plik tekstowy (bufor) i zlokalizować fizyczny adres tego bufora i nie chcę, aby jądro zapisało ten plik w nieciągłych regionach pamięci.uzyskać fizyczny adres bufora pod Linuksem

Powód, dla którego potrzebuję tego, ponieważ mam silnik DMA, który przesyła dane ze wstępnie ustawionego adresu pamięci fizycznej, więc muszę wymusić na Linuxie utworzenie pliku bufora w tej dokładnej lokalizacji pamięci, tak aby podczas zapisywania danych do tego file jej natychmiast przekazywane przez silnik DMA do innego rdzenia Hardware

Więcej szczegółów:.

mój system ma 512 MB DDR3 RAM podłączony do systemu za pośrednictwem „kontroler Multi pamięci portu Xilinx” (MPMC) adres bazowy tego kontrolera pamięci to 0x90000000, wszystkie jednostki w systemie uzyskują dostęp do pamięci za pośrednictwem tego kontrolera, w tym MicroBlaze, jednostki DMA, której używam specjalnego interfejsu o nazwie Native Perso Nality Interface (NPI) do komunikacji z pamięcią na bardzo niskim poziomie, dzięki czemu osiąga bardzo wysoką prędkość.

Jednostka NPI DMA została pierwotnie zaprojektowana do użycia pod bardzo prostym osadzonym jądrem o nazwie "xilkernel", która nie obsługiwała pamięci wirtualnej, ani MMU nie była częścią MicroBlaze, więc programista mógł zobaczyć, gdzie będzie kod OS i wybierz adres pamięci fizycznej, taki jak 0x91800000, jako adres źródłowy, z którego będzie przesyłane DMA, następnie programista może umieścić plik pod tym dokładnym adresem i uruchomić system, gdy potrzebujemy do migracji projektu, aby użyć Linuksa zamiast xilkernel natknęliśmy się na ten problem, mam pliki na zewnętrznym urządzeniu pamięci masowej, do którego mogę uzyskać dostęp jako urządzenie blokowe z Linuksa i potrzebuję przenieść każdy plik do pamięci głównej (DDR3 RAM) i sprawić, aby plik DMA był przesyłany strumieniowo. obecnie strumienie DMA ze stałego adresu, ale w razie potrzeby mogę je wygenerować.

+2

Spójrz na ten plik PDF rozdziału wyjaśniającego, w jaki sposób jądro Linux zarządza pamięcią wirtualną i fizyczną. Podaje przykłady mapowania i przypinania pamięci fizycznej dla różnych scenariuszy. http://lwn.net/images/pdf/LDD3/ch15.pdf –

+1

@bromanous Czy opracowałeś to urządzenie samodzielnie, czy jest to rdzeń IP innej firmy, którego nie możesz zmodyfikować? Jeśli możesz go zmodyfikować, bardzo polecam skonfigurować oprogramowanie adresowe DMA, aby móc korzystać ze standardowych funkcji DMA, o których mówi tian_yufen. –

+0

@BenjaminLeinweber, tak, mam kod źródłowy dla jądra DMA i mogę skonfigurować adres, z którego pochodzą strumienie DMA i ustawić go jako parametr ogólny. – bromanous

Odpowiedz

5

Aby obsługiwać bufory do interfejsu ze sterownikiem DMA, istnieją określone funkcje. Funkcje te dbają nie tylko o translację adresu, ale także o spójność pamięci podręcznej z pamięcią, na przykład spłukiwanie pamięci podręcznej (zapis danych w pamięci przed wysłaniem) i unieważnianie pamięci podręcznej (unieważnianie pamięci podręcznej przed odebraniem).

(1) Aby przydzielić bufor, uzyskać zarówno adres wirtualny i fizyczny adres:

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

wartość zwracana funkcji jest wirtualny adres bufora przydzielonego, natomiast dma_handle wskaźnik ratuje fizyczny adres przydzielonego bufora.

(2) Aby przejść jeden bufor przyznane do urządzenia:

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

wartość powrotna jest fizyczny adres bufora, i parametr dir to DMA_TO_DEVICE, PTR wirtualny adres bufora;

(3) do odbierania z urządzenia jeden bufor:

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

Parametr dir to DMA_FROM_DEVICE.

Uwaga: Uwaga: Aby korzystać z trzech funkcji związanych z dma, należy zarejestrować urządzenie na jednej konkretnej magistrali, która ma dma_map_ops, inaczej te trzy funkcje nie mogą być używane.

+2

To nie odpowiada na pytanie OP. OP chce utworzyć bufor DMA w stałej lokalizacji w pamięci. Żaden z tych interfejsów API nie jest w stanie tego zrobić. –

4

muszę zmusić Linux, aby utworzyć plik bufora w tym dokładnym umieszczeniem pamięci

To nie jest możliwe. (Faktycznie utworzeniu pytanie XY).

Skoro masz sprzęt, który „strumienie danych od zadanego adresu fizycznego pamięci”, to trzeba upewnić się, że jądro Linux nie korzysta z tego obszaru pamięci, jako część jego puli pamięci. Musisz poinformować jądro , gdy uruchomi się, aby nie używać tego regionu pamięci. Nie będzie można "odzyskać" ani przydzielić buforów w tym konkretnym regionie pamięci fizycznej, gdy stanie się on częścią przestrzeni pamięci kontrolowanej przez jądro.

Najbardziej ogólną metodą wykluczania regionu pamięci jest użycie parametru memmap= w wierszu komend jądra.

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 

Niektóre struktury, takie jak ramię z jego ATAGs, mają inne mniej widoczny i bardziej bezpieczne sposoby rezerwowania obszary pamięci fizycznej.

W jakiś sposób musisz podać adres i rozmiar tego regionu pamięci do sterownika urządzenia. Można to uzyskać, parsując wiersz polecenia lub (kciuk w dół) na stałe, używając #define s.

Sterownik powinien zadeklarować użycie regionu pamięci, dzwoniąc pod numer request_mem_region().
Sterownik może odwzorować ten obszar pamięci na wirtualną przestrzeń adresową, wywołując ioreamp().

Ponieważ sterownik jest już dostarczony lub zna już adres fizyczny, jest to już zrobione. Ponieważ pamięć fizyczna została przydzielona, ​​pamięć jest przy tym ciągła. Będziesz musiał skonfigurować MMU, aby wyłączyć buforowanie w tym regionie pamięci. Obszar pamięci będzie wówczas "DMAable".

+2

+1 dla bezpośredniej odpowiedzi na pytanie. Inną podobną metodą jest użycie urządzenia w górnej części pamięci i informowanie Linuksa, że ​​jest mniej pamięci niż w rzeczywistości używa parametru mem = boot. Na przykład, jeśli masz 64 MB pamięci, możesz przekazać mem = 63M, aby zarezerwować megawat dla swojego urządzenia, począwszy od 0x3F00000. –

+0

@sawdust Nie rozumiem, jak "Musisz skonfigurować MMU, aby wyłączyć buforowanie w tym regionie pamięci", spojrzałem na regulowane parametry MicroBlaze i ta opcja nie istniała. Czy ustawienie pamięci nie jest wystarczające? – bromanous

+1

@bromanous - uwzględniłem to jako dodatkową myśl o kompletności. Prawdopodobnie nie musisz robić nic konkretnego. Mam nadzieję, że specyfikacja 'memmap =' i wywołanie 'ioremap()' dla twojego arch/board/proc ustawi odpowiednie atrybuty dla tego regionu pamięci. – sawdust

Powiązane problemy