Raspberry Pi 5 IoT In C - GPIO Registers |
Written by Harry Fairhead | |||||||||||||||||||||||||||||||||||||||||||||||||||||
Tuesday, 04 March 2025 | |||||||||||||||||||||||||||||||||||||||||||||||||||||
Page 4 of 4
PAD ControlUsing 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:
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 PulseNow 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 In Chapter but not in this extract
Summary
Raspberry Pi 5 IoT In C
|
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
|
Comments
or email your comment to: comments@i-programmer.info