2016-06-20 30 views
0

Ich versuche, auf die Hardware registers of an A20 SOM zuzugreifen, indem ich sie in userspace mmapping. In diesem Fall ist das Ziel der PIO, der unter der physischen Adresse 0x01C20800 aufgeführt ist.mmap() schlägt fehl, während devmemm erfolgreich ist (C/CPP) [Allzwinner A20]

Das offizielle Olimex Debian7 (Wheezy) Bild wird verwendet. Kernel Linux a20-olimex 3.4.90+

konnte ich die Lage überprüfen, indem die devmem2 tool und Allwinner in der Dokumentation auf dem genannten Speicherbereich unter Verwendung von (schaltete den pinMode und Ebene mit devmem).

Der mmap Anruf auf der anderen Seite

*map = mmap(
     NULL, 
     BLOCK_SIZE, // = (4 * 1024) 
     PROT_READ | PROT_WRITE, 
     MAP_SHARED, 
     *mem_fd, 
     *addr_p  
); 

nicht mit mmap error: Invalid argument

Hier ist eine vollständigere Version des Codes: http://pastebin.com/mfEuVdbJ

über die Zeiger als den gleichen Code Keine Sorge funktioniert beim Zugriff auf UART0 unter 0x01C28000. Obwohl nur UART0 (und UART4), die als serielle Konsole verwendet wird. Ich habe die script.bin (immer noch im Einsatz trotz DTB) ohne Erfolg dekompiliert, da UART 0, 7 und 8 dort aktiviert sind.

Ich bin angemeldet auch als Benutzer root

würde ich noch etwas erraten, um Berechtigungen verwandt, aber ich bin ziemlich gerade jetzt verloren, da devmem kein Problem bei allen

hat
> [email protected]:~# devmem2 0x01c20800 w /dev/mem opened. Memory mapped 
> at address 0xb6f85000. 

Antwort

0

Während sourcejedi nicht sicher mein Problem behoben, gab er mir den richtigen Ansatz. nahm ich einen Blick auf die vorerwähnte devmem tool's source zu entdecken, dass die Adresse des mmap Anruf

maskiert

address & ~MAP_MASK die gesamte Seite zu erhalten, die, wie in meinem Kommentar im Wesentlichen der gleiche Vorgang ist.

jedoch bis an die richtige Stelle zurück, nachdem das Mapping durchgeführt wurde, haben Sie die Maske zurück

final_address = mapped_address + (target_address & MAP_MASK);

Dies führte zu folgenden Code (basierend auf OP's pastebin)

hinzufügen

Wo MAP_MASK = (sysconf(_SC_PAGE_SIZE) - 1) in diesem Fall

int map_peripheral(unsigned long *addr_p, int *mem_fd, void **map, volatile unsigned int **addr) 
{ 
    if (!(*addr_p)) { 
     printf("Called map_peripheral with uninitilized struct.\n"); 
     return -1; 
    } 

    // Open /dev/mem 
    if ((*mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) { 
     printf("Failed to open /dev/mem, try checking permissions.\n"); 
     return -1; 
    } 

    *map = mmap(
     NULL, 
     MAP_SIZE, 
     PROT_READ | PROT_WRITE, 
     MAP_SHARED, 
     *mem_fd,     // file descriptor to physical memory  virtual file '/dev/mem' 

     *addr_p & ~MAP_MASK   // address in physical map to be exposed 
/************* magic is here **************************************/ 
    ); 

    if (*map == MAP_FAILED) { 
     perror("mmap error"); 
     return -1; 
    } 

    *addr = (volatile unsigned int *)(*map + (*addr_p & MAP_MASK)); 
/************* and here ******************************************/ 
    return 0; 
} 
0

, wenn Sie das lesen freundliches Handbuch

EINVAL   Invalid argument (POSIX.1) 

ist der Fehlercode. (Nicht EPERM!). So sehen wir es oben für die spezifische Funktion

EINVAL We don't like addr, length, or offset (e.g., they are too large, 
      or not aligned on a page boundary). 

BLOCK_SIZE, // 1024 -?

Sie möchten ein Vielfaches von sysconf(_SC_PAGE_SIZE). In der Praxis wird es 4096 sein. Ich werde mich nicht mit der ganz allgemeinen Mathematik beschäftigen, um es zu berechnen - Sie werden Beispiele finden, wenn Sie es brauchen.

+0

In der Tat ist BLOCK_SIZE \t \t (4 * 1024) ich Chaos Zustand um mit mit sysconf (_SC_PAGE_SIZE) bereits 'adr = adr - (Adr & sysconf (_SC_PAGE_SIZE));' – mystery

+0

@mystery 'addr = addr - (addr & sysconf (_SC_PAGE_SIZE));'? Das wird nichts ausrichten. Geben Sie den ** Wert ** der Adresse ein, die Sie verwenden möchten. –