Skip to content

Instantly share code, notes, and snippets.

@tsutsui
Created February 16, 2026 17:34
Show Gist options
  • Select an option

  • Save tsutsui/0c0d6c1d7f4e2d5dbaaf210789c51ad7 to your computer and use it in GitHub Desktop.

Select an option

Save tsutsui/0c0d6c1d7f4e2d5dbaaf210789c51ad7 to your computer and use it in GitHub Desktop.
Raspberry Pi 3 GPIO test on NetBSD/evbarm
/*
* 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