5

I can't seem to set the pull-up resistor mode on the PI4 with most methods I try. I have tried: C# (the new System.Device.Gpio interface), WiringPi (using a C# abstraction), and wiringPi command line interface. Setting the pin mode to input or output always works, just not changing the pull up mode. If I use an example python script, the mode does change, so the hardware is likely not broken.

Steps to reproduce:

root@raspberrypi:/home/pi# gpio -g mode 24 in
root@raspberrypi:/home/pi# gpio -g mode 24 up
root@raspberrypi:/home/pi# gpio -g read 24 
0 
root@raspberrypi:/home/pi#

There's nothing connected to BCM Pin 24, so the result should be 1. Same result with WiringPi 2.50 and 2.52. Same result on other pins.

Edit: Update after some time has passed

WiringPi is deprecated, but there's an unofficial release here that works on the Pi4. Just use that one (particularly helpful are still the command line options)

System.Device.GPIO nuget for C# has been updated too. It seamlessly supports the Pi4/400 now as well.

PMF
  • 906
  • 7
  • 14

4 Answers4

4

I can confirm that result with version 2.52 of wiringPi, setting the pulls does not work on the Pi4B.

wiringPi is now deprecated.

http://wiringpi.com/wiringpi-deprecated/

You could contact the author but do not expect a response.

joan
  • 71,852
  • 5
  • 76
  • 108
2

I have run into the very same issue, setting pull-up with latest wiringPI (2.52) on the 4B+ does not work. I solved it by using 'raspi-gpio' utility ( https://github.com/RPi-Distro/raspi-gpio ) to just activate the pull-ups via commandline, which worked fine with my 4B+ Just be aware that raspi-gpio do use 'BCM' numbering. So in your case for GPIO.24 you need to use '13'; the raspi-gpio line would be 'raspi-gpio set 13 pu'

hope that helps

lisy.dev
  • 21
  • 1
2

Although WiringPi is discontinued, there was an unofficial patch.

(Open-source is hard to kill, others will continue it.)

Tested, and GPIO worked great on my RaspberryPi4 after applying that.

Patch:

diff -ruN wiringPi/wiringPi.c wiringPi/wiringPi.c
--- wiringPi/wiringPi.c
+++ wiringPi/wiringPi.c
@@ -215,6 +215,7 @@ volatile unsigned int *_wiringPiTimerIrqRaw ;

#define GPIO_PERI_BASE_OLD 0x20000000 #define GPIO_PERI_BASE_NEW 0x3F000000 +#define GPIO_PERI_BASE_RP4 0xFE000000

static volatile unsigned int piGpioBase = 0 ;

@@ -547,6 +548,10 @@ static uint8_t gpioToPUDCLK [] = 39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, } ;

+#define PULLUPDN_OFFSET_2711_0 57 +#define PULLUPDN_OFFSET_2711_1 58 +#define PULLUPDN_OFFSET_2711_2 59 +#define PULLUPDN_OFFSET_2711_3 60

// gpioToPwmALT // the ALT value to put a GPIO pin into PWM mode @@ -814,7 +819,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) ;

@@ -883,7 +888,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
      

@@ -955,6 +960,30 @@ void piBoardId (int model, int rev, int mem, int maker, int *warranty) if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) piGpioLayoutOops ("Unable to open /proc/cpuinfo") ;

  • char buffer[12] ;
  • const char *ranges_file = "/proc/device-tree/soc/ranges" ;
  • int info_fd = open(ranges_file, O_RDONLY) ;
  • if (info_fd < 0) {
  • fprintf(stderr, "cannot open: %s", ranges_file) ;
  • exit (EXIT_FAILURE) ;
  • }
  • ssize_t n = read(info_fd, buffer, sizeof(buffer)) ;
  • close(info_fd) ;
  • if (n < 8) {
  • fprintf(stderr, "cannot read base address: %s", ranges_file) ;
  • exit (EXIT_FAILURE) ;
  • }
  • uint32_t gpio_base = (buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7] << 0) ;
  • if (!gpio_base)
  • {
  • gpio_base = (buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11] << 0) ;
  • }
  • while (fgets (line, 120, cpuFd) != NULL) if (strncmp (line, "Revision", 8) == 0) break ;

@@ -968,7 +997,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) ;

@@ -1007,7 +1036,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 ;

@@ -1034,7 +1063,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) &gt; 4 ;

// Extract last 4 characters:

 c = c + strlen (c) - 4 ;

@@ -1073,8 +1102,11 @@ void piBoardId (int model, int rev, int mem, int maker, int *warranty)

 else                              { *model = 0           ; *rev = 0              ; *mem =   0 ; *maker = 0 ;               }

}

  • if (gpio_base == GPIO_PERI_BASE_RP4) {
  • *model = PI_MODEL_4;
  • }

}

/* @@ -1205,6 +1237,10 @@ void pwmSetRange (unsigned int range) void pwmSetClock (int divisor) { uint32_t pwm_control ;

  • if(piGpioBase == GPIO_PERI_BASE_RP4) {

  • divisor = 540*divisor/192;

  • } divisor &= 4095 ;

    if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))

@@ -1260,7 +1296,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) ;

@@ -1504,11 +1540,31 @@ 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) ;
  • *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ;
  • *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ;
  • // Check GPIO register
  • int is2711 = *(gpio + PULLUPDN_OFFSET_2711_3) != 0x6770696f;
  • if(is2711) {
  •    // Pi 4 Pull-up/down method
    
  •    int pullreg = PULLUPDN_OFFSET_2711_0 + (pin &gt;&gt; 4);
    
  •    int pullshift = (pin &amp; 0xf) &lt;&lt; 1;
    
  •    unsigned int pullbits;
    
  •    unsigned int pull = 0; // Turn PUD off by default
    
  •    if (pud == PUD_UP) {
    
  •        pull = 1;
    
  •    } else if (pud == PUD_DOWN) {
    
  •        pull = 2;
    
  •    }
    
  •    pullbits = *(gpio + pullreg);
    
  •    pullbits &amp;= ~(3 &lt;&lt; pullshift);
    
  •    pullbits |= (pull &lt;&lt; pullshift);
    
  •    *(gpio + pullreg) = pullbits;
    
  • } else {
  •    // Legacy Pull-up/down method
    
  •    *(gpio + GPPUD)              = pud &amp; 3 ;       delayMicroseconds (5) ;
    
  •    *(gpio + gpioToPUDCLK [pin]) = 1 &lt;&lt; (pin &amp; 31) ;   delayMicroseconds (5) ;
    
  •    *(gpio + GPPUD)              = 0 ;         delayMicroseconds (5) ;
    
  •    *(gpio + gpioToPUDCLK [pin]) = 0 ;         delayMicroseconds (5) ;
    
  • } } else // Extension module {

@@ -1680,7 +1736,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.

@@ -1699,7 +1755,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.

@@ -1748,7 +1804,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

@@ -1804,7 +1860,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)

@@ -1861,7 +1917,7 @@ unsigned int digitalReadByte2 (void) data = (data << 1) | x ; } }

  • else
  • else data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins

    return data ;

@@ -2265,6 +2321,9 @@ int wiringPiSetup (void) case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: piGpioBase = GPIO_PERI_BASE_OLD ; break ;

  • case PI_MODEL_4:

  •  piGpioBase = GPIO_PERI_BASE_RP4 ;
    
  •  break ;
    
    

    default: piGpioBase = GPIO_PERI_BASE_NEW ;

@@ -2273,7 +2332,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) @@ -2311,13 +2370,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) ; @@ -2437,7 +2496,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 -ruN wiringPi/wiringPi.h wiringPi/wiringPi.h --- wiringPi/wiringPi.h +++ wiringPi/wiringPi.h @@ -100,6 +100,7 @@ #define PI_MODEL_CM3 10 #define PI_MODEL_ZERO_W 12 #define PI_MODEL_3P 13 +#define PI_MODEL_4 14

#define PI_VERSION_1 0 #define PI_VERSION_1_1 1

Note that the patch should be executed inside of Wiring-Pi root (outside of it's wiringPi sub-directory).

Also, this is a copy of my other answer on StackOverflow.com, and is not related to https://github.com/WiringPi/WiringPi (although, they are free to apply this, too).

Top-Master
  • 121
  • 4
0

While working on the next version of Pi4J, Robert Savage found a solution by using the unofficial version of WiringPi that be found on GitHub in WiringPi > WiringPi.

Remove the existing WiringPi installation, clone the GitHub project and build it like this:

echo "--------------------------------------------"
echo "Uninstalling any existing WiringPi versions "
echo "--------------------------------------------"
sudo apt-get remove wiringpi -y
sudo apt-get --force-yes --yes install git-core gcc make
echo "--------------------------------------------"
echo "Cloning latest WiringPi sources from repo   "
echo "--------------------------------------------"
cd /opt/pi4j
git clone https://github.com/WiringPi/WiringPi --branch master --single-branch wiringpi
cd /opt/pi4j/wiringpi
echo "--------------------------------------------"
echo "Building and installing WiringPi library"
echo "--------------------------------------------"
sudo ./build uninstall
sudo ./build clean
sudo ./build
Frank
  • 328
  • 1
  • 9