JMercer
Posts: 5
Joined: Fri Aug 02, 2013 2:01 pm

Addressing Registers

Fri Aug 02, 2013 2:11 pm

Hi there!

Recently got the Raspberry Pi Model B and have I2C working off of the GPIO header, I made a memory map of the registers and mmap'd the GPIO. But my question is: How can I use virtual addresses or bus addresses instead of the physical addresses to access the GPIO? I've searched high and low for an example where someone is using something other than the physical addresses and have found diddly squat. I wanted to do this from scratch instead of using another library so I could learn more about embedded programming.

WiringPi uses the physical addresses, as does the library that the Python GPIO access works off of and anywhere else I've seen.

The datasheet references all the registers as bus addresses but tells you how to convert to physical/virtual addresses, which makes me think that I should be able to use the bus addresses somewhere.

Programming in C by the way.:)

Thanks!

JMercer
Posts: 5
Joined: Fri Aug 02, 2013 2:01 pm

Re: Addressing Registers

Mon Aug 05, 2013 9:25 am

Bump

User avatar
joan
Posts: 14959
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Addressing Registers

Mon Aug 05, 2013 9:38 am

Using C under Linux you will be using virtual addresses.

If you want the physical address of a virtual address you will need to interpret /proc/pid/pagemap where pid is the Linux process number.

From memory, to go from a physical address to a bus address you need to add 0x40000000.

JMercer
Posts: 5
Joined: Fri Aug 02, 2013 2:01 pm

Re: Addressing Registers

Wed Aug 07, 2013 8:44 am

Thanks!

I'll look into the pagemap thing, but my mmap call is:

map = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE_ADDR)

where GPIO_BASE_ADDR is 0x20200000

I though this was a physical address? Maybe, I'm not understanding the whole physical/virtual thing?

Thanks again:)

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Addressing Registers

Wed Aug 07, 2013 9:12 am

In that case, after the call, map is a pointer holding a virtual address that corresponds to the physical address 0x20200000.

That is the purpose of mmap*: to map a physical address to somewhere in virtual memory.

Virtual memory is what the program sees. All pointers point to virtual memory, all variables live there. Each program thinks it has access to the whole of memory, and no program can access memory belonging to another program.

As someone once said, Virtual memory is memory that's nearly there.

It's there when you need it, but it might not be there at any other time.

The Linux kernel works hard behind the scenes making sure that all the virtual memory that the active program wants to use, is mapped to real memory. But the virtual memory that belongs to inactive programs does not have to be mapped to physical memory; it can be copied to the Swap disk. That means that more programs can run simultaneously.

Most of the time the mapping between virtual and physical addresses is handled entirely by the Linux kernel. If you allocate an array, you don't care exactly which part of physical memory it exists in, just so long as you know the virtual address. In fact if it is swapped out to disk and then back in, its physical address will probably change. But its virtual address stays the same.

mmap is a special case. It tells the kernel that you want to access a particular area of physical "memory". In that case you do care about the physical address, and the mapping is permanent. The virtual address that mmap returns will always (during the lifetime of the program) refer to the same physical address. In the case of GPIO of course, that memory won't be swapped out anyway. In the more general case, for example if you are setting up some super-fast shared memory, you need to disable swapping yourself.

NB: that might be bus address rather than physical address. The difference only matters when you are dealing with the GPU.

----
* At least it is when the fd refers to /dev/mem.

JMercer
Posts: 5
Joined: Fri Aug 02, 2013 2:01 pm

Re: Addressing Registers

Wed Aug 07, 2013 10:43 am

That was a really good explanation! I understand the mmap function more now:)

So are the virtual/bus addresses mentioned in the datasheet not usable by the user, but are used by the GPU? Or are they more suggestions of where to store the pointer to the corresponding physical address?

Sorry if I'm being stupid here, I'm just trying to wrap my head round this:)

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Addressing Registers

Wed Aug 07, 2013 11:07 am

OK, I've read the datasheet now ;-)

Ignore Bus addresses unless you are giving them to the GPU or DMA. You aren't, so ignore them.

Ignore what the datasheet says about Virtual addresses unless you are writing Linux kernel code. You aren't, so ignore it.
The datasheet is talking about how all of memory is mapped for the use of the Linux kernel. Each program(process) has its own mapping, as I said above, and the kernel also has one. It happens that the kernel's mapping is so fixed that it can be described in the datasheet. Programs don't use that mapping, they use one created just for them by the kernel, as I described above. It is a process virtual address, not a kernel virtual address.

This is probably where your confusion arises from.

The only thing you are interested in from the datasheet is the physical address.

You use mmap to map that physical address to a process virtual address that your program can see.

JMercer
Posts: 5
Joined: Fri Aug 02, 2013 2:01 pm

Re: Addressing Registers

Wed Aug 07, 2013 12:32 pm

That sounds exactly like what I was looking for, thanks!!:)

I think the datasheet's fairly confusing tbh

Cheers!
Jake

gsh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1564
Joined: Sat Sep 10, 2011 11:43 am

Re: Addressing Registers

Wed Aug 07, 2013 12:43 pm

It's possible you're also being confused because the are actually three memory maps...

The virtual address is what the linux kernel gives you to use to access things... All accesses in the kernel are done from this virtual addressing system, even the kernel and interrupts. People think that when you go into an interrupt you are using physical addresses, you are not, you are using kernel virtual addresses.

The physical address is the address that the ARM thinks it is using to access the devices on the chip... that looks like 0x20200000

The MMU in the ARM uses a special lookup table to convert your virtual address that you got from mmap() into a physical address that looks like 0x20200000

But the address that the datasheet talks about are all 0x7e200000 these are bus addresses...

There is another translation layer that is programmed by the GPU to limit what the ARM has access to (it does this for security reasons, for example you don't have access to the SD controller registers otherwise you'll end up breaking the memory!)

This translation converts the ARM 'physical' address from 0x20200000 to 0x7e200000 to access the physical register

Clear as mud?

Gordon
--
Gordon Hollingworth PhD
Raspberry Pi - Director of Software Engineering

Return to “Beginners”