Raspberry Pi 5 IoT In C - GPIO Registers
Written by Harry Fairhead   
Tuesday, 04 March 2025
Article Index
Raspberry Pi 5 IoT In C - GPIO Registers
Registers
PAD
PAD Control

PAD Control

Using the RIO we can read and write the GPIO lines, but there is a further step we have to complete before we can actually make use of them. Each GPIO line has its own PAD which is a set of components that control the physical connection of the line to the outside world. To make a GPIO line work you have to configure the pad to act as input or output and set its electrical characteristics. You can see the Pi 5’s PAD structure in the diagram below:

This is very similar to the PAD design found in other members of the Pi family. The PAD registers for the GPIO bank we are using is at 0x400f0000 which means its offset is 0xf0000:

uint32_t *PADBase = PERIBase + 0xf0000 / 4;

The only complication is that the first register is a VOLTAGE_SELECT register which sets the voltage that all of the GPIO lines in bank 0 work with. A zero sets 3.3V and a one sets 1.8V. The default is 3.3V and you can ignore this register unless you need to work at 1.8V.

After the VOLTAGE_SELECT register there is a PAD register for each GPIO line: 

Bits

Name

Description

Type

Reset

31:8

Reserved

 

 

 

7

OD

Output disable. Has priority over output enable from peripherals

RW

0x1

6

IE

Input enable

RW

0x0

5:4

DRIVE

Drive strength.
0x0 → 2mA
0x1 → 4mA
0x2 → 8mA
0x3 → 12mA

RW

0x1

3

PUE

Pull-up enable

RW

Varies

2

PDE

Pull-down enable

RW

Varies

1

SCHMITT

Enable Schmitt trigger

RW

0x1

0

SLEWFAST

Slew rate control. 1 = Fast, 0 = Slow

RW

0x0

We can access the PAD registers using:

uint32_t *pad = PADBase + 1;

For example, if we want to set the PAD to output with a default drive, no pull-up/down, no Schmitt trigger and slow slew rate we would use:

pad[pin]= 0x10;

Notice that output is set by not enabling input.

 

 

A Fast Pulse

Now we can re-write a Blinky-style program to find out how fast the Pi 5 can toggle a GPIO line. We first have to map the peripherals area into user space and set up all of the addresses we want to use. Next we configure the pin as an output and start a loop that toggles the line using the XOR register:

The complete program is:

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
typedef struct{
    uint32_t status;
    uint32_t ctrl; 
}GPIOregs;
#define GPIO ((GPIOregs*)GPIOBase)
typedef struct
{
    uint32_t Out;
    uint32_t OE;
    uint32_t In;
    uint32_t InSync;
} rioregs;
#define rio ((rioregs *)RIOBase)
#define rioXOR ((rioregs *)(RIOBase + 0x1000 / 4))
#define rioSET ((rioregs *)(RIOBase + 0x2000 / 4))
#define rioCLR ((rioregs *)(RIOBase + 0x3000 / 4))
int main(int argc, char **argv)
{
    int memfd = open("/dev/mem", O_RDWR | O_SYNC);
    uint32_t *map = (uint32_t *)mmap(
        NULL,
        64 * 1024 * 1024,
        (PROT_READ | PROT_WRITE),
        MAP_SHARED,
        memfd,
        0x1f00000000
    );
    if (map == MAP_FAILED)
    {
        printf("mmap failed: %s\n", strerror(errno));
        return (-1);
    };
    close(memfd);
    uint32_t *PERIBase = map;
    uint32_t *GPIOBase = PERIBase + 0xD0000 / 4;
    uint32_t *RIOBase = PERIBase + 0xe0000 / 4;
    uint32_t *PADBase = PERIBase + 0xf0000 / 4;
    uint32_t *pad = PADBase + 1;   
    
    uint32_t pin = 2;
    uint32_t fn = 5;
    GPIO[pin].ctrl=fn;
    pad[pin] = 0x10;
    rioSET->OE = 0x01<<pin;
    rioSET->Out = 0x01<<pin;
    
    for (;;)
    {
        rioXOR->Out = 0x04;
    } 
    return (EXIT_SUCCESS);
}

I
f you try this out you will find that it produces 24ns pulses.

 In Chapter but not in this extract

  • The Gpio5 Library
  • Initializing GPIO
  • Get and Set
  • PAD Configuration
  • Working with Gpio5
  • Examples
  • Interrupts?

Summary

  • The Pi 5 has its peripherals implemented by the custom RP1 chip and this makes it incompatible with all previous versions of the Raspberry Pi.

  • The memory map and the register configurations are different to other Pis and more like those found in the Pico.

  • You can still work with the Pi 5’s registers using the standard memory-mapping techniques.

  • The /dev/mem device accesses all of the memory, but needs root privileges.

  • The /dev/gpiomem0 device only provides the GPIO registers, but it can be used without root privileges.

  • The Pi 5 uses the same RIO-based GPIO implementation as the Pico. To use the GPIO lines you first have to select RIO mode.

  • Each GPIO line also has a PAD and a PAD control register.

  • The RIO registers are used to control and read the state of the GPIO line.

  • Using direct register access, the Pi 5 can produce well-formed 25ns pulses

  • Although using the registers directly is a good way to get started, creating functions, and hence a library to do the same job, is a good idea.

  • The Gpio5 library is based on the Pico SDK GPIO functions and it allows you to run Pico GPIO programs with little modification.

  • Working with raw interrupts under Linux is not easy and best avoided.

Raspberry Pi 5 IoT In C
Drivers and Gpio5

By Harry Fairhead

CIoTPi5360
Buy from Amazon.

Contents

  1. The Pi 5 For The IoT
  2. C and Visual Studio Code
  3. Drivers: A First Program
  4. The GPIO Character Drive
  5. GPIO Using I/O Control
  6. GPIO Events
  7. GPIO Hardware With Gpio5
         Extract: GPIO Registers ***NEW!
  8. Some Electronics
  9. The Device Tree
  10. Pulse Width Modulation
  11. SPI Devices
  12. I2C Driver and Gpio5
  13. Sensor Drivers – Linux IIO & hwmon
  14. 1-Wire Bus
  15. The PIO 313
  16. Going Further With Drivers
  17. Appendix I Gpio5

 <ASIN:1871962943>

 

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


Deno 2.2 Adds Built-in OpenTelemetry
06/03/2025

Deno 2.2 has been released with built-in OpenTelemetry among its improvements. Other changes include new Lint plugins, and support for node:sqlite.



GDWC Games Competition Open For Entries
14/02/2025

The Games Development World Championship 2025 is open for entries. The GDWC competition has two new categories this year - Best Discord Game Award and Proceduralism Award, joining the existing ca [ ... ]


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Tuesday, 04 March 2025 )