From aca883a051a32f2513b1db90a74efddd0c714ccf Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Sat, 14 Dec 2019 01:09:13 +0000 Subject: [PATCH 1/4] Add support for Raspberry Pi 4B This change make the following commands correctly detect the 4B however there may be an issue with reading GPIO inputs on the 4B as they are always returning zero. The aim of this change is to be the source-equivalent of the binary package release 2.52[1] which was the last release before upstream development ceased. [1] http://wiringpi.com/wiringpi-updated-to-2-52-for-the-raspberry-pi-4b/ --- gpio/readall.c | 7 +++++-- wiringPi/wiringPi.c | 36 ++++++++++++++++++------------------ wiringPi/wiringPi.h | 5 +++-- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/gpio/readall.c b/gpio/readall.c index 097755a..2d745a4 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -80,7 +80,7 @@ static char *alts [] = "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3" } ; -static int physToWpi [64] = +static int physToWpi [64] = { -1, // 0 -1, -1, // 1, 2 @@ -113,7 +113,7 @@ static int physToWpi [64] = -1, -1, -1, -1, -1, -1, -1, -1, -1 } ; -static char *physNames [64] = +static char *physNames [64] = { NULL, @@ -309,6 +309,8 @@ static void plus2header (int model) printf (" +-----+-----+---------+------+---+---Pi 3B+-+---+------+---------+-----+-----+\n") ; else if (model == PI_MODEL_3AP) printf (" +-----+-----+---------+------+---+---Pi 3A+-+---+------+---------+-----+-----+\n") ; + else if (model == PI_MODEL_4B) + printf (" +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+\n") ; else printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; } @@ -356,6 +358,7 @@ void doReadall (void) (model == PI_MODEL_2) || (model == PI_MODEL_3AP) || (model == PI_MODEL_3B) || (model == PI_MODEL_3BP) || + (model == PI_MODEL_4B) || (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W)) piPlusReadall (model) ; else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3) || ((model == PI_MODEL_CM3P))) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 3db6866..73ec220 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -237,7 +237,7 @@ const char *piModelNames [20] = "Pi 3A+", // 14 "Unknown15", // 15 "CM3+", // 16 - "Unknown17", // 17 + "Pi 4B", // 17 "Unknown18", // 18 "Unknown19", // 19 } ; @@ -818,7 +818,7 @@ int piGpioLayout (void) for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) *c = 0 ; - + if (wiringPiDebug) printf ("piGpioLayout: Revision string: %s\n", line) ; @@ -887,7 +887,7 @@ int piBoardRev (void) * So the distinction between boards that I can see is: * * 0000 - Error - * 0001 - Not used + * 0001 - Not used * * Original Pi boards: * 0002 - Model B, Rev 1, 256MB, Egoman @@ -972,7 +972,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) *c = 0 ; - + if (wiringPiDebug) printf ("piBoardId: Revision string: %s\n", line) ; @@ -1011,7 +1011,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) bMfg = (revision & (0x0F << 16)) >> 16 ; bMem = (revision & (0x07 << 20)) >> 20 ; bWarranty = (revision & (0x03 << 24)) != 0 ; - + *model = bType ; *rev = bRev ; *mem = bMem ; @@ -1038,7 +1038,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) // If longer than 4, we'll assume it's been overvolted *warranty = strlen (c) > 4 ; - + // Extract last 4 characters: c = c + strlen (c) - 4 ; @@ -1078,7 +1078,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = 0 ; } } } - + /* @@ -1264,7 +1264,7 @@ void gpioClockSet (int pin, int freq) pin = physToGpio [pin] ; else if (wiringPiMode != WPI_MODE_GPIO) return ; - + divi = 19200000 / freq ; divr = 19200000 % freq ; divf = (int)((double)divr * 4096.0 / 19200000.0) ; @@ -1510,7 +1510,7 @@ void pullUpDnControl (int pin, int pud) *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; - + *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; } @@ -1684,7 +1684,7 @@ void pwmWrite (int pin, int value) /* * analogRead: - * Read the analog value of a given Pin. + * Read the analog value of a given Pin. * There is no on-board Pi analog hardware, * so this needs to go to a new node. ********************************************************************************* @@ -1703,7 +1703,7 @@ int analogRead (int pin) /* * analogWrite: - * Write the analog value to the given Pin. + * Write the analog value to the given Pin. * There is no on-board Pi analog hardware, * so this needs to go to a new node. ********************************************************************************* @@ -1752,7 +1752,7 @@ void pwmToneWrite (int pin, int freq) * Write an 8-bit byte to the first 8 GPIO pins - try to do it as * fast as possible. * However it still needs 2 operations to set the bits, so any external - * hardware must not rely on seeing a change as there will be a change + * hardware must not rely on seeing a change as there will be a change * to set the outputs bits to zero, then another change to set the 1's * Reading is just bit fiddling. * These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers @@ -1808,7 +1808,7 @@ unsigned int digitalReadByte (void) data = (data << 1) | x ; } } - else + else { raw = *(gpio + gpioToGPLEV [0]) ; // First bank for these pins for (pin = 0 ; pin < 8 ; ++pin) @@ -1865,7 +1865,7 @@ unsigned int digitalReadByte2 (void) data = (data << 1) | x ; } } - else + else data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins return data ; @@ -2277,7 +2277,7 @@ int wiringPiSetup (void) // Open the master /dev/ memory control device // Device strategy: December 2016: -// Try /dev/mem. If that fails, then +// Try /dev/mem. If that fails, then // try /dev/gpiomem. If that fails then game over. if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0) @@ -2315,13 +2315,13 @@ int wiringPiSetup (void) pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; if (pwm == MAP_FAILED) return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; - + // Clock control (needed for PWM) clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; if (clk == MAP_FAILED) return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; - + // The drive pads pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; @@ -2441,7 +2441,7 @@ int wiringPiSetupSys (void) // Open and scan the directory, looking for exported GPIOs, and pre-open // the 'value' interface to speed things up for later - + for (pin = 0 ; pin < 64 ; ++pin) { sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 0ff0c92..ecce383 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -102,6 +102,7 @@ #define PI_MODEL_3BP 13 #define PI_MODEL_3AP 14 #define PI_MODEL_CM3P 16 +#define PI_MODEL_4B 17 #define PI_VERSION_1 0 #define PI_VERSION_1_1 1 @@ -134,7 +135,7 @@ extern const int piMemorySize [ 8] ; // wiringPiNodeStruct: // This describes additional device nodes in the extended wiringPi // 2.0 scheme of things. -// It's a simple linked list for now, but will hopefully migrate to +// It's a simple linked list for now, but will hopefully migrate to // a binary tree for efficiency reasons - but then again, the chances // of more than 1 or 2 devices being added are fairly slim, so who // knows.... @@ -211,7 +212,7 @@ extern void pwmWrite (int pin, int value) ; extern int analogRead (int pin) ; extern void analogWrite (int pin, int value) ; -// PiFace specifics +// PiFace specifics // (Deprecated) extern int wiringPiSetupPiFace (void) ; From a49f696232809cede14f8e4de3eb118bd5fbd037 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Sat, 14 Dec 2019 02:01:23 +0000 Subject: [PATCH 2/4] Use correct peripheral address for Pi4B --- wiringPi/wiringPi.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 73ec220..2d581e9 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -213,8 +213,9 @@ volatile unsigned int *_wiringPiTimerIrqRaw ; // piGpioBase: // The base address of the GPIO memory mapped hardware IO -#define GPIO_PERI_BASE_OLD 0x20000000 -#define GPIO_PERI_BASE_NEW 0x3F000000 +#define GPIO_PERI_BASE_OLD 0x20000000 +#define GPIO_PERI_BASE_2708 0x3F000000 +#define GPIO_PERI_BASE_2711 0xFE000000 static volatile unsigned int piGpioBase = 0 ; @@ -1533,7 +1534,6 @@ int digitalRead (int pin) { char c ; struct wiringPiNodeStruct *node = wiringPiNodes ; - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode @@ -2243,7 +2243,9 @@ int wiringPiSetup (void) piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3) || (model == PI_MODEL_CM3P)) + if ((model == PI_MODEL_CM) || + (model == PI_MODEL_CM3) || + (model == PI_MODEL_CM3P)) wiringPiMode = WPI_MODE_GPIO ; else wiringPiMode = WPI_MODE_PINS ; @@ -2270,8 +2272,12 @@ int wiringPiSetup (void) piGpioBase = GPIO_PERI_BASE_OLD ; break ; + case PI_MODEL_4B: + piGpioBase = GPIO_PERI_BASE_2711 ; + break ; + default: - piGpioBase = GPIO_PERI_BASE_NEW ; + piGpioBase = GPIO_PERI_BASE_2708 ; break ; } From 41f941a78ee929406bcda6c3f80ea6d554e5a48b Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Sat, 14 Dec 2019 20:42:06 +0000 Subject: [PATCH 3/4] Fix GPIO pull up/down for Pi4B Based on this raspi-gpio commit[1] the 2711 chip uses a different method for pull up/down. This change implements that same method. With this change, wiringPi now works for the Pi4B with the subset of functionality used by zynthian. [1] https://github.com/RPi-Distro/raspi-gpio/commit/80fa7d04eafb3ea34fc6f2d32de5f1873b5fb369?diff=unified --- wiringPi/wiringPi.c | 48 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 2d581e9..76f5684 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -214,7 +214,7 @@ volatile unsigned int *_wiringPiTimerIrqRaw ; // The base address of the GPIO memory mapped hardware IO #define GPIO_PERI_BASE_OLD 0x20000000 -#define GPIO_PERI_BASE_2708 0x3F000000 +#define GPIO_PERI_BASE_2835 0x3F000000 #define GPIO_PERI_BASE_2711 0xFE000000 static volatile unsigned int piGpioBase = 0 ; @@ -543,6 +543,14 @@ static uint8_t gpioToFEN [] = #define GPPUD 37 +/* 2711 has a different mechanism for pin pull-up/down/enable */ +#define GPPUPPDN0 57 /* Pin pull-up/down for pins 15:0 */ +#define GPPUPPDN1 58 /* Pin pull-up/down for pins 31:16 */ +#define GPPUPPDN2 59 /* Pin pull-up/down for pins 47:32 */ +#define GPPUPPDN3 60 /* Pin pull-up/down for pins 57:48 */ + +static volatile unsigned int piGpioPupOffset = 0 ; + // gpioToPUDCLK // (Word) offset to the Pull Up Down Clock regsiter @@ -1509,11 +1517,36 @@ void pullUpDnControl (int pin, int pud) else if (wiringPiMode != WPI_MODE_GPIO) return ; - *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; + if (piGpioPupOffset == GPPUPPDN0) + { + // Pi 4B pull up/down method + int pullreg = GPPUPPDN0 + (pin>>4); + int pullshift = (pin & 0xf) << 1; + unsigned int pullbits; + unsigned int pull; - *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + switch (pud) + { + case PUD_OFF: pull = 0; break; + case PUD_UP: pull = 1; break; + case PUD_DOWN: pull = 2; break; + default: return ; /* An illegal value */ + } + + pullbits = *(gpio + pullreg); + pullbits &= ~(3 << pullshift); + pullbits |= (pull << pullshift); + *(gpio + pullreg) = pullbits; + } + else + { + // legacy pull up/down method + *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; + + *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + } } else // Extension module { @@ -2270,14 +2303,17 @@ int wiringPiSetup (void) case PI_ALPHA: case PI_MODEL_CM: case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: piGpioBase = GPIO_PERI_BASE_OLD ; + piGpioPupOffset = GPPUD ; break ; case PI_MODEL_4B: piGpioBase = GPIO_PERI_BASE_2711 ; + piGpioPupOffset = GPPUPPDN0 ; break ; default: - piGpioBase = GPIO_PERI_BASE_2708 ; + piGpioBase = GPIO_PERI_BASE_2835 ; + piGpioPupOffset = GPPUD ; break ; } From 9aed9a44154eb68c2461aa72e1b32d85680fc1ae Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Sat, 14 Dec 2019 20:45:00 +0000 Subject: [PATCH 4/4] Increment version to 2.60 Now that the upstream maintainer has abandoned this project without establishing another maintainer, its difficult to choose an appropriate version number. Going with 2.60 for now, as this only has incremental changes to support 4B. --- VERSION | 2 +- version.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index f02fc20..f6a4163 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.50 +2.60 diff --git a/version.h b/version.h index 07e50ef..812dbdc 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "2.50" +#define VERSION "2.60" #define VERSION_MAJOR 2 -#define VERSION_MINOR 50 +#define VERSION_MINOR 60