I'm reading this article, Low Level Programming of the Raspberry Pi in C, which explains how to access the raspberry pi on a low level.

It states that the virtual gpio address is 0x7E200000.

Therefore a macro is defined like this

#define BCM2708_PERI_BASE       0x20000000
#define GPIO_BASE               (BCM2708_PERI_BASE + 0x200000)

How do I calculate the offset between the peripherie base and the gpio base?

So how does one calculate that 0x20000000 + 0x20000000 = 0x7E200000

Is this simply binary arithmetic?

  • 0x2000000 + 0x2000000 = 0x4000000. 0x20000000 + 0x200000 = 0x20200000 (the code actually says the latter). – RemcoGerlich Sep 26 '16 at 21:38
  • 1
    Please note that resource requests are off-topic, so I edited that out of your question. A good answer may link to resources, but will stand on its own. – user22815 Sep 26 '16 at 23:12

What Low Level Programming of the Raspberry Pi in C actually says is:

So the BCM2708_PERI_BASE macro contains the physical adress value at which the peripheral registers start. This is the adress we will need to use in our program. The virtual address value is 0x7E000000, and it are these virtual adresses that will be found in the datasheet.

There are a lot of different peripherals available on the BCM2835 (Timers, USB, GPIO, I2C, ...), and they will be defined by an offset to this virtual adress! For example, if we are interested in the GPIO peripheral (like in the example code above), we can find in the manual at page 90 that the virtual address is 0x7E200000. This means that the offset to the physical adress will be 0x200000 which explains the GPIO_BASE.

That doesn't say

0x2000 0000 + 0x2000 0000 = 0x7E20 0000

It says

0x7E00 0000 + 0x0020 0000 = 0x7E20 0000

It just say's it badly, because it expresses

0x00200000 as

Which is the same number, but that's really hard to see because humans don't like to count un-grouped zeros. You're a victim of poorly presented HEX.

I've spent a lot of time bit fiddling. I've sent specifications back to be rewritten over issues like this. Even when working at a low level it's important to keep humans in mind.

Which is why I really wish you'd said it like this:

0x7E00 0000 + 
0x0020 0000 
0x7E20 0000

Because this stuff is important to get right. In certain shops white-space can literally save lives. Don't make it harder than it has to be.

As for the macro keep in mind how virtual mapping works. In one context the offset exists, in another it doesn't. At least it seems like it doesn't. It's the same with array indexing. someArray[0] exists wherever someArray exists. So someArray[2] doesn't exist at 2. It's wherever + 2. You're virtual address has a wherever address of 0x7E00 0000.

Look back at where you found this macro

#define BCM2708_PERI_BASE       0x20000000
#define GPIO_BASE               (BCM2708_PERI_BASE + 0x200000)

You'll notice that the 0x7E00 0000 number doesn't appear in the macro or even in any of the code in this article. That's because you get that offset for free. These programs are addressing beyond that offset. Just like when I say someArray[2] I don't have to know where someArray exists.

So I'd expect at the end of the day that the GPIO_BASE would point here:

0x7E00 0000 + 
0x2000 0000 + 
0x0020 0000 
0x9E20 0000

And that it's value within the program would read only as:

0x2000 0000 +
0x0020 0000 
0x2020 0000

Since you get 0x7E00 0000 from the virtual mapping of the program memory you don't need it in the program. That's one of the nice things about being virtual.

  • Thanks for a detailed explanation. I really want to get deeper in this, could you recommend also a good learning resource? Thank you – xhallix Sep 27 '16 at 5:23
  • Sure, I recommend Raspberry Pi Stack Exchange. I'll bet you can find articles that even manage to spell address with two d's :) – candied_orange Sep 27 '16 at 5:28
  • ............... ;) – xhallix Sep 27 '16 at 5:42
  • These are bus adresses not virtual adresses! This is an important difference because these are the adresses that are advertised to the system bus by the VCore-MMU to the system bus. Virtual Adresses would be the ones that get translated to physical ones by the ARM-Kernel-MMU. – Sebi2020 Feb 24 at 11:04

Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus addresses for peripherals are set up to map onto the peripheral bus address range starting at 0x7E000000. Thus a peripheral advertised here at bus address 0x7Ennnnnn is available at physical address 0x20nnnnnn.

So the BCM2708_PERI_BASE macro contains the physical adress value at which the peripheral registers start. This is the adress we will need to use in our program. The virtual address value is 0x7E000000, and it are these virtual adresses that will be found in the datasheet.

It is just a matter that certain popular publications are using one board configuration standard and the Pi is using another. So, there is a well-defined mapping between Pi addresses of 0x20nnnnnn and that other well-known board configuration that uses 0x7Ennnnnn for the same I/O range.

There is no arithmetic that will turn 0x20nnnnnn into 0x7Ennnnnn (that is, without knowing the mapping, which gives you that magic constant, i.e. 0x7E000000 - 0x20000000 == 0x5E000000).

There are many reasons one board may use different ranges for something like this, such as having fewer overall address lines wired from the processor, as this saves money and power on the board, though at the cost of less total memory being accessible.

  • Again this are not virtual adresses. That are bus adresses and the clou is that you have to translate them back to physical adresses if you want to specify bus-adresses because the ARM-Kernel uses physical-Adresses. In the example above this translation already took place. Another approeach would be phys_io_addr = bus_addr - (bus_io_base - phys_io_base) with bus_io_base = 0x7e00 0000 and phys_io_base = 0x2000 0000. Sadly the datasheet explains that badly. – Sebi2020 Feb 24 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.