Skip to content
Adam YH Lee edited this page Jul 30, 2015 · 11 revisions

In this article you will do these followings:

  1. Install Java Development Kit and Runtime Environment (openjdk-7)
  2. Install an external Java library (RXTXcomm)
  3. Compile a console application written Java using the above two.

Note that this article does not present a cross development environment. Java's bytecode is portable by design. So it is easy to compile a piece of Java code on an x86 workstation and deploy to an ARM device. However we intentionally avoid such workflow for now. Unlike C/C++ which is extensively documented, Yocto Project's SDK lacks Java cross development.

Hence we will native-compile a simple TwoWaySerialComm Java app that dumps the standard output into a unoccupied serial console and vice versa. It is originally written by Johannes Eickhold for EclipseSource.com.

This program relies on RXTX, a Java communication API. RXTX is available as a recipe and is also a part of the Gumstix Package Repository.

Prepare your Gumstix for Java

Make sure you are running a recent version of Gumstix Yocto image on your Gumstix board.

Here we install JRE, JVM, and RXTXComm API on your Gumstix:

$ smart update
$ smart install librxtx-java openjdk-7-jre openjdk-7-jdk

When this is successful, you will have javac, the compiler, and RXTX Java class like this:

root@overo:~# ls /usr/share/java
rxtx.jar
RXTXcomm.jar
...

Configure Java Environment

Before we compile any Java code, let's set classpath and LD_LIBRARY_PATH:

export CLASSPATH="/usr/share/java/RXTXcomm.jar"
export LD_LIBRARY_PATH="/usr/lib/jni"

Skipping this step will result in compile error. Here CLASSPATH refers to the location where Java user class files are. And LD_LIBRARY_PATH refers to the Java system library.

Compile Java

Copy the following source code into TwoWaySerialComm.java file:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
 
public class TwoWaySerialComm {
 
  void connect( String portName ) throws Exception {
    CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier( portName );
    if( portIdentifier.isCurrentlyOwned() ) {
      System.out.println( "Error: Port is currently in use" );
    } else {
      int timeout = 2000;
      CommPort commPort = portIdentifier.open( this.getClass().getName(), timeout );
 
      if( commPort instanceof SerialPort ) {
        SerialPort serialPort = ( SerialPort )commPort;
        serialPort.setSerialPortParams( 57600,
                                        SerialPort.DATABITS_8,
                                        SerialPort.STOPBITS_1,
                                        SerialPort.PARITY_NONE );
 
        InputStream in = serialPort.getInputStream();
        OutputStream out = serialPort.getOutputStream();
 
        ( new Thread( new SerialReader( in ) ) ).start();
        ( new Thread( new SerialWriter( out ) ) ).start();
 
      } else {
        System.out.println( "Error: Only serial ports are handled by this example." );
      }
    }
  }
 
  public static class SerialReader implements Runnable {
 
    InputStream in;
 
    public SerialReader( InputStream in ) {
      this.in = in;
    }
 
    public void run() {
      byte[] buffer = new byte[ 1024 ];
      int len = -1;
      try {
        while( ( len = this.in.read( buffer ) ) > -1 ) {
          System.out.print( new String( buffer, 0, len ) );
        }
      } catch( IOException e ) {
        e.printStackTrace();
      }
    }
  }
 
  public static class SerialWriter implements Runnable {
 
    OutputStream out;
 
    public SerialWriter( OutputStream out ) {
      this.out = out;
    }
 
    public void run() {
      try {
        int c = 0;
        while( ( c = System.in.read() ) > -1 ) {
          this.out.write( c );
        }
      } catch( IOException e ) {
        e.printStackTrace();
      }
    }
  }
 
  public static void main( String[] args ) {
    String SerialPortID = args[0];
    System.setProperty("gnu.io.rxtx.SerialPorts", SerialPortID);
    try {
      ( new TwoWaySerialComm() ).connect( args[0] );
    } catch( Exception e ) {
      System.out.println( "Can't find serial port\n" );
      e.printStackTrace();
    }
  }
}

Note that the code has been slightly modified from the original version. The original code is missing some key import clause. It also fails to set the default port for RXTX.

Then you can compile like below:

javac TwoWaySerialComm.java

If the code compiled, you should have 4 files:

$ ls TwoWaySerialComm*
TwoWaySerialComm.class  TwoWaySerialComm.java
TwoWaySerialComm$SerialReader.class  TwoWaySerialComm$SerialWriter.class

If you run into an issue like this:

Error: Could not find or load main class TwoWaySerialComm

Add the path to your Java bytecode to CLASSPATH:

export CLASSPATH=$CLASSPATH:/Path-To-Bytecode/

Run

The example program will refer to locations above CLASSPATH when it executes:

java TwoWaySerialComm /dev/ttyO0