This project is submitted for

Description

I've been developping and using this tiny file for a few years now and it has been already published in 2014 in the french Linux Magazine and Open Silicium, but here you should find a sort of "repository" with the freshest version.

Optimised for size/speed/latency/real-time, then only for convenience. USE AT YOUR OWN RISKS.

Tested on RPI A, B, B+, RPi2 and RPi3. Contributions are welcome.

No picture or illustration because it makes no sense for a very low-level library...

The RPi2 swapped the venerable BCM2835 for a BCM2836. The Peripheral block is pretty much the same (or so we hope !) but the BCM2835 changed its base address. So that's the only thing that seems to matter for now.

Note: For Raspberry Pi 2, change BCM2708_PERI_BASE to 0x3F000000 for the code to work.

My current approach is to provide the base pointer as a compile-time parameter because I write mostly "bare-metal" code for a specific board, which is then embedded somewhere for an indefinite while. I don't do "portable binary code" that gets distributed and executed here and there on all kinds of boards.

Actually, "simple is best" because the situation is pretty complicated with the current software environment. A pile of legacy code is accumulating... Some distribution provide features that allow detection of the board type and revisions, some other don't. And this depends on the kernel compile flags, as well as the distribution's bells and whistles.

Another argument in favor of a compile-time parameter is: the pointer is constant and can be optimised, which saves a bit of time and space. Nothing really important but in some cases it can do a little welcome difference.

The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits()
are low level peripheral register access functions. They are designed
to use physical addresses as described in section 1.2.3 ARM physical
addresses of the BCM2835 ARM Peripherals manual. 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 in the manual at
bus address 0x7Ennnnnn is available at physical address 0x20nnnnnn.

On RPI 2, the peripheral addresses are different and the bcm2835
library gets them from reading /proc/device-tree/soc/ranges. This is
only availble with recent versions of the kernel on RPI 2.

(...)

Raspberry Pi 2 (RPI2)

For this library to work correctly on RPI2, you MUST have the device
tree support enabled in the kernel. You should also ensure you are using
the latest version of Linux. The library has been tested on RPI2 with
2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29.

When device tree suport is enabled, the file
/proc/device-tree/soc/ranges will appear in the file system, and the
bcm2835 module relies on its presence to correctly run on RPI2 (it is
optional for RPI1). Without device tree support enabled and the presence
of this file, it will not work on RPI2.

To enable device tree support:

sudo raspi-config
under Advanced Options - enable Device Tree
Reboot.

Since I don't distribute binaries, I don't care about supporting all the HW&SW combinations under the sun. I can relegate the detection to a bash script :-)

Oh and in an older Raspbian running on a B+, I get the necessary info from a different /proc/ file: