RPi with an Oscilloscope and Java Embedded: Ready for Benchmarking (Part 8)

Well, as I mentioned to Robert Savage recently, I know how to get to the same speed in Java SE Embedded as the Pi4J Java to JNI library from Savage Home Automation and more importantly to also achieve the same 5MHz max frequency on a GPIO pin as using C native. But knowing how is not exactly the same as implementing, is it? :-) So, I'll show how instead, since showing is the same as implementing, right? ;-) Well, it should be the same. B-)

The approach in theory could use NIO memory mapped buffer that I was originally thinking should be as fast as C native. But in practice anyone that has tried this has gotten a bug where it says "No device found" error when trying to map the /dev/mem of the Raspberry Pi. That's what @Geomancer86 also noticed also, as he mentioned on twitter.

So, what's the deal? It seems Java SE Embedded NIO does one type of file open and mmap down in the native layer underneath java.nio.ByteBuffer that does not allow for opening native memory devices (only real files on the Linux system). But, we need to access /dev/mem from Java on the Raspberry Pi to access the GPIO pins in memory to flip the bits as fast as possible to reach the maximum possible frequency in doing so.

There something we can learn by looking at Gordon Henderson's WiringPi C native code. That is there's a different way of doing the native file open and mmap that's needed, and we know he's doing it the right way since WiringPi can get that 5MHz on the GPIO pins that we want.

See: https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringPi.c
Scroll down to line 1319

// Open the master /dev/memory device

  if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
  {
    if (wiringPiDebug)
    {
      int serr = errno ;
fprintf (stderr, "wiringPiSetup: Unable to open /dev/mem: %s\n", 
  strerror (errno)) ;
      errno = serr ;
    }
    return -1 ;
  }

// GPIO:

  gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, 
    MAP_SHARED, fd, GPIO_BASE) ;
  if ((int32_t)gpio == -1)
  {
    if (wiringPiDebug)
    {
      int serr = errno ;
fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", 
  strerror (errno)) ;
      errno = serr ;
    }
    return -1 ;
  }

Instead of what NIO does currently, we need to instead do the same as above and then hand back a Java ByteBuffer that is pointing to that GPIO Base mapped in memory. Then we can use java.nio.ByteBuffer to twiddle bits representing the GPIO pins and turn them on/off as fast as possible, which in theory gives us that max 5MHz.

If anyone wants to try this, try extracting just that WiringPi native C code from Gordon Henderson's library (above) and make your own JNI call to it from Java SE Embedded to mimic what NIO does. Then make another JNI call to do a write to the memory just like Gordon does to turn the pin on/off as fast as possible. That in theory should give the max 5MHz that C native can do and have it be accessible from the Java SE Embedded side.

So, that's me showing how it could be done, it's up to someone out there to see if that theory holds up. Any takers? Showing is just like implementing, right? :-)

Comments:

Post a Comment:
Comments are closed for this entry.
About

Hinkmond Wong's blog on making Machine to Machine (M2M) and the Incredible Internet of Things (IoT) smarter with Java Embedded Technologies

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
2
3
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today