简体   繁体   中英

mmap a device and access it device's memory map

I'm working on a very simple application which will test a device. There is no need for a driver and I have admin permissions.

I was going to use a mmap and this is where I got a confused.

The idea is to do the following

int devD = open("/path/to/my/device", "rw");
void *myDevPtr = mmap(start, length, prot, flags, devD, offset);

Here is where I found the documentation for it. I'm confused about every parameter except the file descriptor and the protection.

void *start . What exactly this is the start of? Is it the start of memory map for my device?

size_t length . My device has its own memory map. Is it the length of my devices memory map or this is something else?

int flags . This one puzzles me. If my file descriptor is a device, what do I set my flags to?

off_t offset . This one is also confusing. This is an offset from the start pointer, but what exactly is this offset into?

Another is question that I have is about communicating with the mmapped device. Say I need to write data to a specific register in the device. How would I do it?

I realize that these questions might look too simplistic, but I've been at it for some time now and couldn't find a concrete example that would address my situation.

Any help with this is really appreciated.

void *start. What exactly this is the start of? Is it the start of memory map for my device?

It's the logical address within your program where you want the mapping to occur. If you give it NULL, it will assign one [recommmended]. This is a "hint" and the address of the mapped area is the mmap return value

size_t length. My device has its own memory map. Is it the length of my devices memory map or this is something else?

[Not knowing your device], I would assume it's the same. But, say your device was 6GB long. You may want to access this in sections, so you might specify (eg) 1MB instead. And, then, remap later [see the offset section]

int flags. This one puzzles me. If my file descriptor is a device, what do I set my flags to?

Use MAP_SHARED so that what you write to the area is flushed to the "backing store" (which is your device).

off_t offset. This one is also confusing. This is an offset from the start pointer, but what exactly is this offset into?

No, it is not an offset from start . It is the offset within your device that the mapping should be done to (ie just like the offset for lseek ).


UPDATE:

When you say: [Not knowing your device], I would assume it's the same. Do you mean that length is the length of the devices memory map?

From that standpoint, yes. If you want to map the entire area, which as I mentioned, can be large.

Normally, you map the entire device/file, starting at offset 0 for the length of the device/file.

I'm also a little confused about the offset. Say my device has a register at offset 0x100. In order to read/write this register I would need to set offset to 0x100. Am I correct?

Yes and no. You can do it two ways. Herein, let's call the mapped address [the return value from mmap ] by the name mapbase .

(1) Give mmap an offset parameter of 0x100. Then, do (eg) val = *mapbase . Effectively, this is saying to the OS: "I only care about this one register and you handle the mapping to it"

(2) Give mmap an offset parameter of 0. Then, do val = mapbase[0x100] Effectively, this is saying: "I want a mapping to all the registers and I will handle the indexing/offsetting manually"

Method (2) is more usual (ie you want to create a single mapping that can access just about any register). If you use method (1), what about a register that is located at 0x80? It's inaccessible [unless you do a remap, which is time consuming].


UPDATE #2:

As arsv pointed out, you may need to open /dev/mem to map to a device's registers.

This depends upon your device's driver . Suppose we have /dev/mydevice . Now, suppose we do fdd = open("/dev/mydevice",O_RDWR)

It is up to the driver to provide a mapping between I/O done to the open file descriptor ( fdd ) and the device's registers .

Some drivers support this, but most don't. If the device does support this, then we do the mmap with fdd

If it doesn't we have to do fdm = open("/dev/mem",O_RDWR) and pass fdm to mmap . Of course, now the mmap offset parameter will be radically different.

Check Mapping a physical device to a pointer in User space .

start is virtual memory address to map the device to. Leave NULL there.
flags should be MAP_SHARED.
offset is into the file being mmaped; for /dev/mem, that would be page-aligned physical address of the device.

Then just write to the mmaped area.

char* ptr = mmap(..., [/dev/mem], BASE);
*(ptr + OFFSET) = value;

Keep in mind that the physical address in this case will be (BASE + OFFSET).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM