Code and Life

Programming, electronics and other cool tech stuff

Supported by

Supported by Picotech

Raspberry Pi 2 vs. 1 GPIO Benchmark

Raspberry Pi 2 GPIO Benchmark

It’s battle time! Some of you may have heard that Raspberry Pi 2 is out with more punch than ever. Just how much more? Well, apt-get dist-upgrade went about 5 times faster with the new Pi. With 1 GB of RAM and four cores, this will definitely be a boost for my home SSH box ergonomics over the previous version.

But what about hacking? There has been a lot of interest in getting GPIO benchmarks for the Pi 2 similar to my earlier Raspberry Pi GPIO benchmark. Well here it is! Please refer to the earlier article for source code and nice screenshots of square waves, as I’ll concentrate on the performance difference only here. You can also get the code from Github:

https://github.com/jokkebk/rpi-gpio-benchmark

Summary of results

All the Pi 1 benchmarks were ran 14th and 15th February 2015 using latest versions of the libraries as stated in my updated benchmark post. Pi 2 benchmarks were all run 25th and 26th March 2015 with the latest versions. If you get significantly different results at a later date, please let me know and I’ll update the table!

Language Library Pi 1 Pi 2 Change
Shell /proc/mem access 2.8 kHz 7.0 kHz 2,5x
Shell / wiringPi WiringPi gpio utility 40 Hz 95 Hz 2,4x
Python RPi.GPIO 70 kHz 243 kHz 2,5x
Python wiringpi2 bindings 28 kHz 103 kHz 3,7x
Ruby wiringpi bindings 21 kHz N/A 3,7x
C Native library 22 MHz 41.7 MHz 1,9x
C BCM2835 5.4 MHz 7.2 MHz 1,3x
C WiringPi normal GPIO wiringPiSetup() 4.1 MHz 9.3 MHz 2,3x
C WiringPi GPIO wiringPiSetupGpio() 4.6 MHz 9.4 MHz 2x
C WiringPi sys wiringPiSetupSys() 120 kHz 185 kHz 1.5x
Perl BCM2835 48 kHz 154 kHz 3.2x

Raspberry Pi 2 GPIO Issues

It seems that not all code has yet caught up with the new version. For example, in strobe.c, peripheral base address needs to be changed from 0x20000000 to 0x3F000000:


#define BCM2708_PERI_BASE        0x3F000000

Ruby bindings for wiringpi (or wiringpi2) did not work at all for unknown reasons, possible due to the above change, or something else. At least there is following line in ext/wiringpi/WiringPi/wiringPi/wiringPi.c:


#define BCM2708_PERI_BASE        0x20000000

Conclusions

Based on the benchmarks, the Pi 2 is generally 2-3 times as fast in GPIO operations too as its predecessor. Most libraries work already very well on the new Pi member, but Ruby bindings to wiringPi still seem to have some troubles.

29 comments

Rodrigo:

row 3, col 4: Hz or kHz ?

Joonas Pihlajamaa:

Whoops, kHz of course :) Fixed!

He:

93Hz @Pi 2

Lukas M:

Please consider benchmarking on javascript with onoff library for Node.js (or io.js). https://github.com/fivdi/onoff
Thanks (-;

brenson:

Hi Joonas,

I asked about a PC to Mac keyboard compatibility issue before. Could you answer here, please?

Thank you

Joonas Pihlajamaa:

Hi Brenson, The question was of little relevance to Rasperry Pi 2 benchmark (and from context I was not sure if it would fit the USB HID keyboard article), so I removed your question and sent you email instead. If the email did not reach you, email me at firstname.lastname@gmail.com and I’ll be in touch. :)

Brenson:

Hi Joonas,

And thanks for answering. For some reason – ISP settings for the moment probably – can’t do anything with a mail account. Will you please answer here and leave it for 1-2 days please. I will try solve the mail issue.

Thanks a lot

Ahrnov:

Hello,
Nice piece of work here :)
But do you have any idea on how much time switching from input to output (and vice-versa) does take?
Like in the code from elinux.org:
for (g=7; g<=11; g++)
{
INP_GPIO(g); // must use INP_GPIO before we can use OUT_GPIO
OUT_GPIO(g);
}
Say you have to switch to output, give some data, switch back to input, read some using the same GPIO ports?
Many thanks

Anton:

Hello,
very interesting comparison! Would you mind adding [GPIO Zero](http://pythonhosted.org/gpiozero/) to it, as it appears it might become the preferred way of interacting with the GPIOs in Python?

ab0032:

Shouldn’t shell/wiringPi gpio command be Hz and not kHz? Screenshot of previous benchmark suggests that to me. It was 100x slower than plain shell.

Joonas Pihlajamaa:

You are right, I fixed that. :)

Duncan:

Hi, are you still seeing interruptions due to the non realise kernel, or its the Pi2 able to use one of the cores to drive the gpio output without interruptions?

Duncan:

*Realise = realtime (autocorrect issue! )

Johan:

Hi, great work, thanks! It would be very interesting o see how the pigpio library performs too. As I understand it, it is very fast and focusing on time critical tasks that you can’t use wiringpi for.

Kevin Kibbe:

Thanks very much for your benchmark work. It’s great to see this as I’m at the beginning stages of my first Pi hardware project. My first embedding playings were with an 1802 micro…

I have a WiringPi C program running on a B+ Pi and am wondering how much better the PI 2 is as far as interruptions when the Pi does something else, like respond to the mouse etc. For my project I will be receiving data on the Ethernet port and outputting data on the GPIO pins. I don’t need the pi to do anything else for my project but It would be nice if it was fast enough as I am using it now and able to rlogin etc.

Regards, Kevin

Joonas Pihlajamaa:

Thanks! I would assume that the Pi2 is about as much faster in interrupt handling as it is faster to Pi1 in other tasks, i.e. there would be roughly half the time spent in interrupts. Still difficult for time-critical GPIO work (like software serial or other SW signalling), so you may want to use a hardware-supported protocol (I think Pi has SPI or I2C) to transfer data. Of course for blinking LEDs or something that does not require microsecond accuracy, GPIO should be fine.

Kevin Kibbe:

Thanks for the response Joonas. I’ll have my PI2 tomorrow, I’ll post my results back here. What I have done is write a C program to toggle a gpio port and with the ordinary B+ I get the ~4.5MHz rate. That speed is fine but when you zoom out with the scope you see lots of gaps in the 50 uS range or even worse it’s those that I’m trying to shorten. I assume in the setup of the PI there are things that eat up time that I can shut off. I’ll look into them. But it’s the quad core that I am hoping will save me time…

Kevin Kibbe:

I find it interesting that i can’t find a way to set and read the GPIO pins byte wise… Joonas, do you know of a way to do this?

Joonas Pihlajamaa:

Sorry, no idea. Many microcontrollers do have this feature, don’t know about the Pi.

Kevin Kibbe:

Imagine my surprise when I find the wiringPi has this function:
digitalWriteByte()

For some reason it’s not well documented and few seam to know about it. What’s odd is that Gordon doesn’t even tell you which pins are what on the GPIO (other than saying they are not the dual use pins) but it seams to work on my Pi B+.

Gustavo Massaneiro:

I’m curious too for results of pigpio library, I think it will get a better result compared to wiringPi, maybe even very close to the C native code.

thomas:

So does that mean you can poll the a GPIO pin every 23.98 ns?
Can you receive interrupts on a GPIO pin at that speed?

Wachino:

What about Pi 3?

Jason Tokarz:

Have you tried running the benchmarks on Linux with the RT patch to see if that helps the ‘hang’ issue?

Joonas Pihlajamaa:

No, haven’t tried that.

prb:

I used Ultibo (an open source baremetal environment based on Lazarus) to measure the toggle rate for RPi B+, RPi 3 and RPi Zero.

All results are posted here: https://ultibo.org/forum/viewtopic.php?f=13&t=904

I got ~41.6 MHz for RPi B+, ~60.0 MHz for RPi 3 and ~66.6 MHz for RPi Zero. The last result was kind of surprising I would say. :-)

I can HIGHLY recommend Ultibo for doing these kind of “Arduino-like” things; it is much better suited for real-time work that Linux.

LedBlue:

I did some tests on RPi CM3 for native C and WiringPi benchmarks

With WiringPi I achieved about 15MHz
for(;;){
digitalWrite (LED, HIGH) ; // On
digitalWrite (LED, LOW) ; // Off
}

With Native C I achieved about 57MHz
for (;;)
{
GPIO_SET = 1<<g;
GPIO_CLR = 1<<g;
}

By Adding a read cycle to the native C, frequency drops to about 10MHz
for (;;)
{
GPIO_SET = 1<<g;
GPIO_CLR = 1<<g;
gpioVal = (*(gpio+13));
}

Jeff:

Have you tried testing a pin configured for input for the maximum possible sampled input frequency before aliasing occurs ?

Joonas Pihlajamaa:

No, I haven’t tried benchmarking the input side at all. Good project for someone though!