Meteo Recipe
Posted: Wed Aug 17, 2011 6:01 pm
This recipe demonstrates bulding of Java Application with GPIO and ADC support. Accessing of GPIO and ADC is made through dynamic libraries written in C. In Java this interface is available through JNI bindings.
First let’s make base structure of recipe
Bin – directory for compiled JAVA files
Lib – sources of C library
Meteo – JAVA API sources
Meteo_test – JAVA Test API sources
Let’s add necessary files in lib directory
DigitalChannel.c - includes C implementation and JNI exports for export, direction, read and write GPIO channels. In addition there is function for software PWM. It can be used to test the system time quantum.
AnalogChannel.c - includes C API implementation and JNI exports for accessing and reading ADC channels.
ep93xx_adc.h - includes registry address defines and base ADC functions
peekpoke.h
Next we have to add necessary JAVA API files in meteo directory
DigitalChannel.java
AnalogChannel.java
JAVA API has no main class, so it can’t be tested directly after deployment. That’s why there is another class MeteoTest which can be used for basic test of API functionallity. This class is located in meteo_test directory
MeteoTest.java
Finally we have to add meteo recipe
meteo_1.0.bb
Build meteo recipe with the following command
After successful build, on target platform you can deploy the following packages:
libmeteo-jni – dynamic libraries. They will be installed as libAnalogChannel.so and libDigitalChannel.so in /usr/lib/jni directory
libmeteo-java – JAVA API archive. It will be installed as meteo.jar in /usr/share/java directory
libmeteo-test – JAVA API Test application. It will be installed as meteo_test.jar in /usr/share/java directory.
Let’s deploy our application on target platform. Execute the following command on target platform.
Start test application
First let’s make base structure of recipe
- Code: Select all
mkdir –p /angstrom/sources/local/recipes/meteo/files/bin
mkdir –p /angstrom/sources/local/recipes/meteo/files/lib
mkdir –p /angstrom/sources/local/recipes/meteo/files/meteo/channels
mkdir –p /angstrom/sources/local/recipes/meteo/files/meteo_test
Bin – directory for compiled JAVA files
Lib – sources of C library
Meteo – JAVA API sources
Meteo_test – JAVA Test API sources
Let’s add necessary files in lib directory
DigitalChannel.c - includes C implementation and JNI exports for export, direction, read and write GPIO channels. In addition there is function for software PWM. It can be used to test the system time quantum.
- Code: Select all
#include "meteo_channels_DigitalChannel.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#define TRUE 0x01
#define FALSE 0x00
int pwm_flag = FALSE;
char *uitos(unsigned int number) {
unsigned int n = number;
int size = 1;
do {
size++;
n /= 10;
} while(n >= 1);
char *buffer = (char *) malloc(size);
if(buffer == NULL) {
printf("Cannot allocate memory.\n");
exit(1);
}
memset(buffer, 0, size);
sprintf(buffer, "%d", number);
return buffer;
}
void exportGPIO(unsigned int number) {
FILE *fp;
int size, count;
//Using sysfs we need to write "gpioNumber" to /sys/class/gpio/export
//This will create the folder /sys/class/gpio/gpio"gpioNumber"
if((fp = fopen("/sys/class/gpio/export", "wb")) == NULL) {
printf("Cannot open export file.\n");
exit(1);
}
char *gpioNumber = uitos(number);
//Write our value of "gpioNumber" to the file
size = strlen(gpioNumber);
count = fwrite(gpioNumber, sizeof(char), size, fp);
fclose(fp);
if(size != count) {
printf("Fwrite error.\n");
exit(1);
}
//printf("...export file accessed, new pin %s now accessible\n", gpioNumber);
free(gpioNumber);
}
void unexportGPIO(unsigned int number) {
FILE *fp;
int size, count;
//Using sysfs we need to write "gpioNumber" to /sys/class/gpio/export
//This will create the folder /sys/class/gpio/gpio"gpioNumber"
if((fp = fopen("/sys/class/gpio/unexport", "wb")) == NULL) {
printf("Cannot open unexport file.\n");
exit(1);
}
char *gpioNumber = uitos(number);
//Write our value of "gpioNumber" to the file
size = strlen(gpioNumber);
count = fwrite(gpioNumber, sizeof(char), size, fp);
fclose(fp);
if(size != count) {
printf("Fwrite error.\n");
exit(1);
}
//printf("...unexport file accessed, new pin %s now unaccessible\n", gpioNumber);
free(gpioNumber);
}
void directionGPIO(unsigned int number, const char *gpioDirection) {
FILE *fp;
int size, count;
char *gpioNumber = uitos(number);
size = strlen("/sys/class/gpio/gpio") + strlen(gpioNumber) + strlen("/direction");
char *path = (char *) malloc(size);
count = sprintf(path, "%s%s%s", "/sys/class/gpio/gpio", gpioNumber, "/direction");
if(count != size) {
printf("Sprintf error.\n");
exit(1);
}
//SET DIRECTION
//Open the LED's sysfs file in binary for reading and writing, store file pointer in fp
if((fp = fopen(path, "wb")) == NULL) {
printf("Cannot open direction file.\n");
exit(1);
}
//Write our value of "out" or "in" to the file
size = strlen(gpioDirection);
count = fwrite(gpioDirection, sizeof(char), size, fp);
fclose(fp);
if(size != count) {
printf("Fwrite error.\n");
exit(1);
}
//printf("...direction of pin %s set to %s\n", gpioNumber, gpioDirection);
free(path);
free(gpioNumber);
}
unsigned int readGPIO(unsigned int number) {
FILE *fp;
int size, count;
unsigned int value;
char *gpioNumber = uitos(number);
size = strlen("/sys/class/gpio/gpio") + strlen(gpioNumber) + strlen("/value");
char *path = (char *) malloc(size);
count = sprintf(path, "%s%s%s", "/sys/class/gpio/gpio", gpioNumber, "/value");
if(count != size) {
printf("Sprintf error.\n");
exit(1);
}
//GET VALUE
//Open the LED's sysfs file in binary for reading, store file pointer in fp
if((fp = fopen(path, "rb")) == NULL) {
printf("Cannot open value file.\n");
exit(1);
}
size = sizeof(char);
char *gpioValue = (char *) malloc(size);
count = fread(gpioValue, sizeof(char), size, fp);
fclose(fp);
if(size != count) {
printf("Fread error.\n");
exit(1);
}
value = atoi(gpioValue);
//printf("...value of pin %s set to %d...\n", gpioNumber, value);
free(path);
free(gpioNumber);
free(gpioValue);
return value;
}
void writeGPIO(unsigned int number, unsigned int value) {
FILE *fp;
int size, count;
char *gpioNumber = uitos(number);
size = strlen("/sys/class/gpio/gpio") + strlen(gpioNumber) + strlen("/value");
char *path = (char *) malloc(size);
count = sprintf(path, "%s%s%s", "/sys/class/gpio/gpio", gpioNumber, "/value");
if(count != size) {
printf("Sprintf error.\n");
exit(1);
}
//SET VALUE
//Open the LED's sysfs file in binary for writing, store file pointer in fp
if((fp = fopen(path, "wb")) == NULL) {
printf("Cannot open value file.\n");
exit(1);
}
char *gpioValue = uitos(value);
size = strlen(gpioValue);
//Write our value of "gpioNumber" to the file
count = fwrite(gpioValue, sizeof(char), size, fp);
fclose(fp);
if(size != count) {
printf("Fwrite error.\n");
exit(1);
}
//printf("...value of pin %s set to %s...\n", gpioNumber, gpioValue);
free(path);
free(gpioNumber);
free(gpioValue);
}
void nsleep(double seconds) {
struct timespec req = {0}, rem = {0};
time_t sec = (int) seconds;
unsigned long nsec = seconds * 1000000000L - sec * 1000000000L;
req.tv_sec = sec;
req.tv_nsec = nsec;
nanosleep(&req, &rem);
}
JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_export(JNIEnv *env, jobject obj, jint number, jstring direction) {
/*Extracting information from the parameter */
const char *gpioDirection = (*env)->GetStringUTFChars(env, direction, 0);
exportGPIO(number);
directionGPIO(number, gpioDirection);
/*Releasing the Java String once you have got the C string is very important!!!*/
(*env)->ReleaseStringUTFChars(env, direction, gpioDirection);
}
JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_unexport(JNIEnv *env, jobject obj, jint number) {
unexportGPIO(number);
}
JNIEXPORT jint JNICALL Java_meteo_channels_DigitalChannel_read(JNIEnv *env, jobject obj, jint number) {
return readGPIO(number);
}
JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_write(JNIEnv *env, jobject obj, jint number, jint value) {
writeGPIO(number, value);
}
JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_stopPWM(JNIEnv *env, jobject obj, jint number) {
pwm_flag = TRUE;
}
JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_pwm(JNIEnv *env, jobject obj, jint number, jdouble f, jdouble k) {
//Export GPIO
exportGPIO(number);
directionGPIO(number, "out");
double t, t1, t2;
t = 1.0 / f;
t1 = t * k / 100.0;
t2 = t * (100.0 - k) / 100.0;
//Run an infinite loop - will require Ctrl-C to exit this program
while(1) {
if(pwm_flag == TRUE) {
unexportGPIO(number);
break;
}
if(t1 > 0) {
writeGPIO(number, 1); //high level
nsleep(t1);
}
if(t2 > 0) {
writeGPIO(number, 0); //low level
nsleep(t2);
}
}
}
AnalogChannel.c - includes C API implementation and JNI exports for accessing and reading ADC channels.
- Code: Select all
/*
ADC Operation
================
1 To enable clocks for the ADC block, set the TSEN bit in the Syscon section (ADCClkDiv register).
2 Set the DeviceCfg.ADCEN bit.
3 Clear the DeviceCfg.ADCPD bit.
4 Select an input. First unlock the software lock by writing 0xAA to the ADCSWLock register.
Then write an appropriate value (selected from Table 20-2on page520) to the ADCSwitch register.
5 To poll, read the ADCResult register repeatedly. Bit 31 of this register is the SDR,
or Synchronous Data Ready, bit. This bit is set when a new valid conversion value appears in
this register and is cleared when this register is read.
So when two consecutive reads show the bit clear and then set, the second read has the new valid value.
6 Conversion data may also be processed using interrupts from this module. If bit 11 in the ADCIntEn register
(the RINTEN bit) is set, an interrupt occurs whenever the SDR bit in the ADCResult register is set.
Therefore, an interrupt handler can read the ADCResult register whenever a new valid sample appears
in the register, which both returns a new conversion value and clears the interrupt.
Register Memory Map
====================
Address Name SW locked Type Size Description
-------------------------------------------------------------------------
0x8090_0000 Reserved
0x8090_0004 Reserved
0x8090_0008 ADCResult No Read Only 32 bits ADC result register.
0x8090_000C Reserved
0x8090_0010 Reserved
0x8090_0014 Reserved
0x8090_0018 ADCSwitch Write Read/Write 28 bits ADC Switch Matrix control register.
0x8090_001C Reserved
0x8090_0020 ADCSWLock NA Read/Write 1-bit read ADC software lock register.
8-bit write
0x8090_0024 ADCIntEn No Read/Write 9 bits ADC Interrupt Enable Register
0x8093_0090 ADCClkDiv Yes R/W 32 ADC Clock Divider
0x8093_0080 DeviceCfg Yes R/W 32 Device configuration
ADC result register: 0x8090_0008
Bit 31: SDR: Synchronous Data Ready
Bit 0-12: AD: Analog-to-digital converter output at 12-bit resolution
ADCSwitch: 0x8090_0018
Input to Measure ADC Switch Value
ADC4 0x0000_0610
ADC3 0x0000_0620
ADC2 0x0000_0640
ADC1 0x0000_0680
ADC0 0x0000_0608
ADCSWLock: 0x8090_0020
SWLCK Software lock bits
WRITE: The Unlock value for this feature is 0xAA
READ: During a read operation SWLCK[0] has the following meaning:
1 = Unlocked for current bus access.
0 = Locked
ADCIntEn: 0x8090_0024
RINTEN: Bit 11: Synchronous Data Ready Interrupt Enable. Setting this bit results in an
interrupt whenever the Synchronous Data Ready (SDR) bit in the ADCResult register is set.
ADCClkDiv: 0x8093_0090
ADCEN: Bit 31: ADC clock enable.
ADIV: Bit 16: ADC clock divider value.
0 - ADC Clock is divide-by-16 from the external oscillator.
1 - ADC Clock is divide-by-4 from the external oscillator.
DeviceCfg: 0x8093_0080
ADCPD: Bit 2: ADC Power Down.
1 - ADC and clocks are powered down.
0 - ADC and clocks are active. ADCPD must be zero for normal ADC operation.
ADCEN: Bit 17: ADC Enable.
The ADCEN bit does not affect the ADC power state.
ADC power down is directly controlled by the ADCPD bit.
1 = ADC Interface enabled.
0 = ADC Interface disabled.
*/
#include "meteo_channels_AnalogChannel.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include "peekpoke.h"
#include "ep93xx_adc.h"
/* Prototypes */
int get_channel_value(int channel);
/* globals */
static unsigned long adc_page, syscon_page;
static int devmem;
int get_channel_value(int channel) {
int cur_ch, avg, i;
switch(channel) {
case 0:
cur_ch = ADC_CH0;
break;
case 1:
cur_ch = ADC_CH1;
break;
case 2:
cur_ch = ADC_CH2;
break;
case 3:
cur_ch = ADC_CH3;
break;
case 4:
cur_ch = ADC_CH4;
break;
}
//discard first two samples
read_channel(adc_page, cur_ch);
read_channel(adc_page, cur_ch);
avg = 0;
//read 10 more samples
for(i = 0; i < 10; i++) {
usleep(10000);
avg += read_channel(adc_page, cur_ch);
}
avg /= 10;
if(avg < 0x7000) avg += 0x10000;
avg -= 40905;
return avg;
}
JNIEXPORT void JNICALL Java_meteo_channels_AnalogChannel_init(JNIEnv *env, jobject obj) {
devmem = open("/dev/mem", O_RDWR|O_SYNC);
assert(devmem != -1);
adc_page = (unsigned long) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, devmem, ADC_PAGE);
assert(&adc_page != MAP_FAILED);
syscon_page = (unsigned long) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, devmem, SYSCON_PAGE);
assert(&syscon_page != MAP_FAILED);
init_ADC(adc_page, syscon_page);
}
JNIEXPORT void JNICALL Java_meteo_channels_AnalogChannel_destroy(JNIEnv *env, jobject obj) {
assert(munmap(&adc_page, getpagesize()) == -1);
assert(munmap(&syscon_page, getpagesize()) == -1);
close(devmem);
}
JNIEXPORT jint JNICALL Java_meteo_channels_AnalogChannel_read(JNIEnv *env, jobject obj, jint channel) {
return get_channel_value(channel);
}
JNIEXPORT jdouble JNICALL Java_meteo_channels_AnalogChannel_readAsVoltage(JNIEnv *env, jobject obj, jint channel) {
int value = get_channel_value(channel);
return ((double)value * 3.3) / 49732;
}
ep93xx_adc.h - includes registry address defines and base ADC functions
- Code: Select all
#define ADC_PAGE 0x80900000
#define ADCRESULT_OFFSET 0x0008
#define SDR_MASK 0x80000000
#define DATA_OFFSET 0x0008
#define DATA_MASK 0xFFFF
#define ADCSWITCH_OFFSET 0x0018
#define ADC_CH0 0x0608
#define ADC_CH1 0x0680
#define ADC_CH2 0x0640
#define ADC_CH3 0x0620
#define ADC_CH4 0x0610
#define ADCSWLOCK_OFFSET 0x0020
#define UNLOCK_VAL 0xAA
#define SYSCON_PAGE 0x80930000
#define ADCCLKDIV_OFFSET 0x0090
#define SYSCON_UNLOCK 0x00C0
#define TSEN_MASK 0x80000000
#define DEVICECFG_OFFSET 0x0080
#define ADCPD_MASK 0x02
#define ADCEN_MASK 0x20000
/* prototypes */
void init_ADC(unsigned long adc_page, unsigned long syscon_page);
int read_channel(unsigned long adc_page, unsigned short channel);
static char is_ADC_busy(unsigned long adc_page);
void init_ADC(unsigned long adc_page, unsigned long syscon_page)
{
unsigned long val;
/* set TSEN bit */
val = PEEK32(syscon_page + ADCCLKDIV_OFFSET);
//unlock the software lock
POKE32(syscon_page + SYSCON_UNLOCK, UNLOCK_VAL);
POKE32(syscon_page + ADCCLKDIV_OFFSET, TSEN_MASK | val);
/* set ADCEN bit */
val = PEEK32(syscon_page + DEVICECFG_OFFSET);
POKE32(adc_page + SYSCON_UNLOCK, UNLOCK_VAL); //unlock the soft lock
POKE32(syscon_page + DEVICECFG_OFFSET, val | ADCEN_MASK);
/* clear ADCPD bit */
val = PEEK32(syscon_page + DEVICECFG_OFFSET);
POKE32(adc_page + SYSCON_UNLOCK, UNLOCK_VAL); //unlock the soft lock
POKE32(syscon_page + DEVICECFG_OFFSET, val & ~ADCPD_MASK);
}
int read_channel(unsigned long adc_page, unsigned short channel)
{
unsigned long val;
POKE32(adc_page + ADCSWLOCK_OFFSET, UNLOCK_VAL); //unlock the soft lock
//write ADCSwitch reg to select channel
POKE32(adc_page + ADCSWITCH_OFFSET, channel);
while(is_ADC_busy(adc_page)); //poll ADCResult
//read result from data regisyyter
val = PEEK32(adc_page + DATA_OFFSET) ;
val = val & DATA_MASK;
return val;
}
static char is_ADC_busy(unsigned long adc_page)
{
unsigned long val;
val = PEEK32(adc_page + ADCRESULT_OFFSET);
if((val & SDR_MASK) == SDR_MASK) return TRUE;
return FALSE;
}
peekpoke.h
- Code: Select all
// We can't expect that a dereference of an unsigned short * always
// produces a ldrh or strh since the compiler may choose to use
// a byte write instead. Hence, we emit the peeks and pokes using
// inline assembler. --JO
static inline unsigned short PEEK16(unsigned long addr) {
unsigned short ret;
asm volatile (
"ldrh %0, [ %1 ]\n"
: "=r" (ret)
: "r" (addr)
: "memory"
);
return ret;
}
static inline void POKE16(unsigned long addr, unsigned short dat) {
asm volatile (
"strh %1, [ %0 ]\n"
:
: "r" (addr), "r" (dat)
: "memory"
);
}
static inline unsigned long PEEK32(unsigned long addr) {
unsigned long ret;
asm volatile (
"ldr %0, [ %1 ]\n"
: "=r" (ret)
: "r" (addr)
: "memory"
);
return ret;
}
static inline void POKE32(unsigned long addr, unsigned long dat) {
asm volatile (
"str %1, [ %0 ]\n"
:
: "r" (addr), "r" (dat)
: "memory"
);
}
static inline unsigned char PEEK8(unsigned long addr) {
unsigned char ret;
asm volatile (
"ldrb %0, [ %1 ]\n"
: "=r" (ret)
: "r" (addr)
: "memory"
);
return ret;
}
static inline void POKE8(unsigned long addr, unsigned char dat) {
asm volatile (
"strb %1, [ %0 ]\n"
:
: "r" (addr), "r" (dat)
: "memory"
);
}
#define TRUE 0x01
#define FALSE 0x00
Next we have to add necessary JAVA API files in meteo directory
DigitalChannel.java
- Code: Select all
package meteo.channels;
public class DigitalChannel {
public native void export(int number, String direction);
public native void unexport(int number);
public native int read(int number);
public native void write(int number, int value);
public native void pwm(int number, double f, double k);
public native void stopPWM(int number);
static {
System.loadLibrary("DigitalChannel");
}
}
AnalogChannel.java
- Code: Select all
package meteo.channels;
public class AnalogChannel {
private native void init();
public native void destroy();
public native int read(int channel);
public native double readAsVoltage(int channel);
public AnalogChannel() {
this.init();
}
static {
System.loadLibrary("AnalogChannel");
}
}
JAVA API has no main class, so it can’t be tested directly after deployment. That’s why there is another class MeteoTest which can be used for basic test of API functionallity. This class is located in meteo_test directory
MeteoTest.java
- Code: Select all
package meteo_test;
import java.text.DecimalFormat;
import meteo.channels.*;
public class MeteoTest {
private static AnalogChannel analog;
private static DigitalChannel digital;
private static double f = 70.0; //Hz
private static double k = 50.0; //%
private static int pwmGPIO = 8;
private static class PwmTest extends Thread {
public void run() {
digital.pwm(pwmGPIO, f, k);
System.out.println("PWM Stopped");
}
public void stopPWM() {
digital.stopPWM(pwmGPIO);
}
}
public static void main(String[] args) {
// Analog Channel Test
DecimalFormat dFormat = new DecimalFormat("0.000");
System.out.println("Read all 5 ADC channels:");
analog = new AnalogChannel();
for(int i = 0; i < 5; i++) {
System.out.println("Analog channel " + i + " value: " + analog.read(i) + ", as voltage: " + dFormat.format(analog.readAsVoltage(i)) + "V");
}
analog.destroy();
// Digital Channel Test
//Integer to keep track of whether we want on or off
boolean toggle = false;
int value = 0;
int gpio = 0;
System.out.println("Digital channel test: export GPIO 6, 8 as output and GPIO 4 as input.");
digital = new DigitalChannel();
digital.export(6, "out");
digital.export(8, "out");
digital.export(4, "in");
for(int i = 0; i < 10; i++) {
toggle = !toggle;
value = digital.read(4);
gpio = value == 0 ? 6 : 8;
if(toggle) {
digital.write(gpio, 1);
}
else {
digital.write(gpio, 0);
}
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
System.out.println("thread interrupted");
}
}
digital.unexport(6);
digital.unexport(8);
digital.unexport(4);
System.out.println("Start PWM Test for 5 seconds.");
PwmTest test = new PwmTest();
test.start();
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
System.out.println("thread interrupted");
}
test.stopPWM();
}
}
Finally we have to add meteo recipe
meteo_1.0.bb
- Code: Select all
DESCRIPTION = "JAVA Meteo Application"
PR = "r0"
DEPENDS = "classpath classpath-tools-native"
inherit autotools java-library
SRC_URI = "file://meteo/* \
file://meteo_test/* \
file://lib/* \
file://bin"
S = ${WORKDIR}
do_compile() {
#JAVAH="gjavah -classpath \$(CLASSPATH) -d \$(DEST) -jni" \
JAVAH="gjavah -jni"
JAR=gjar \
#JAVAC="javac -classpath \$(CLASSPATH) -d \$(TOP)/ -O -source 1.3 -target 1.3" \
JAVAC="javac"
JAVAINCLUDEDIR=${STAGING_INCDIR}/classpath \
GLIBTOOL="${TARGET_SYS}-libtool --tag=CC"
${JAVAC} meteo/channels/AnalogChannel.java
${JAVAC} meteo/channels/DigitalChannel.java
${JAVAH} -classpath ${S} -d lib/ meteo.channels.AnalogChannel
${JAVAH} -classpath ${S} -d lib/ meteo.channels.DigitalChannel
${CC} ${CFLAGS} ${LDFLAGS} -shared -I${JAVAINCLUDEDIR} lib/AnalogChannel.c -o lib/libAnalogChannel.so
${CC} ${CFLAGS} ${LDFLAGS} -shared -I${JAVAINCLUDEDIR} lib/DigitalChannel.c -o lib/libDigitalChannel.so
${JAR} cvf bin/meteo.jar meteo
${JAVAC} -classpath bin/meteo.jar meteo_test/MeteoTest.java
${JAR} cmf meteo_test/headers.txt bin/meteo_test.jar meteo_test/*.class
}
do_install() {
install -d ${D}/${libdir_jni}
install -d ${D}/${datadir_java}
METEO_PATH="${D}/${libdir_jni}" \
JHOME="${D}/${datadir_java}" \
GLIBTOOL="${TARGET_SYS}-libtool"
install -m 0755 ${S}/lib/lib*.so ${METEO_PATH}
install -m 0755 ${S}/bin/*.jar ${JHOME}
}
do_stage() {
oe_jarinstall -s bin/meteo.jar
oe_jarinstall -s bin/meteo_test.jar
}
PACKAGES = "lib${PN}-jni lib${PN}-dev lib${PN}-jni-dbg lib${PN}-test ${JPN}"
FILES_lib${PN}-jni = "${libdir_jni}/lib*.so"
FILES_lib${PN}-dev = "${libdir_jni}/lib*.la ${libdir_jni}/lib*.a"
FILES_lib${PN}-jni-dbg = "${libdir_jni}/.debug/lib*.so"
FILES_lib${PN}-test = "${datadir_java}/*_test.jar"
Build meteo recipe with the following command
- Code: Select all
bitbake meteo && bitbake package-index
After successful build, on target platform you can deploy the following packages:
libmeteo-jni – dynamic libraries. They will be installed as libAnalogChannel.so and libDigitalChannel.so in /usr/lib/jni directory
libmeteo-java – JAVA API archive. It will be installed as meteo.jar in /usr/share/java directory
libmeteo-test – JAVA API Test application. It will be installed as meteo_test.jar in /usr/share/java directory.
Let’s deploy our application on target platform. Execute the following command on target platform.
- Code: Select all
opkg update && opkg install libmeteo-jni && opkg install libmeteo-java && opkg install libmeteo-test
Start test application
- Code: Select all
cd /usr/share/java
java –jar meteo_test.jar