Created
February 16, 2026 17:34
-
-
Save tsutsui/0c0d6c1d7f4e2d5dbaaf210789c51ad7 to your computer and use it in GitHub Desktop.
Raspberry Pi 3 GPIO test on NetBSD/evbarm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * gpio_mmap_test.c | |
| * Minimal Raspberry Pi GPIO test using GPIO access via /dev/mem mmap(2) | |
| * | |
| * Wiring: | |
| * GPIO20 -> LED (1: on, 0: off) | |
| * | |
| * Build: | |
| * cc -O2 -Wall -Wextra -o gpio_mmap_test gpio_mmap_test.c | |
| */ | |
| #include <sys/mman.h> | |
| #include <fcntl.h> | |
| #include <inttypes.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| // #define PERI_BASE 0x20000000u /* BCM2835 (Pi 1/Zero) */ | |
| #define PERI_BASE 0x3F000000u /* BCM2836/2837 (Pi 2/3) */ | |
| // #define PERI_BASE 0xFE000000u /* BCM2711 (Pi 4) */ | |
| #define GPIO_BASE (PERI_BASE + 0x200000u) | |
| #define GPIO_SIZE 0x1000u | |
| /* GPIO registers */ | |
| #define GPFSEL0 0x00 | |
| #define GPFSEL1 0x04 | |
| #define GPFSEL2 0x08 | |
| #define GPSET0 0x1c | |
| #define GPCLR0 0x28 | |
| #define GPLEV0 0x34 | |
| enum { | |
| PIN_D0 = 20, /* DA0 */ | |
| }; | |
| #define MASK_D0 (1u << PIN_D0) | |
| static volatile uint32_t *gpio; | |
| static void | |
| die(const char *msg) | |
| { | |
| perror(msg); | |
| exit(EXIT_FAILURE); | |
| } | |
| /* Minimal memory barrier (ordering for MMIO) */ | |
| static inline void | |
| mmio_barrier(void) | |
| { | |
| #if (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__) | |
| __asm__ volatile("dmb ish" ::: "memory"); | |
| #else | |
| __sync_synchronize(); | |
| #endif | |
| } | |
| /* Set GPIO function to output: fsel=001 */ | |
| static void | |
| gpio_config_output(int pin) | |
| { | |
| uint32_t reg = pin / 10; | |
| uint32_t shift = (pin % 10) * 3; | |
| volatile uint32_t *fsel = &gpio[GPFSEL0 / 4 + reg]; | |
| uint32_t v = *fsel; | |
| v &= ~(7u << shift); | |
| v |= (1u << shift); | |
| *fsel = v; | |
| mmio_barrier(); | |
| } | |
| static void | |
| gpio_config(void) | |
| { | |
| gpio_config_output(PIN_D0); | |
| } | |
| static inline void | |
| gpio_write_masks(uint32_t set_mask, uint32_t clr_mask) | |
| { | |
| if (clr_mask) | |
| gpio[GPCLR0 / 4] = clr_mask; | |
| if (set_mask) | |
| gpio[GPSET0 / 4] = set_mask; | |
| mmio_barrier(); | |
| } | |
| static inline void | |
| gpio_d0_on() | |
| { | |
| gpio_write_masks(MASK_D0, 0); | |
| } | |
| static inline void | |
| gpio_d0_off() | |
| { | |
| gpio_write_masks(0, MASK_D0); | |
| } | |
| int | |
| main(int argc, char **argv) | |
| { | |
| int fd = open("/dev/mem", O_RDWR | O_SYNC); | |
| if (fd == -1) | |
| die("open(/dev/mem)"); | |
| void *p = mmap(NULL, GPIO_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, | |
| fd, GPIO_BASE); | |
| if (p == MAP_FAILED) | |
| die("mmap(GPIO)"); | |
| gpio = (volatile uint32_t *)p; | |
| gpio_config(); | |
| printf("D0 (GPIO%d): ON\n", PIN_D0); | |
| gpio_d0_on(); | |
| sleep(2); | |
| printf("D0 (GPIO%d): OFF\n", PIN_D0); | |
| gpio_d0_off(); | |
| munmap((void*)gpio, GPIO_SIZE); | |
| close(fd); | |
| exit(EXIT_SUCCESS); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment