3

I appreciate the PI4J project and the access it provides to GPIO from Java (my language of choice) however, compared to C, Java is much slower. Normally this is not a problem but I was working with accessing the HC-SR04 ultrasonic TX/RX and I needed to make timings at the microsecond level. For example, to measure a distance of 10cm, I need to measure a pulse that is high for only 590 usecs.

My belief is that Java is too slow for these rates. When I wrote my app in C, it was more than fast enough to take a measurement. However, I only needed to report the measured distance every second to my user. This meant that I could write my interfacing code in C but write the remainder of my logic in Java.

This worked great. Using Java's JNI, I could call "wiringPi" directly and without issue. However, prior to calling the wiringPi APIs to change the state of pins and watch for changes, I have to call wiringPi setup functions including defining the input or output direction off a pin. I figured that I could use PI4J to setup my environment and then call C to perform my measurements. This appeared not to work and I had to do all my wiringPi APIs from C and ignore the PI4J library altogether.

And with this pre-amble, now the question.

If I wish to make direct wiringPi API calls from a C function and the C function is called from Java via JNI, can we "mix in" the use of PI4J in conjunction with direct wiringPi API calls?

2

This may seem like a slight aside, but perhaps may answer your question a little better. If this is all clear to you, I'll answer anyway in the hopes it is useful to someone else.

All access to GPIOs in Linux is done through the kernel. And there's a specific GPIO subsystem to handle this. Your very best performance would be to write a kernel driver.

However, the GPIO driver writers have provided a very clean and simple interface to the GPIO subsystem. This can be accessed from userspace via the sysfs filesystem. Specifically, via /sys/class/gpio/.

Any userspace API that is accessing GPIOs either wrote their own driver, did some mmap()ing directly to the GPIO registers (BAD!), or used the sysfs interface mentioned above. The is true of WiringPi and any others.

Bottom line is that you can directly use sysfs interface - its quite easy to use. Google for more info on it (include the kernel docs).

Here's a super duper simple example. To use GPIO 12 as an input (the default), and view its current value:

pi@raspberrypi ~ $ echo 12 > /sys/class/gpio/export pi@raspberrypi ~ $ cat /sys/class/gpio/gpio12/value 1

  • I agree that a kernel driver might have an advantage performance wise (and it is a shame no one has written a pi specific one to fulfill the role of wiringPi, when multiple people have instead written userspace libraries). However, it is not true that "All access to GPIOs in Linux is done through the kernel", except tangentially: those userspace libs use mmap() on /dev/mem. You actually refer to this...anyway, the generic /sys/class interface has limitations the userspace libs don't have, and it would be good to point out that if it does what you need, great, if not, wiringPi et. al. – goldilocks Oct 9 '15 at 18:35
  • 1
    Right - I meant "All access..." in that even if you are going through /dev/mem, you're going through a kernel driver. No matter how you slice it, you have to go from userspace to kernelspace to access GPIOs. – Brian Oct 9 '15 at 19:19
0

If I wish to make direct wiringPi API calls from a C function and the C function is called from Java via JNI, can we "mix in" the use of PI4J in conjunction with direct wiringPi API calls?

There's only one way to find out for sure, but I don't see why not. They're both presumably using the same basic methodology, which is to mmap() part of kernelspace. I don't think it is possible for one process to prevent another process from doing the same thing at the same time in this sense, and it certainly isn't desirable to prevent it, or you could only have one program on the system using this at a time.

  • Thanks for the response. I follow what you are saying from the underlying low level principles ... however I think the reality will be found in the PI4J internals. For example, PI4J claims to "contain" its own copy of wiringPi library ... which could result in my C code (which is called from Java) instantiating one copy (in address space) while PI4J instantiates a second copy. My tests have so far proved unsuccesful in getting the obvious to work. – Kolban Apr 12 '15 at 12:41
  • I'm not very familiar with wiringPi, but if it uses some sort of global initialization then that's a problem, unless you can find a way to patch PI4J to get at whatever handle it is you need from there. – goldilocks Apr 12 '15 at 13:32

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.