2

I'm currently trying to understand the pigpio library and I found it supports reading from and writing to more than one GPIO pin at once. However can it do the same with pin mode?

I'm asking the question because I am also trying to write a program to test a graphics display (that is powered in 3.3v). The latter uses a 8080-like communication bus, i.e. there are 3 control lines (outputs) but data is read from and written to the same 8 bus lines so I'd need to set 8 GPIO lines as inputs or outputs at different times.

The display expects commands and parameters. When reading from the display, I must write an 8-bit data, pulse the WR line low, set the 8 GPIO lines as input before I can pulse the RD line low and read what's on the 8 GPIO lines.

So is it possible to control 8 GPIO pins as input/output in one go? Or do they have to be set individually?

The device is a Raspberry Pi 2 model B.


EDIT: I also took a look at BCM2835 library and looking at the code it seems it might be possible though the 32-bit word that controls GPIO pins is split into bit fields, each field being 3 bits wide, due to the many possible pin configurations:

/* Function select
// pin is a BCM2835 GPIO pin number NOT RPi pin number
//      There are 6 control registers, each control the functions of a block
//      of 10 pins.
//      Each control register has 10 sets of 3 bits per GPIO pin:
//
//      000 = GPIO Pin X is an input
//      001 = GPIO Pin X is an output
//      100 = GPIO Pin X takes alternate function 0
//      101 = GPIO Pin X takes alternate function 1
//      110 = GPIO Pin X takes alternate function 2
//      111 = GPIO Pin X takes alternate function 3
//      011 = GPIO Pin X takes alternate function 4
//      010 = GPIO Pin X takes alternate function 5
//
// So the 3 bits for port X are:
//      X / 10 + ((X % 10) * 3)
*/
void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode)
{
    /* Function selects are 10 pins per 32 bit word, 3 bits per pin */
    volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10);
    uint8_t   shift = (pin % 10) * 3;
    uint32_t  mask = BCM2835_GPIO_FSEL_MASK << shift;
    uint32_t  value = mode << shift;
    bcm2835_peri_set_bits(paddr, value, mask);
}

So it looks like setting the mode for multiple pins is possible but it requires determining which bank to address first. If the 8 GPIO pins are fixed then the mask can be set in much fewer steps than setting all 8 pins one by one.

Can anyone confirm?

2

pigpio does not support setting the mode of multiple GPIO in one operation.

You would need to write your own code. The pigpio implementation is as follows.

int gpioSetMode(unsigned gpio, unsigned mode)
{
   int reg, shift, old_mode;

   DBG(DBG_USER, "gpio=%d mode=%d", gpio, mode);

   CHECK_INITED;

   if (gpio > PI_MAX_GPIO)
      SOFT_ERROR(PI_BAD_GPIO, "bad gpio (%d)", gpio);

   if (mode > PI_ALT3)
      SOFT_ERROR(PI_BAD_MODE, "gpio %d, bad mode (%d)", gpio, mode);

   reg   =  gpio/10;
   shift = (gpio%10) * 3;

   old_mode = (gpioReg[reg] >> shift) & 7;

   if (mode != old_mode)
   {
      switchFunctionOff(gpio);

      gpioInfo[gpio].is = GPIO_UNDEFINED;
   }

   gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);

   return 0;
}

There are six 32-bit registers used to read/write the mode, GPIO Alternate function select register 0 through 5.

Register 0 for GPIO 0-9, 1 for GPIO 10-19, 2 for GPIO 20-29, 3 for GPIO 30-39, 4 for GPIO 40-49, and 5 for GPIO 50-53.

You need to preserve the settings of any GPIO you don't want to alter when you update one or more GPIO within a register.

  • Ah, thanks a lot Joan! That's exactly the information I needed. – user29510 Oct 15 '17 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy