diff --git a/README.md b/README.md index fe54592..8a3cf50 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ - -:warning: This library was deprecated by its author in August 2019. Until 31st October 2023 it was maintaining at https://github.com/WiringPi/WiringPi/ but later set to read only because there was no interest in properly maintaining it. -In 2024 GC2 fork the project to maintaining it and to keep the best GPIO Library for Raspberry Pi running. We do our best, but we have limited resources and can not give support. +ℹ️ Since 2024, [GC2](https://github.com/GrazerComputerClub) has taken over maintenance of the project, supporting new OS versions as well as current hardware generations. We are dedicated to keeping the arguably best-performing GPIO Library for Raspberry Pi running smoothly. We strive to do our best, but please note that this is a community effort, and we cannot provide any guarantees or take responsibility for implementing specific features you may need. WiringPi (Unofficial Mirror/Fork) ================================= @@ -42,9 +40,10 @@ wiringPi has been wrapped for multiple languages: Support ------- -Please do not email Gordon if you have issues, he will not be able to help. -Dont' email @Gadgetoid. -Don't email GC2, use issue system of github to report errors. +Please use the [issue system](https://github.com/WiringPi/WiringPi/issues) of GitHub. +Please do not email Gordon if you have issues. +Dont' email @Gadgetoid. +Please don't email GC2 for reporting issues, you might [contact us](wiringpi@gc2.at) for anything that's not for the public eye. Debug ------- diff --git a/VERSION b/VERSION index 80bf4d0..ae0a2e9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.72 +2.73 \ No newline at end of file diff --git a/debian-template/wiringPi/DEBIAN/control b/debian-template/wiringPi/DEBIAN/control index 40262ba..4797516 100644 --- a/debian-template/wiringPi/DEBIAN/control +++ b/debian-template/wiringPi/DEBIAN/control @@ -1,5 +1,5 @@ Package: wiringpi -Version: 2.72 +Version: 2.73 Section: libraries Priority: optional Architecture: armhf diff --git a/gpio/gpio.c b/gpio/gpio.c index a4574a1..7c448a5 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -794,6 +794,31 @@ void doMode (int argc, char *argv []) ********************************************************************************* */ +static void doPadDrivePin (int argc, char *argv []) +{ + + if (argc != 4) { + fprintf (stderr, "Usage: %s drivepin pin value\n", argv [0]) ; + exit (1) ; + } + + int pin = atoi (argv [2]) ; + int val = atoi (argv [3]) ; + + if ((pin < 0) || (pin > 27)) { + fprintf (stderr, "%s: drive pin not 0-27: %d\n", argv [0], pin) ; + exit (1) ; + } + + if ((val < 0) || (val > 3)) { + fprintf (stderr, "%s: drive value not 0-3: %d\n", argv [0], val) ; + exit (1) ; + } + + setPadDrivePin (pin, val) ; +} + + static void doPadDrive (int argc, char *argv []) { int group, val ; @@ -807,7 +832,7 @@ static void doPadDrive (int argc, char *argv []) group = atoi (argv [2]) ; val = atoi (argv [3]) ; - if ((group < 0) || (group > 2)) + if ((group < -1) || (group > 2)) //-1 hidden feature for read and print values { fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ; exit (1) ; @@ -1536,6 +1561,7 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "pwmc" ) == 0) doPwmClock (argc, argv) ; else if (strcasecmp (argv [1], "pwmTone" ) == 0) doPwmTone (argc, argv) ; else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; + else if (strcasecmp (argv [1], "drivepin" ) == 0) doPadDrivePin(argc, argv) ; else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ; else if (strcasecmp (argv [1], "pins" ) == 0) doReadall () ; diff --git a/gpio/readall.c b/gpio/readall.c index 932f8e1..6da28b7 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -75,11 +75,23 @@ static void doReadallExternal (void) ********************************************************************************* */ -static char *alts [] = +static const char unknown_alt[] = " - "; +static const char *alts [] = { - "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3" + "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3", "ALT6", "ALT7", "ALT8", "ALT9" } ; + +static const char* GetAltString(int alt) { + + if (alt>=0 && alt<=11) { + return alts[alt]; + } + + return unknown_alt; +} + + static int physToWpi [64] = { -1, // 0 @@ -177,7 +189,7 @@ static void readallPhys (int physPin) else pin = physToWpi [physPin] ; - printf (" | %4s", alts [getAlt (pin)]) ; + printf (" | %4s", GetAltString(getAlt (pin))) ; printf (" | %d", digitalRead (pin)) ; } @@ -201,7 +213,7 @@ static void readallPhys (int physPin) pin = physToWpi [physPin] ; printf (" | %d", digitalRead (pin)) ; - printf (" | %-4s", alts [getAlt (pin)]) ; + printf (" | %-4s", GetAltString(getAlt (pin))) ; } printf (" | %-5s", physNames [physPin]) ; @@ -233,11 +245,11 @@ static void allReadall (void) for (pin = 0 ; pin < 27 ; ++pin) { printf ("| %3d ", pin) ; - printf ("| %-4s ", alts [getAlt (pin)]) ; + printf ("| %-4s ", GetAltString(getAlt (pin))) ; printf ("| %s ", digitalRead (pin) == HIGH ? "High" : "Low ") ; printf ("| ") ; printf ("| %3d ", pin + 27) ; - printf ("| %-4s ", alts [getAlt (pin + 27)]) ; + printf ("| %-4s ", GetAltString(getAlt (pin + 27))) ; printf ("| %s ", digitalRead (pin + 27) == HIGH ? "High" : "Low ") ; printf ("|\n") ; } @@ -315,6 +327,8 @@ static void plus2header (int model) printf (" +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+\n") ; else if (model == PI_MODEL_400) printf (" +-----+-----+---------+------+---+---Pi 400-+---+------+---------+-----+-----+\n") ; + else if (model == PI_MODEL_5) + printf (" +-----+-----+---------+------+---+---Pi 5---+---+------+---------+-----+-----+\n") ; else printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; } @@ -363,7 +377,8 @@ void doReadall (void) (model == PI_MODEL_3AP) || (model == PI_MODEL_3B) || (model == PI_MODEL_3BP) || (model == PI_MODEL_4B) || (model == PI_MODEL_400) || (model == PI_MODEL_CM4) || - (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W) || (model == PI_MODEL_ZERO_2W)) + (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W) || (model == PI_MODEL_ZERO_2W) || + (model == PI_MODEL_5) ) piPlusReadall (model) ; else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3) || (model == PI_MODEL_CM3P) ) allReadall () ; @@ -401,5 +416,5 @@ void doQmode (int argc, char *argv []) } pin = atoi (argv [2]) ; - printf ("%s\n", alts [getAlt (pin)]) ; + printf ("%s\n", GetAltString(getAlt (pin))) ; } diff --git a/newVersion b/newVersion old mode 100644 new mode 100755 diff --git a/version.h b/version.h index d2d73a4..baffaa8 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "2.72" +#define VERSION "2.73" #define VERSION_MAJOR 2 -#define VERSION_MINOR 72 +#define VERSION_MINOR 73 \ No newline at end of file diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 5fec7c2..382686d 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -123,6 +123,50 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; #define FSEL_ALT4 0b011 #define FSEL_ALT5 0b010 +//RP1 chip (@Pi5) - 3.1.1. Function select +#define RP1_FSEL_ALT0 0x00 +#define RP1_FSEL_GPIO 0x05 //SYS_RIO +#define RP1_FSEL_NONE 0x09 +#define RP1_FSEL_NONE_HW 0x1f //default, mask + +//RP1 chip (@Pi5) RIO address +const unsigned int RP1_RIO_OUT = 0x0000; +const unsigned int RP1_RIO_OE = (0x0004/4); +const unsigned int RP1_RIO_IN = (0x0008/4); + +//RP1 chip (@Pi5) RIO offset for set/clear value +const unsigned int RP1_SET_OFFSET = (0x2000/4); +const unsigned int RP1_CLR_OFFSET = (0x3000/4); + +//RP1 chip (@Pi5) PDE/PDU pull-up/-down enable +const unsigned int RP1_PUD_UP = (1<<3); +const unsigned int RP1_PUD_DOWN = (1<<2); +const unsigned int RP1_INV_PUD_MASK = ~(RP1_PUD_UP | RP1_PUD_DOWN); //~0x0C + +//RP1 chip (@Pi5) pin level, status register +const unsigned int RP1_STATUS_LEVEL_LOW = 0x00400000; +const unsigned int RP1_STATUS_LEVEL_HIGH = 0x00800000; +const unsigned int RP1_STATUS_LEVEL_MASK = 0x00C00000; + +const unsigned int RP1_DEBOUNCE_DEFAULT_VALUE = 4; +const unsigned int RP1_DEBOUNCE_MASK = 0x7f; +const unsigned int RP1_DEBOUNCE_DEFAULT = (RP1_DEBOUNCE_DEFAULT_VALUE << 5); + +const unsigned int RP1_PAD_DEFAULT_0TO8 = (0x0B | 0x70); //Slewfast, Schmitt, PullUp, | 12mA, Input enable +const unsigned int RP1_PAD_DEFAULT_FROM9 = (0x07 | 0x70); //Slewfast, Schmitt, PullDown, | 12mA, Input enable + +const unsigned int RP1_PAD_DRIVE_MASK = 0x00000030; +const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK); + +//RP1 chip (@Pi5) address +const unsigned long long RP1_64_BASE_Addr = 0x1f000d0000; +const unsigned int RP1_BASE_Addr = 0x40000000; +const unsigned int RP1_PWM0_Addr = 0x40098000; // Adress is not mapped to gpiomem device! +const unsigned int RP1_IO0_Addr = 0x400d0000; +const unsigned int RP1_SYS_RIO0_Addr = 0x400e0000; +const unsigned int RP1_PADS0_Addr = 0x400f0000; + + // Access from ARM Running Linux // Taken from Gert/Doms code. Some of this is not in the manual // that I can find )-: @@ -130,11 +174,24 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; // Updates in September 2015 - all now static variables (and apologies for the caps) // due to the Pi v2, v3, etc. and the new /dev/gpiomem interface +const char* gpiomem_global = "/dev/mem"; +const char* gpiomem_BCM = "/dev/gpiomem"; +const char* gpiomem_RP1 = "/dev/gpiomem0"; +const int gpiomem_RP1_Size = 0x00030000; +// PCIe Memory access, static define - maybe needed to detect in future +//dmesg: rp1 0000:01:00.0: bar1 len 0x400000, start 0x1f00000000, end 0x1f003fffff, flags, 0x40200 +const char* pciemem_RP1_path = "/sys/bus/pci/devices/0000:01:00.0"; +const char* pciemem_RP1 = "/sys/bus/pci/devices/0000:01:00.0/resource1"; +const int pciemem_RP1_Size = 0x00400000; +const unsigned short pciemem_RP1_Ventor= 0x1de4; +const unsigned short pciemem_RP1_Device= 0x0001; + static volatile unsigned int GPIO_PADS ; static volatile unsigned int GPIO_CLOCK_BASE ; static volatile unsigned int GPIO_BASE ; static volatile unsigned int GPIO_TIMER ; static volatile unsigned int GPIO_PWM ; +static volatile unsigned int GPIO_RIO ; #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) @@ -188,22 +245,25 @@ static int wiringPiSetuped = FALSE ; // Locals to hold pointers to the hardware +static volatile unsigned int *base ; static volatile unsigned int *gpio ; static volatile unsigned int *pwm ; static volatile unsigned int *clk ; static volatile unsigned int *pads ; static volatile unsigned int *timer ; static volatile unsigned int *timerIrqRaw ; +static volatile unsigned int *rio ; // Export variables for the hardware pointers +volatile unsigned int *_wiringPiBase ; volatile unsigned int *_wiringPiGpio ; volatile unsigned int *_wiringPiPwm ; volatile unsigned int *_wiringPiClk ; volatile unsigned int *_wiringPiPads ; volatile unsigned int *_wiringPiTimer ; volatile unsigned int *_wiringPiTimerIrqRaw ; - +volatile unsigned int *_wiringPiRio ; // Data for use with the boardId functions. // The order of entries here to correspond with the PI_MODEL_X @@ -216,6 +276,7 @@ volatile unsigned int *_wiringPiTimerIrqRaw ; #define GPIO_PERI_BASE_OLD 0x20000000 #define GPIO_PERI_BASE_2835 0x3F000000 #define GPIO_PERI_BASE_2711 0xFE000000 +#define GPIO_PERI_BASE_2712 0x00 //unknown - 32-bit mapped global mem access not supported for now static volatile unsigned int piGpioBase = 0 ; @@ -512,6 +573,21 @@ int GPIOToSysFS(const int pin) { return sysfspin; } +int GetMaxPin() { + return PI_MODEL_5 == RaspberryPiModel ? 27 : 63; +} + + +#define RETURN_ON_MODEL5 if (PI_MODEL_5 == RaspberryPiModel) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; } + +int FailOnModel5() { + if (PI_MODEL_5 == RaspberryPiModel) { + return wiringPiFailure (WPI_ALMOST, "Function not supported on Raspberry Pi 5.\n" + " Unable to continue. Keep an eye of new versions at https://github.com/wiringpi/wiringpi\n") ; + } + return 0; +} + // gpioToGPFSEL: // Map a BCM_GPIO pin to it's Function Selection // control port. (GPFSEL 0-5) @@ -768,6 +844,7 @@ static void usingGpioMemCheck (const char *what) fprintf (stderr, "%s: Unable to do this when using /dev/gpiomem. Try sudo?\n", what) ; exit (EXIT_FAILURE) ; } + } @@ -1186,23 +1263,73 @@ int physPinToGpio (int physPin) * Set the PAD driver value ********************************************************************************* */ +void setPadDrivePin (int pin, int value) { + if (PI_MODEL_5 != RaspberryPiModel) return; + if (pin < 0 || pin > GetMaxPin()) return ; + + uint32_t wrVal; + value = value & 3; // 0-3 supported + wrVal = (value << 4); //Drive strength 0-3 + pads[1+pin] = (pads[1+pin] & RP1_INV_PAD_DRIVE_MASK) | wrVal; + if (wiringPiDebug) { + printf ("setPadDrivePin: pin: %d, value: %d (%08X)\n", pin, value, pads[1+pin]) ; + } +} + void setPadDrive (int group, int value) { - uint32_t wrVal ; + uint32_t wrVal, rdVal; if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { - if ((group < 0) || (group > 2)) - return ; + value = value & 7; // 0-7 supported + if (PI_MODEL_5 == RaspberryPiModel) { + if (-1==group) { + printf ("Pad register:\n"); + for (int pin=0, maxpin=GetMaxPin(); pin<=maxpin; ++pin) { + unsigned int drive = (pads[1+pin] & RP1_PAD_DRIVE_MASK)>>4; + printf (" Pin %2d: 0x%08X drive: 0x%d = %2dmA\n", pin, pads[1+pin], drive, 0==drive ? 2 : drive*4) ; + } + } + if (group !=0) { // only GPIO range @RP1 + return ; + } + switch(value) { + default: + /* bcm*/ // RP1 + case 0: /* 2mA*/ value=0; break; // 2mA + case 1: /* 4mA*/ + case 2: /* 6mA*/ value=1; break; // 4mA + case 3: /* 8mA*/ + case 4: /*10mA*/ value=2; break; // 8mA + case 5: /*12mA*/ + case 6: /*14mA*/ + case 7: /*16mA*/ value=3; break; //12mA + } + wrVal = (value << 4); //Drive strength 0-3 + //set for all pins even when it's avaiable for each pin separately + for (int pin=0, maxpin=GetMaxPin(); pin<=maxpin; ++pin) { + pads[1+pin] = (pads[1+pin] & RP1_INV_PAD_DRIVE_MASK) | wrVal; + } + rdVal = pads[1+17]; // only pin 17 readback, for logging + } else { + if (-1==group) { + printf ("Pad register: Group 0: 0x%08X, Group 1: 0x%08X, Group 2: 0x%08X\n", *(pads + 0 + 11), *(pads + 1 + 11), *(pads + 2 + 11)) ; + } + + if ((group < 0) || (group > 2)) + return ; - wrVal = BCM_PASSWORD | 0x18 | (value & 7) ; - *(pads + group + 11) = wrVal ; + wrVal = BCM_PASSWORD | 0x18 | value; //Drive strength 0-7 + *(pads + group + 11) = wrVal ; + rdVal = *(pads + group + 11); + } if (wiringPiDebug) { printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ; - printf ("Read : %08X\n", *(pads + group + 11)) ; + printf ("Read : %08X\n", rdVal) ; } } } @@ -1228,11 +1355,48 @@ int getAlt (int pin) else if (wiringPiMode != WPI_MODE_GPIO) return 0 ; - fSel = gpioToGPFSEL [pin] ; - shift = gpioToShift [pin] ; + if (PI_MODEL_5 == RaspberryPiModel) { + alt = (gpio[2*pin+1] & RP1_FSEL_NONE_HW); //0-4 function + + /* + BCM: + 000b = GPIO Pin 9 is an input + 001b = GPIO Pin 9 is an output + 100b = GPIO Pin 9 takes alternate function 0 + 101b = GPIO Pin 9 takes alternate function 1 + 110b = GPIO Pin 9 takes alternate function 2 + 111b = GPIO Pin 9 takes alternate function 3 + 011b = GPIO Pin 9 takes alternate function 4 + 010b = GPIO Pin 9 takes alternate function 5 + RP1: + 8 = alternate function 6 + 9 = alternate function 7 + 10 = alternate function 8 + 11 = alternate function 9 + */ + switch(alt) { + case 0: return 4; + case 1: return 5; + case 2: return 6; + case 3: return 7; + case 4: return 3; + case RP1_FSEL_GPIO: { + unsigned int outputmask = gpio[2*pin] & 0x3000; //Bit13-OETOPAD + Bit12-OEFROMPERI + return (outputmask==0x3000) ? 1 : 0; //1=OUT 0=IN + } + case 6: return 8; + case 7: return 9; + case 8: return 10; + case 9: return 11; + default:return alt; + } - alt = (*(gpio + fSel) >> shift) & 7 ; + } else { + fSel = gpioToGPFSEL [pin] ; + shift = gpioToShift [pin] ; + alt = (*(gpio + fSel) >> shift) & 7 ; + } return alt ; } @@ -1247,6 +1411,7 @@ void pwmSetMode (int mode) { if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { + FailOnModel5(); if (mode == PWM_MODE_MS) *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; else @@ -1264,6 +1429,7 @@ void pwmSetMode (int mode) void pwmSetRange (unsigned int range) { + FailOnModel5(); if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; @@ -1284,6 +1450,7 @@ void pwmSetClock (int divisor) { uint32_t pwm_control ; + FailOnModel5(); if (piGpioBase == GPIO_PERI_BASE_2711) { divisor = 540*divisor/192; @@ -1335,6 +1502,7 @@ void gpioClockSet (int pin, int freq) { int divi, divr, divf ; + FailOnModel5(); pin &= 63 ; /**/ if (wiringPiMode == WPI_MODE_PINS) @@ -1466,6 +1634,7 @@ void pinModeAlt (int pin, int mode) { int fSel, shift ; + RETURN_ON_MODEL5 setupCheck ("pinModeAlt") ; if ((pin & PI_GPIO_MASK) == 0) // On-board pin @@ -1477,10 +1646,25 @@ void pinModeAlt (int pin, int mode) else if (wiringPiMode != WPI_MODE_GPIO) return ; - fSel = gpioToGPFSEL [pin] ; - shift = gpioToShift [pin] ; + if (PI_MODEL_5 == RaspberryPiModel) { + + //confusion! diffrent to to BCM! this is taking directly the value for the register + /* + "alt0" 0b100 + "alt1" 0b101 + "alt2" 0b110 + "alt3" 0b111 + "alt4" 0b011 + "alt5" 0b010 + */ + gpio[2*pin+1] = (mode & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time + } else { + fSel = gpioToGPFSEL [pin] ; + shift = gpioToShift [pin] ; + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; + } - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; } } @@ -1491,12 +1675,21 @@ void pinModeAlt (int pin, int mode) ********************************************************************************* */ +//Default: rp1_set_pad(pin, 0, 1, 0, 1, 1, 1, 0); +void rp1_set_pad(int pin, int slewfast, int schmitt, int pulldown, int pullup, int drive, int inputenable, int outputdisable) { + + pads[1+pin] = (slewfast != 0) | ((schmitt != 0) << 1) | ((pulldown != 0) << 2) | ((pullup != 0) << 3) | ((drive & 0x3) << 4) | ((inputenable != 0) << 6) | ((outputdisable != 0) << 7); +} + void pinMode (int pin, int mode) { int fSel, shift, alt ; struct wiringPiNodeStruct *node = wiringPiNodes ; int origPin = pin ; + if (wiringPiDebug) + printf ("pinMode: pin:%d mode:%d\n", pin, mode) ; + setupCheck ("pinMode") ; if ((pin & PI_GPIO_MASK) == 0) // On-board pin @@ -1508,27 +1701,43 @@ void pinMode (int pin, int mode) else if (wiringPiMode != WPI_MODE_GPIO) return ; + if (wiringPiDebug) + printf ("pinMode: bcm pin:%d mode:%d\n", pin, mode) ; + softPwmStop (origPin) ; softToneStop (origPin) ; fSel = gpioToGPFSEL [pin] ; shift = gpioToShift [pin] ; - /**/ if (mode == INPUT) - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input - else if (mode == OUTPUT) - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ; - else if (mode == SOFT_PWM_OUTPUT) + if (mode == INPUT) { + if (PI_MODEL_5 == RaspberryPiModel) { + pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; + gpio[2*pin+1] = RP1_FSEL_GPIO | RP1_DEBOUNCE_DEFAULT; // GPIO + rio[RP1_RIO_OE + RP1_CLR_OFFSET] = 1<>4); - int pullshift = (pin & 0xf) << 1; - unsigned int pullbits; - unsigned int pull; - - switch (pud) - { - case PUD_OFF: pull = 0; break; - case PUD_UP: pull = 1; break; - case PUD_DOWN: pull = 2; break; + if (PI_MODEL_5 == RaspberryPiModel) { + unsigned int pullbits = pads[1+pin] & RP1_INV_PUD_MASK; // remove bits + switch (pud){ + case PUD_OFF: pads[1+pin] = pullbits; break; + case PUD_UP: pads[1+pin] = pullbits | RP1_PUD_UP; break; + case PUD_DOWN: pads[1+pin] = pullbits | RP1_PUD_DOWN; break; default: return ; /* An illegal value */ } + } else { + 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; + + 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) ; - 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) ; + *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + } } } else // Extension module @@ -1655,10 +1876,18 @@ int digitalRead (int pin) else if (wiringPiMode != WPI_MODE_GPIO) return LOW ; - if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0) - return HIGH ; - else - return LOW ; + if (PI_MODEL_5 == RaspberryPiModel) { + switch(gpio[2*pin] & RP1_STATUS_LEVEL_MASK) { + default: // 11 or 00 not allowed, give LOW! + case RP1_STATUS_LEVEL_LOW: return LOW ; + case RP1_STATUS_LEVEL_HIGH: return HIGH ; + } + } else { + if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0) + return HIGH ; + else + return LOW ; + } } else { @@ -1704,12 +1933,12 @@ void digitalWrite (int pin, int value) { /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode { - if (sysFds [pin] != -1) + if (sysFds [pin] != -1) { - if (value == LOW) - write (sysFds [pin], "0\n", 2) ; - else - write (sysFds [pin], "1\n", 2) ; + if (value == LOW) + write (sysFds [pin], "0\n", 2) ; + else + write (sysFds [pin], "1\n", 2) ; } return ; } @@ -1719,11 +1948,20 @@ void digitalWrite (int pin, int value) pin = physToGpio [pin] ; else if (wiringPiMode != WPI_MODE_GPIO) return ; - - if (value == LOW) - *(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ; - else - *(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ; + if (PI_MODEL_5 == RaspberryPiModel) { + if (value == LOW) { + //printf("Set pin %d >>0x%08x<< to low\n", pin, 1<>0x%08x<< to high\n", pin, 1< 63)) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", pin) ; + if (pin < 0 || pin > maxpin) + return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-%d (%d)\n", maxpin, pin) ; /**/ if (wiringPiMode == WPI_MODE_UNINITIALISED) return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; @@ -2384,6 +2632,11 @@ int wiringPiSetup (void) piGpioPupOffset = GPPUPPDN0 ; break ; + case PI_MODEL_5: + piGpioBase = GPIO_PERI_BASE_2712 ; + piGpioPupOffset = 0 ; + break ; + default: piGpioBase = GPIO_PERI_BASE_2835 ; piGpioPupOffset = GPPUD ; @@ -2395,37 +2648,46 @@ int wiringPiSetup (void) // Try /dev/mem. If that fails, then // try /dev/gpiomem. If that fails then game over. + const char* gpiomemGlobal = gpiomem_global; + const char* gpiomemModule = gpiomem_BCM; + if (PI_MODEL_5 == model) { - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Raspberry Pi 5 not supported.\n" - " Unable to continue. Keep an eye of new versions at https://github.com/GrazerComputerClub/WiringPi\n") ; + gpiomemGlobal = pciemem_RP1; + gpiomemModule = gpiomem_RP1; } - if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0) + if (gpiomemGlobal==NULL || (fd = open (gpiomemGlobal, O_RDWR | O_SYNC | O_CLOEXEC)) < 0) { - if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem + + if (gpiomemModule && (fd = open (gpiomemModule, O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem { piGpioBase = 0 ; usingGpioMem = TRUE ; } else - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n" + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open %s or %s: %s.\n" " Aborting your program because if it can not access the GPIO\n" " hardware then it most certianly won't work\n" - " Try running with sudo?\n", strerror (errno)) ; + " Try running with sudo?\n", gpiomemGlobal, gpiomemModule, strerror (errno)) ; } + if (wiringPiDebug) { + printf ("wiringPi: access to %s succeded\n", usingGpioMem ? gpiomemModule : gpiomemGlobal) ; + } +// GPIO: + if (PI_MODEL_5 != model) { + //Set the offsets into the memory interface. - //Set the offsets into the memory interface. - - GPIO_PADS = piGpioBase + 0x00100000 ; - GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; - GPIO_BASE = piGpioBase + 0x00200000 ; - GPIO_TIMER = piGpioBase + 0x0000B000 ; - GPIO_PWM = piGpioBase + 0x0020C000 ; + GPIO_PADS = piGpioBase + 0x00100000 ; + GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; + GPIO_BASE = piGpioBase + 0x00200000 ; + GPIO_TIMER = piGpioBase + 0x0000B000 ; + GPIO_PWM = piGpioBase + 0x0020C000 ; + GPIO_RIO = 0x00 ; // Map the individual hardware components -// GPIO: - if (PI_MODEL_5 != model) { + // GPIO: + base = NULL; gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; if (gpio == MAP_FAILED) return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; @@ -2462,23 +2724,55 @@ int wiringPiSetup (void) *(timer + TIMER_PRE_DIV) = 0x00000F9 ; timerIrqRaw = timer + TIMER_IRQ_RAW ; + // Export the base addresses for any external software that might need them + _wiringPiBase = base ; _wiringPiGpio = gpio ; _wiringPiPwm = pwm ; _wiringPiClk = clk ; _wiringPiPads = pads ; _wiringPiTimer = timer ; + _wiringPiRio = NULL ; } else { - _wiringPiGpio = NULL ; + unsigned int MMAP_size = (usingGpioMem) ? gpiomem_RP1_Size : pciemem_RP1_Size; + + GPIO_PADS = (RP1_PADS0_Addr-RP1_IO0_Addr) ; + GPIO_CLOCK_BASE = 0x00; + GPIO_BASE = (RP1_IO0_Addr-RP1_BASE_Addr) ; + GPIO_TIMER = 0x00; + GPIO_PWM = RP1_PWM0_Addr-RP1_BASE_Addr; + GPIO_RIO = (RP1_SYS_RIO0_Addr-RP1_IO0_Addr) ; + + //map hole RP1 memory block from beginning, + base = (unsigned int *)mmap(0, MMAP_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x00000000) ; + if (base == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ; + if (usingGpioMem) { + gpio = base; // RP1 start adress of map memory for gpio (same as module memory) + } else { + gpio = &base[GPIO_BASE/4];// RP1 start adress of map memory for gpio + } + pads = &gpio[GPIO_PADS/4]; // RP1 start adress of map memory for pads + rio = &gpio[GPIO_RIO/4]; // RP1 start adress of map memory for rio + GPIO_PADS += GPIO_BASE; + GPIO_RIO += GPIO_BASE; + + // Export the base addresses for any external software that might need them + _wiringPiBase = base ; + _wiringPiGpio = gpio ; _wiringPiPwm = NULL ; _wiringPiClk = NULL ; - _wiringPiPads = NULL ; + _wiringPiPads = pads ; _wiringPiTimer = NULL ; - } - - -// Export the base addresses for any external software that might need them - - + _wiringPiRio = rio ; + } + if (wiringPiDebug) { + printf ("wiringPi: memory map gpio 0x%x %s\n", GPIO_BASE , _wiringPiGpio ? "valid" : "invalid"); + printf ("wiringPi: memory map pads 0x%x %s\n", GPIO_PADS , _wiringPiPads ? "valid" : "invalid"); + printf ("wiringPi: memory map rio 0x%x %s\n", GPIO_RIO , _wiringPiRio ? "valid" : "invalid"); + printf ("wiringPi: memory map pwm 0x%x %s\n", GPIO_PWM , _wiringPiPwm ? "valid" : "invalid"); + printf ("wiringPi: memory map clk 0x%x %s\n", GPIO_CLOCK_BASE, _wiringPiClk ? "valid" : "invalid"); + printf ("wiringPi: memory map timer 0x%x %s\n", GPIO_TIMER,_wiringPiTimer ? "valid" : "invalid"); + } initialiseEpoch () ; @@ -2541,7 +2835,6 @@ int wiringPiSetupPhys (void) int wiringPiSetupSys (void) { - int pin ; char fName [128] ; if (wiringPiSetuped) @@ -2575,7 +2868,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) + for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin) { int pinFS = GPIOToSysFS(pin); if (pinFS>=0) { diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 0f5cd1c..462900e 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -236,6 +236,7 @@ extern void piBoardId (int *model, int *rev, int *mem, int *m extern int wpiPinToGpio (int wpiPin) ; extern int physPinToGpio (int physPin) ; extern void setPadDrive (int group, int value) ; +extern void setPadDrivePin (int pin, int value); // Interface V2 extern int getAlt (int pin) ; extern void pwmToneWrite (int pin, int freq) ; extern void pwmSetMode (int mode) ;