I'm struggling to figure out how the WiringPi C library manipulates the GPIO hardware. Is it possible to change multiple output pins on the GPIO simultaneously in C using the library? For example, writing a byte onto 8 of the pins? And would this be slower than modifying one pin at a time?
2 Answers
It's possible with a very minor caveat.
When you set a GPIO high or low you write to one of two registers.
A set register to set selected GPIOs high.
A clear register to set selected GPIOs low.
The set and clear registers are 32 bits in size and control GPIO 0-31.
To set GPIO x high you write 1<<x
to the set register. E.g. to set GPIO 4 high you write 16 to the set register. You can set multiple bits at the same time. Each GPIO with its corresponding bit set will be set high. The level of a GPIO without a bit set will be unaffected, i.e. if high it will stay high, if low it will stay low.
The clear register works in a similar fashion. If you set a bit high the corresponding GPIO will be set low.
So the minor caveat is if you want to set a group of GPIO to an arbitrary value you'd need two writes, one to the set register for the GPIO you wanted high, and another to the clear register for the GPIO you wanted low (the order is immaterial).
pigpio has a clear and set functions for the GPIO.
wiringPi has similar functions.
-
Just what I wanted to know - thanks - you say the order is immaterial, but just to be clear, if one instruction sets and one clears, then the order would still affect the output, even if the final state is the same?– JayyCommented Sep 30, 2016 at 12:52
-
@Jodes Yes, you are quite right. If you set and clear the same GPIO the last operation will be the end result, so in that case the order is important.– joanCommented Sep 30, 2016 at 13:12
-
1@PeterGreen The level registers are read only (page 90 of BCM2835 ARM Peripherals)– joanCommented Sep 30, 2016 at 14:48
-
2@PeterGreen Page 96 also say 0 means low and 0 means high. I'd ignore page 96.– joanCommented Sep 30, 2016 at 16:26
-
1
I believe WiringPi, like other Pi specific GPIO libraries such as pigpio and libbcm2835, works by mmap()
ing part of kernel space into user space using /dev/mem
(or the more specific /dev/gpiomem
; beware not to mess around casually particularly with the former or you could cause just about anything, including serious filesystem corruption, to occur). You can find an example of this technique on elinux.org if you are interested.
This provides access to hardware registers normally only accessible to the kernel. What you are asking for -- to set the value of eight arbitrary GPIOs in parallel -- would require hardware pathways and the SoC, being organized around a CPU with 1-4 cores, may require code to manipulate each execute linearly on a processor core (one instruction at a time).
[See joan's answer for more details about this -- evidently you can set GPIO values as a whole via hardware, but I'll let this answer stand for the general outline].
Even if this were the case, very likely you could do it in few enough instructions that on a single core Pi running at 700 Mhz, eight GPIOs could be set within a microsecond, which is pretty much but not quite literally instantaneous. If you have to do parallel busing at a higher frequency than that, again, a special hardware feature would be required to implement it and the Pi does not have an 8 pin parallel bus.
It does mean if all you want to do is set the value of 8 gpios more or less at the same time, just do it with 8 procedural calls in code [or in parallel using the library features mentioned by joan] and the time it takes them to execute is what it is, but it probably will not be anything relative to a human scale.
-
Interesting! Complicated too! Plus I had no idea there were other low level libraries - I'll have to check them out - thanks again– JayyCommented Sep 30, 2016 at 12:51
-
Take joan's answer as more authoritative about the details; she's actually worked with this stuff whereas I just know approximately where it is. So the big picture here is I think accurate but evidently you can manipulate GPIOs in parallel; I notice the pigpio lib functions she links use a 32-bit register, which is the front-side bus width of the CPU, i.e., the number of bits that can be sooshed forth at once. So this would take a minimal number of instructions -- making it happen at a high fixed rate is another issue, but that's not what your question is.– goldilocks ♦Commented Sep 30, 2016 at 12:54
-
++ to you and @joan for the work you've done. I just started with the Pi a couple of months ago, and I love reading detailed info like this. I've only wrapped C libraries (wiringPi), but I've never had to deal with the low-level stuff (and I only know enough C to cause serious damage and just get by).– steviebCommented Sep 30, 2016 at 22:27