2016-12-24 5 views
0

Ich habe Probleme beim Zuordnen von physischem Speicher auf Xilinx Zynq, nachdem versucht wurde, UIO anstelle von Mapping direkt /dev/mem zu verwenden. Während der Plan ist, die Anwendung als normaler Benutzer anstelle von root auszuführen, wird dies weiterhin als root ausgeführt.mmap EINVAL-Fehler auf UIO-Gerät

Anscheinend ist die erste Zuordnung erfolgreich, während der Rest für den gleichen Dateideskriptor 12 (/dev/uio/ps2pl) fehlgeschlagen ist. Der offensichtliche Unterschied ist der Offset, er liegt jedoch innerhalb des Bereichs (siehe Gerätebaum) und ist ordnungsgemäß ausgerichtet. Diese Anwendung funktionierte gut mit /dev/mem.

der Fehler durch Laufen mit strace eingehalten wird:

open("/dev/uio/ps2pl", O_RDWR|O_SYNC) = 12 
open("/sys/bus/i2c/devices/0-0050/eeprom", O_RDONLY) = 13 
fstat64(13, {st_mode=S_IFREG|0600, st_size=8192, ...}) = 0 
_llseek(13, 0, [0], SEEK_SET)   = 0 
read(13, "\1\1\0\0\0\0\0\0", 8)   = 8 
read(13, "(\\\217\2(\\\217\00233333333\0\0\0\0\0\0\0\0(\\\217\2(\\\217\2"..., 4096) = 4096 
close(13)        = 0 
mmap2(NULL, 48, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0) = 0xb6f93000 
mmap2(NULL, 48, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0x400000) = -1 EINVAL (Invalid argument) 
mmap2(NULL, 196608, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0x200000) = -1 EINVAL (Invalid argument) 
mmap2(NULL, 196608, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0x100000) = -1 EINVAL (Invalid argument) 
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x1f} --- 
+++ killed by SIGSEGV +++ 
Segmentation fault 

die Gerätestruktur wie in den Kernel geladen:

# /root/dtc/dtc -f -I fs /sys/firmware/devicetree/base/amba_pl/ps2pl\@40000000/ 
ERROR (name_properties): "name" property in/is incorrect ("ps2pl" instead of base node name) 
Warning: Input tree has errors, output forced 
/dts-v1/; 

/{ 
    reg = <0x40000000 0x40000000>; 
    name = "ps2pl"; 
    interrupts = <0x0 0x44 0x4>; 
    compatible = "generic-uio"; 
    interrupt-parent = <0x3>; 
}; 

Die Größe des UIO-Mapping der groß genug ist, um die oben mmap aufzunehmen Größen und Offsets:

# cat /sys/devices/soc0/amba_pl/40000000.ps2pl/uio/uio0/maps/map0/size 
0x40000000 

Antwort

0

mmap Offset wird für /dev/mem dann für UIO-Geräte anders behandelt. Es ist nicht möglich, einen willkürlichen Offset zu verwenden, stattdessen ist es nur möglich, den Beginn jeder Region abzubilden. Das obige Beispiel ist nur ein Bereich in der Gerätestruktur definiert, aber es ist möglich, mehrere Bereiche zu definieren:

reg = <0x40000000 0x10000>, 
     <0x40010000 0x10000>, 
     <0x40020000 0x10000>, 
     <0x40030000 0x10000>; 
reg-names = "region0", "id", "region2", "gpio"; 

Zugriff auf jede Region/Mapping nicht offensichtlich ist, wie hier beschrieben: https://lwn.net/Articles/232575/

Der Offset die n ten Regionen für den Zugriff sollte sein:

n * sysconf(_SC_PAGESIZE) 

auf dem Arm die Seitengröße ist ein 12-Bit-Fenster 0x1000.

Einige weitere allgemeine Dokumentation. http://elinux.org/images/b/b0/Uio080417celfelc08.pdf