Xenoxygen4213
Posts: 5
Joined: Mon Aug 02, 2021 7:54 pm

Reading GPIO Registers on a Raspberry Pi from C or C++

Mon Aug 02, 2021 8:56 pm

I have been using the following code to turn a basic LED on in a simple circuit

Code: Select all

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(18,GPIO.OUT)
print "LED on"
GPIO.output(18,GPIO.HIGH)
I wanted to read the register values from C to see the changes to the register from C
I used the manual listed https://datasheets.raspberrypi.org/bcm2 ... herals.pdf

I though I would have the right memory address for the pin marked GPIO17 with the following code.

Code: Select all

#include <stdio.h>

void main()
{
    volatile const int *initialMemory = 0x7e200000;
    const int *GPFSEL1Register = initialMemory + 0x04;

    printf("%p \n", GPFSEL1Register);

    int c, k;
    for (c = 31; c >= 0; c--)
    {
        int x = &GPFSEL1Register;
        k = x >> c;

        if (k & 1)
            printf("1");
        else
            printf("0");
    }

    printf("\n");
}
However the bits seem to be randomly changing rather than updating to whether the LED is on/off or if the pin is in INPUT or OUTPUT mode.

Could somebody here please help. Thanks in advance.

cleverca22
Posts: 4405
Joined: Sat Aug 18, 2012 2:33 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Tue Aug 03, 2021 12:49 am

volatile const int *initialMemory = 0x7e200000;
that is the wrong address
you need to map it from 0x7e to something else, that is model specific

https://www.raspberrypi.org/documentati ... dresses.md

and then its a physical addr, but your dealing with virtual, so you need to mmap /dev/mem

you can also mmap /dev/gpiomem to skip all of that, it always maps gpio directly

Heater
Posts: 18532
Joined: Tue Jul 17, 2012 3:02 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Tue Aug 03, 2021 6:02 am

As noted above. User programs run in a "virtual address" space created by the linux kernel. Hardware register addresses are in the real "physical address" space of the processor. In order to access registers you have to map the physical addresses of the registers into the virtual address space of your program. This is done with "mmap()". See "man mmap": https://man7.org/linux/man-pages/man2/mmap.2.html

And not that GPIO addresses have changed with different Pi models.

See here for a nice simple example of directly accessing GPIO registers via mmap() : https://elinux.org/RPi_GPIO_Code_Sample ... ter_access
Memory in C++ is a leaky abstraction .

Xenoxygen4213
Posts: 5
Joined: Mon Aug 02, 2021 7:54 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Tue Aug 03, 2021 11:58 am

cleverca22 wrote:
Tue Aug 03, 2021 12:49 am
volatile const int *initialMemory = 0x7e200000;
that is the wrong address
you need to map it from 0x7e to something else, that is model specific

https://www.raspberrypi.org/documentati ... dresses.md

and then its a physical addr, but your dealing with virtual, so you need to mmap /dev/mem

you can also mmap /dev/gpiomem to skip all of that, it always maps gpio directly
Apologies but im confused about why the Addressess are different from the documentation I linked and how I got this wrong. Why is there a disparity between the 2 documents? Pretty new to this stuff so just trying to learn.

Thanks in advance.

cleverca22
Posts: 4405
Joined: Sat Aug 18, 2012 2:33 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Tue Aug 03, 2021 1:21 pm

internally, the GPIO is at 0x7e200000 in the VPU space

on the pi0/pi1, that whole 16mb block at 0x7e00_0000 is mapped to 0x2000_0000 on the arm physical space
on the pi2/pi3, its mapped to 0x3f00_0000
and on the pi4, its mapped to 0xfe00_0000

the functions in https://www.raspberrypi.org/documentati ... dresses.md will detect the model and tell you the right address automatically

but, thats still in arm physical, and you need to mmap /dev/mem to get arm virtual

but, you can avoid all of that issue, if you just mmap /dev/gpiomem instead, that always maps to the gpio block

Xenoxygen4213
Posts: 5
Joined: Mon Aug 02, 2021 7:54 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Tue Aug 03, 2021 3:52 pm

cleverca22 wrote: internally, the GPIO is at 0x7e200000 in the VPU space

on the pi0/pi1, that whole 16mb block at 0x7e00_0000 is mapped to 0x2000_0000 on the arm physical space
on the pi2/pi3, its mapped to 0x3f00_0000
and on the pi4, its mapped to 0xfe00_0000

the functions in https://www.raspberrypi.org/documentati ... dresses.md will detect the model and tell you the right address automatically

but, thats still in arm physical, and you need to mmap /dev/mem to get arm virtual

but, you can avoid all of that issue, if you just mmap /dev/gpiomem instead, that always maps to the gpio block
So correct me if im misunderstanding.
0x7e200000 is the address in physical memory for the chip (in my case the BCM2711).
0xfe000000 is the adress it will be mapped to in virtual memory always when mmap is called on the pi.

Do the offsets listed in https://datasheets.raspberrypi.org/bcm2 ... herals.pdf still apply for the relavent pins? (Section 5.2 of the document).

I'm assuming the address in virtual memory is determined by the OS rather than the hardware and as such the hardware addresses would be the same as the virtual addresses in somethign like the Pi Pico?

Again thanks for explaining this to me as i ask.

User avatar
HermannSW
Posts: 4537
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Tue Aug 03, 2021 6:51 pm

See C code in "Peek and poke for Raspberry Pi register manipulation" thread:
viewtopic.php?f=33&t=289407&p=1757920&h ... k#p1757920
Image
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://github.com/Hermann-SW/raspiraw
https://stamm-wilbrandt.de/en/Raspberry_camera.html

cleverca22
Posts: 4405
Joined: Sat Aug 18, 2012 2:33 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Wed Aug 04, 2021 3:17 am

Xenoxygen4213 wrote:
Tue Aug 03, 2021 3:52 pm
So correct me if im misunderstanding.
0x7e200000 is the address in physical memory for the chip (in my case the BCM2711).
0xfe000000 is the adress it will be mapped to in virtual memory always when mmap is called on the pi.
7e is in the vpu space, which is a new space you dont see on any other system
fe is in the arm physical space on the pi4
you need to mmap to get an arm virtual addr that you can use from within a normal linux app

User avatar
rpdom
Posts: 19052
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Wed Aug 04, 2021 5:55 am

As cleverca22 said earlier, I'd recommend to mmap /dev/gpiomem, as then you don't have to worry about start addresses at all. All the GPIO offsets will be from 0. That's what I use on my code that runs on any Pi. You also don't need to be root to access it, just a member of the gpio group. Also there is less chance of your code killing anything if it gets an address wrong.
Unreadable squiggle

Xenoxygen4213
Posts: 5
Joined: Mon Aug 02, 2021 7:54 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Wed Aug 04, 2021 8:19 am

cleverca22 wrote:
Wed Aug 04, 2021 3:17 am
Xenoxygen4213 wrote:
Tue Aug 03, 2021 3:52 pm
So correct me if im misunderstanding.
0x7e200000 is the address in physical memory for the chip (in my case the BCM2711).
0xfe000000 is the adress it will be mapped to in virtual memory always when mmap is called on the pi.
7e is in the vpu space, which is a new space you dont see on any other system
fe is in the arm physical space on the pi4
you need to mmap to get an arm virtual addr that you can use from within a normal linux app
I guess my next question then is what is VPU space? My understanding was that it was physical memory, when mmap-ed would come into virtual memory at the same address. Apologies if this is a stupid question, this is all fairly new to me and I cant seem to find any resources that explain this well.

cleverca22
Posts: 4405
Joined: Sat Aug 18, 2012 2:33 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Wed Aug 04, 2021 8:29 am

Screenshot_2021-08-04_05-25-08.png
Screenshot_2021-08-04_05-25-08.png (159.92 KiB) Viewed 694 times
all of the peripherals live in the VPU address space, the left most one in this diagram

the MMIO for controlling them is in a 16mb block at 0x7e00_0000

the ram is then repeating 4 times, at 0, 0x4000_0000, 0x8000_0000, and 0xc000_0000, with some parts covered up at random


there is then a broadcom custom MMU sitting between "arm physical" and the VPU space

that custom broadcom mmu, will map 0x20/0x3f/0xfe to 0x7e, based on what model your using
it keeps moving, to try and keep it out of the way of the ram, but the ram keeps growing

then you have the standard arm mmu, that maps between arm physical and arm virtual

Xenoxygen4213
Posts: 5
Joined: Mon Aug 02, 2021 7:54 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Wed Aug 04, 2021 4:34 pm

cleverca22 wrote:
Wed Aug 04, 2021 3:17 am
Xenoxygen4213 wrote:
Tue Aug 03, 2021 3:52 pm
So correct me if im misunderstanding.
0x7e200000 is the address in physical memory for the chip (in my case the BCM2711).
0xfe000000 is the adress it will be mapped to in virtual memory always when mmap is called on the pi.
7e is in the vpu space, which is a new space you dont see on any other system
fe is in the arm physical space on the pi4
you need to mmap to get an arm virtual addr that you can use from within a normal linux app
Ok so one last question, why does the address change when it get mmap-ed. And how would you find this if its not in the documentation listed for the microcontroller (the doc i listed initially).

cleverca22
Posts: 4405
Joined: Sat Aug 18, 2012 2:33 pm

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Wed Aug 04, 2021 4:38 pm

when you mmap /dev/mem or /dev/gpiomem, it returns the virtual address it got mapped to

if your mapping /dev/mem, the offset(given to mmap) you give is the arm physical address
if your mapping /dev/gpiomem, the offset is 0, and the driver deals with finding the gpio for you

User avatar
HermannSW
Posts: 4537
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: Reading GPIO Registers on a Raspberry Pi from C or C++

Wed Aug 04, 2021 5:39 pm

Here is poke and peek gist from my previous posting as example from memory mapping:
https://gist.github.com/Hermann-SW/b0f9 ... ca910b3c87

Code: Select all

/*
   gcc -Wall -pedantic -Wextra poke.c -o poke
   ln -s poke peek && ln -s poke peek_l && ln -s poke poke_l
   ln -s poke peek_s && ln -s poke peek_sl 
*/
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://github.com/Hermann-SW/raspiraw
https://stamm-wilbrandt.de/en/Raspberry_camera.html

Return to “C/C++”