.mmap
The .mmap
command opens a new IO space where the content is memory
mapped from the device driver or file system. This is especially useful when a
kernel driver offers a mmap function for mapping the content of kernel memory
into userspace. The most famous example is the mem device with its device node
/dev/mem. But there are also many drivers especially in embedded systems using
it.
In the case of a regular file the mapping is done by the file system driver.
For regular files the .file
command would be an alternative and should
deliver the same result. The difference is that .file
is using read
and write system calls to retrieve or set the content of the file whereas
.mmap
is using the mmap system call which is copying the data from the
file into ram memory. This is done by the file system driver and on nowadays
file systems .file
and .mmap
are offered by them. When
having enough free ram and accessing the file very often the .mmap
is
supposed to be faster because there are less system calls to be executed.
See .file
In the case of a device driver the behavior depends on the implementation of the
driver. It particularly depends on the offered read, write and mmap functions.
With /dev/mem for example .file
and .mmap
should deliver the
same results.
But there are many drivers used in embedded systems especially for customer
hardware which are offering either read and write or mmap. In such a case only
the corresponding command can be used.
For example when dealing with large amounts of data (video stream) which should
be visible to the userspace for further processing it’s almost impossible to
copy every single picture to userspace with a driver read function. In such
cases device drivers often only offer a mmap function which avoids the extra
copying operation.
The syntax is:
.mmap filename, base, size
where filename is the name of the device node or the file name, base is the starting offset (or base address) of the mapping and size is the length of the mapped area.
The base has to be a multiple of the MMU page size on the system. It can be retrieved via the C function getpagesize(). On most systems it’s 4096 Bytes.
The following example is mapping the GPIO registers via /dev/mem on the Beaglebone black board and reading the output enable (GPIO_OE) and data out (GPIO_DATAOUT) registers of the IO memory:
$ poke (poke) .mmap /dev/mem, 0x4804c000, 0x1000 (poke) int 0x13C#B (poke) int 0x134#B
When using int on 32 bit systems the full address bus width is used when reading and the same applies to 64 bit systems with the long datatype. All accesses with less bytes than the address bus width are done via a byte by byte copy.
Please write to the poke-devel mailing list if you need a different alignment.
Warning: One should be aware that when writing to mapped registers one is writing to the hardware. Therefore one should be aware of the meaning of the registers as well as the electrical circuit connected. Otherwise the hardware can easily be destroyed. To give an example this could happen when setting a GPIO as output with a high signal while in fact it is connected as an input on the electrical circuit with low signal.