From 97be9408bd47779b28f0660f9fee91565a8117f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20de=20Metz?= Date: Wed, 15 Jul 2020 17:37:50 +0200 Subject: [PATCH] Update to raspberry-gpio-python version 0.7. --- ext/rpi_gpio/c_gpio.c | 111 +++++++++++++++++++++++------------------- ext/rpi_gpio/c_gpio.h | 10 ++-- 2 files changed, 67 insertions(+), 54 deletions(-) diff --git a/ext/rpi_gpio/c_gpio.c b/ext/rpi_gpio/c_gpio.c index e9a5366..985a2f7 100644 --- a/ext/rpi_gpio/c_gpio.c +++ b/ext/rpi_gpio/c_gpio.c @@ -3,7 +3,7 @@ Original code by Ben Croston modified for Ruby by Nick Lowery (github.com/clockvapor) Copyright (c) 2014-2016 Nick Lowery -Copyright (c) 2013-2015 Ben Croston +Copyright (c) 2013-2019 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -47,6 +47,11 @@ SOFTWARE. #define PULLUPDN_OFFSET 37 // 0x0094 / 4 #define PULLUPDNCLK_OFFSET 38 // 0x0098 / 4 +#define PULLUPDN_OFFSET_2711_0 57 +#define PULLUPDN_OFFSET_2711_1 58 +#define PULLUPDN_OFFSET_2711_2 59 +#define PULLUPDN_OFFSET_2711_3 60 + #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) @@ -65,7 +70,7 @@ int setup(void) { int mem_fd; uint8_t *gpio_mem; - uint32_t peri_base; + uint32_t peri_base = 0; uint32_t gpio_base; unsigned char buf[4]; FILE *fp; @@ -76,8 +81,7 @@ int setup(void) // try /dev/gpiomem first - this does not require root privs if ((mem_fd = open("/dev/gpiomem", O_RDWR|O_SYNC)) > 0) { - gpio_map = (uint32_t *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0); - if ((uint32_t)gpio_map < 0) { + if ((gpio_map = (uint32_t *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0)) == MAP_FAILED) { return SETUP_MMAP_FAIL; } else { return SETUP_OK; @@ -99,8 +103,7 @@ int setup(void) if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) return SETUP_CPUINFO_FAIL; - while(!feof(fp) && !found) { - fgets(buffer, sizeof(buffer), fp); + while(!feof(fp) && !found && fgets(buffer, sizeof(buffer), fp)) { sscanf(buffer, "Hardware : %s", hardware); if (strcmp(hardware, "BCM2708") == 0 || strcmp(hardware, "BCM2835") == 0) { // pi 1 hardware @@ -117,26 +120,22 @@ int setup(void) return SETUP_NOT_RPI_FAIL; } + if (!peri_base) + return SETUP_NOT_RPI_FAIL; gpio_base = peri_base + GPIO_BASE_OFFSET; // mmap the GPIO memory registers - if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) return SETUP_DEVMEM_FAIL; - } - if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) { + if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) return SETUP_MALLOC_FAIL; - } - if ((uint32_t)gpio_mem % PAGE_SIZE) { - gpio_mem += PAGE_SIZE - ((uint32_t) gpio_mem % PAGE_SIZE); - } - - gpio_map = (uint32_t *) mmap((void *) gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, gpio_base); + if ((uint32_t)gpio_mem % PAGE_SIZE) + gpio_mem += PAGE_SIZE - ((uint32_t)gpio_mem % PAGE_SIZE); - if ((uint32_t) gpio_map < 0) { + if ((gpio_map = (uint32_t *)mmap( (void *)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, gpio_base)) == MAP_FAILED) return SETUP_MMAP_FAIL; - } return SETUP_OK; } @@ -158,9 +157,8 @@ int eventdetected(int gpio) offset = EVENT_DETECT_OFFSET + (gpio/32); bit = (1 << (gpio%32)); value = *(gpio_map+offset) & bit; - if (value) { + if (value) clear_event_detect(gpio); - } return value; } @@ -169,11 +167,10 @@ void set_rising_event(int gpio, int enable) int offset = RISING_ED_OFFSET + (gpio/32); int shift = (gpio%32); - if (enable) { + if (enable) *(gpio_map+offset) |= 1 << shift; - } else { + else *(gpio_map+offset) &= ~(1 << shift); - } clear_event_detect(gpio); } @@ -196,11 +193,10 @@ void set_high_event(int gpio, int enable) int offset = HIGH_DETECT_OFFSET + (gpio/32); int shift = (gpio%32); - if (enable) { + if (enable) *(gpio_map+offset) |= (1 << shift); - } else { + else *(gpio_map+offset) &= ~(1 << shift); - } clear_event_detect(gpio); } @@ -209,33 +205,51 @@ void set_low_event(int gpio, int enable) int offset = LOW_DETECT_OFFSET + (gpio/32); int shift = (gpio%32); - if (enable) { + if (enable) *(gpio_map+offset) |= 1 << shift; - } else { + else *(gpio_map+offset) &= ~(1 << shift); - } clear_event_detect(gpio); } void set_pullupdn(int gpio, int pud) { - int clk_offset = PULLUPDNCLK_OFFSET + (gpio/32); - int shift = (gpio%32); - - if (pud == PUD_DOWN) { - *(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | - PUD_DOWN; - } else if (pud == PUD_UP) { - *(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_UP; - } else { // pud == PUD_OFF + // Check GPIO register + int is2711 = *(gpio_map+PULLUPDN_OFFSET_2711_3) != 0x6770696f; + if (is2711) { + // Pi 4 Pull-up/down method + int pullreg = PULLUPDN_OFFSET_2711_0 + (gpio >> 4); + int pullshift = (gpio & 0xf) << 1; + unsigned int pullbits; + unsigned int pull = 0; + switch (pud) { + case PUD_OFF: pull = 0; break; + case PUD_UP: pull = 1; break; + case PUD_DOWN: pull = 2; break; + default: pull = 0; // switch PUD to OFF for other values + } + pullbits = *(gpio_map + pullreg); + pullbits &= ~(3 << pullshift); + pullbits |= (pull << pullshift); + *(gpio_map + pullreg) = pullbits; + } else { + // Legacy Pull-up/down method + int clk_offset = PULLUPDNCLK_OFFSET + (gpio/32); + int shift = (gpio%32); + + if (pud == PUD_DOWN) { + *(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_DOWN; + } else if (pud == PUD_UP) { + *(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_UP; + } else { // pud == PUD_OFF + *(gpio_map+PULLUPDN_OFFSET) &= ~3; + } + short_wait(); + *(gpio_map+clk_offset) = 1 << shift; + short_wait(); *(gpio_map+PULLUPDN_OFFSET) &= ~3; + *(gpio_map+clk_offset) = 0; } - - short_wait(); - *(gpio_map+clk_offset) = 1 << shift; - short_wait(); - *(gpio_map+PULLUPDN_OFFSET) &= ~3; - *(gpio_map+clk_offset) = 0; } void setup_gpio(int gpio, int direction, int pud) @@ -265,12 +279,11 @@ void output_gpio(int gpio, int value) { int offset, shift; - if (value) { // value == HIGH + if (value) // value == HIGH offset = SET_OFFSET + (gpio/32); - } else { // value == LOW - offset = CLR_OFFSET + (gpio/32); - } - + else // value == LOW + offset = CLR_OFFSET + (gpio/32); + shift = (gpio%32); *(gpio_map+offset) = 1 << shift; @@ -288,5 +301,5 @@ int input_gpio(int gpio) void cleanup(void) { - munmap((void *) gpio_map, BLOCK_SIZE); + munmap((void *)gpio_map, BLOCK_SIZE); } diff --git a/ext/rpi_gpio/c_gpio.h b/ext/rpi_gpio/c_gpio.h index 398f204..26ba3af 100644 --- a/ext/rpi_gpio/c_gpio.h +++ b/ext/rpi_gpio/c_gpio.h @@ -3,7 +3,7 @@ Original code by Ben Croston modified for Ruby by Nick Lowery (github.com/clockvapor) Copyright (c) 2014-2016 Nick Lowery -Copyright (c) 2013-2015 Ben Croston +Copyright (c) 2013-2019 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -36,10 +36,10 @@ void set_low_event(int gpio, int enable); int eventdetected(int gpio); void cleanup(void); -#define SETUP_OK 0 -#define SETUP_DEVMEM_FAIL 1 -#define SETUP_MALLOC_FAIL 2 -#define SETUP_MMAP_FAIL 3 +#define SETUP_OK 0 +#define SETUP_DEVMEM_FAIL 1 +#define SETUP_MALLOC_FAIL 2 +#define SETUP_MMAP_FAIL 3 #define SETUP_CPUINFO_FAIL 4 #define SETUP_NOT_RPI_FAIL 5