Java Embedded 8 İle 32 Bit Mikrodenetleyici Programlama

Embedded programcılığı denildiğinde ilk akla gelen 8/16/32 bitlik mikrodenetleyiciler ve C dilidir. Mikrodenetleyicilere artan ilgimden dolayı C dilini öğrenmek zorunda kalsam da, hep bu minik cihazları Java ile programlamanın yollarını aramışımdır. Bir mikrodenetleyici kullanarak Java dilinde program yazabilmek için, mikrodenetleyicinin üzerinde bir JVM (Java sanal makinası) olması gerekiyor. Bu da ne yazık ki şimdiye kadar hayalden ibaretti, çünkü birkaç kilobyte ya da megabyte hafızayla sınırlı mikrodenetleyicilerde tam teşekküllü bir JVM çalıştırmak mümkün değil.

Bu durum Java Embedded 8 ile değişmiş gibi görünüyor. Java Embedded 8, Java 8 e uyumlu olmaya çalışan bir Java ME sürümü. Bu yeni Java ME ile tam teşekküllü Java programları yazmak mümkün değil, lakin örneğin 256 KB hafızaya sahip Freescale FRDM-K64F Cortex M4 bazlı bir mikrodenetleyiciyi Java dilinde programlamak mümkün. Bunun nasıl yapıldığını bu yazımda aktarmak istiyorum.

free1

Resim 1

Yukarıda yer alan resimde kullandığım mikrodenetleyiciyi görmektesiniz. Özellikleri şöyle:

  • ARM Cortex M4 işlemci
  • 120 MHz hızında
  • 1 MB flash hafızasına sahip
  • 1 MB flash RAM hafızası mevcut
  • LAN girişi var
  • Çift micro-B USB girişli

Bu adresten FRDM-K64F için Oracle firması tarafından implemente edilen JVM i indirebilirsiniz. Benim bu yazıda kullandığım Java Embedded 8.1 JVM sürümü oracle-jmee-8-1-dp2-k64-mbed-bin.zip ismini taşıyor. Paketin içeriği aşağıdaki resimde görülmekte.

free2

Resim 2

Freescale FRDM-K64F için hazırlanan JVM flash dizinide yer alıyor ve 1 MB büyüklüğünde.

free3


Resim 3

Mikrodenetleyici USB üzerinden bilgisayar ile bağlantı kurduğunda, aşağıdaki resimde görüldüğü gibi MBED isminde bir sürücü oluşmakta. JavaVM.bin dosyası buraya kopyalandığında, JVM kurulumu için gerekli flash işlemi gerçekleşiyor. Bunu yapmadan önce, FRDM-K64F için yeni firmware sürümünün burada yer aldığı şekilde uygulanmasında fayda var.

free4


Resim 4

JVM için gerekli konfigürasyon dosyası resim 2 de görülen sd_card dizinide yer alıyor. Burada özellikle ağ erişimi için gerekli ayarların şu şekilde yapılması gerekmekte:

ip.method = static
# IP address,used with static IP configuration only
ip.addr = 192.168.1.100
# Network mask,used with static IP configuration only
ip.netmask = 255.255.255.0
# Network gateway,used with static IP configuration only
ip.gateway = 192.168.1.1

Bu dosyanın java dizininde olacak şekilde bir mini-sdkarta kopyalanması gerekiyor. Sdkartı board üzerindeki sdkart girişine taktıktan sonra, USB port girişi yanında bulunan reset butonuna tıklayarak, JVM in çalışır hale gelmesini sağlıyoruz.

USB üzerinden bilgisayara bağlı olan boarda bağlanmak için, mikrodenetleyicinin hangi COM porta bağlı olduğunu öğrenmemiz gerekiyor. Device Manager üzerinden bunu tespit edebiliriz.

free5


Resim 5

Görüldüğü gibi board benim bilgisarımda 6 numaralı COM porta bağlı. Putty programını kullanarak, boarda bağlantı kurabiliriz.

free6


Resim 6

free7


Resim 7

Ufak bir switch aracılığı ile bilgisayarım ve FRDM-K64F den oluşan bir ağ oluşturdum. Resim 7 de görüldüğü gibi mikrodenetleyicinin IP adresi 192.168.1.100. Mikrodenetleyiciyi kontrol etmek ve programlamak için kullandığım bilgisayar 192.168.1.22 IP adresine sahip.

Mikrodenetleyiciyi Java dilinde programlayabilmek için bir araç seti (toolchain) oluşturmamız gerekiyor. Bu araç setinde programları yazmak için bir yazılım ortamı (IDE), Java derleyicisi ve kullanacağımız Java Embedded kütüphananeleri yer alacak. Benim kullandığım araç seti şu komponentlerden oluşuyor:

Yazılım ortamı olarak Eclipse in 4.4 sürümünü kullanıyorum. Eclipse altında Java ME uygulamaları geliştirebilmek için “Mobile Tools for Java” plugininin kurulmuş olması gerekiyor. Help > Install New Software menüsü üzerinden bu plugin kurulabilir. Kullandığım update sayfası linki: http://download.eclipse.org/mtj/updates/2.0/stable/. Burada plugin hakkında detaylar bulmak mümkün.

Şimdi sırada Java ME SDK Plug-ins for Eclipse var. Bu plugini buradan (oracle-jmesdk-8-1-rr-eclipse-plugins.zip) temin etmek mümkün. Bu plugini bir zip dosyası olarak edindikten sonra, Eclipse altında Help > Install New Software > Add > Add Archive ile kurulumu yapılabilir.

Gerekli kurulumları yaptıktan sonra, Eclipse altında yeni bir Java ME projesi oluştuyoruz.

free8


Resim 8

Geliştirdiğimiz uygulamayı test edebilmek ve mikrodenetleyiciye aktarabilmek için yeni bir donanım konfigurasyonu oluşturmamız gerekiyor.

free9


Resim 9

Configurations panelinde yer alan Add butonu üzerinden yeni bir donanım konfigürasyonu oluşturabiliriz. Bunun için kullandığımız mikrodenetleyiciyi Device Manager uygulaması aracılığı ile tanımlamamız gerekiyor.

free10


Resim 10

Device Manager uygulaması Java ME SDK 8.1 ile geliyor ve bu uygulamayı bin/device-manager.exe üzerinden çalıştırmak mümkün.

Kullandığımız mikrodenetleyiciyi tanımladıktan sonra, Eclipse altında donanım konfigürasyonu oluşturabiliriz.

free11


Resim 11

Device Selector panelinde de görüldüğü gibi, tanımladığımız mikrodenetleyici EmbeddedExternalDevice1 ismini taşıyor.

free12


Resim 12

Aşağıda kullandığım bilgisayar ve mikrodenetleyici arasında bir socket aracılığı ile haberleşmeyi sağlayan sınıflar yer alıyor. Mikrodenetleyici üzerinde bir socket açarak, sunucu olmasını sağlıyoruz. Mikrodenetleyicinin sahip olduğu IP adresi ve 5000 numaralı port üzerinden mikrodenetleyici ile haberleşmek mümkün.

package com.mikrodevre.jme.socket;

import javax.microedition.midlet.MIDlet;

public class SocketMIDlet extends MIDlet {
	private static final int DEFAULT_PORT = 5000;

	private static final String DEFAULT_ADDRESS = "localhost";

	private static final String SERVER = "Server";

	private static final String CLIENT = "Client";

	private boolean isPaused;

	private Server server;

	private Client client;

	public SocketMIDlet() {

		String mode = getAppProperty("Oracle-Demo-Network-Mode");
		if (mode == null) {
			mode = SERVER;
		}

		String address = getAppProperty("Oracle-Demo-Network-Address");
		if (address == null) {
			address = DEFAULT_ADDRESS;
		}

		int port;

		try {
			port = Integer.parseInt(getAppProperty("Oracle-Demo-Network-Port"));
		} catch (NumberFormatException nfe) {
			port = DEFAULT_PORT;
		}

		if (mode.equals(SERVER)) {

			server = new Server(this, port);
			server.start();

		} else if (mode.equals(CLIENT)) {
			client = new Client(this, address, port);
			client.start();
		} else {
			notifyDestroyed();
		}
	}

	public boolean isPaused() {
		return isPaused;
	}

	public void startApp() {
		isPaused = false;
	}

	public void pauseApp() {
		isPaused = true;
	}

	public void destroyApp(boolean unconditional) {
		if (server != null) {
			server.stop();
		}

		if (client != null) {
			client.stop();
		}
	}
}
package com.mikrodevre.jme.socket;

import javax.microedition.io.Connector;
import javax.microedition.io.ServerSocketConnection;
import javax.microedition.io.SocketConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Server implements Runnable {
	private SocketMIDlet parent;

	private boolean stop;

	InputStream is;

	OutputStream os;

	SocketConnection sc;

	ServerSocketConnection scn;

	Sender sender;

	private int port;

	public Server(SocketMIDlet m, int p) {
		parent = m;
		port = p;
	}

	public void start() {
		Thread t = new Thread(this);
		t.start();
	}

	public void run() {
		String portString = String.valueOf(port);

		try {

			System.out.println("Waiting for connection on port " + portString);
			scn = (ServerSocketConnection) Connector.open("socket://:"
					+ portString);

			while (true) {

				// Wait for a connection.
				sc = (SocketConnection) scn.acceptAndOpen();
				System.out.println("Connection accepted");
				is = sc.openInputStream();
				os = sc.openOutputStream();
				sender = new Sender(os);

				// Sending server messages
				sender.send("Server String");

				while (true) {
					StringBuffer sb = new StringBuffer();
					int c;

					while (((c = is.read()) != '\n') && (c != -1)) {
						sb.append((char) c);
					}

					if (c == -1) {
						break;
					}

					System.out.println("Message received - " + sb.toString());

					if (sb.toString().trim().equals("EXIT")) {

						stop();
						System.out.println("Connection is closed");
						break;
					}
				}
			}

			// parent.notifyDestroyed ();
			// parent.destroyApp (true);

		} catch (IOException ioe) {
			if (ioe.getMessage().indexOf("serversocket") >= 0
					&& ioe.getMessage().indexOf("open") >= 0) {
				System.out.println("Server Port " + portString
						+ " is already taken.");
			} else {
				if (!stop) {
					ioe.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Close all open streams
	 */
	public void stop() {
		try {
			stop = true;

			if (is != null) {
				is.close();
			}

			if (os != null) {
				os.close();
			}

			if (sc != null) {
				sc.close();
			}
			//
			// if (scn != null) {
			// scn.close ();
			// }
		} catch (IOException ioe) {
		}
	}
}

package com.mikrodevre.jme.socket;

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

public class Sender extends Thread {
	private OutputStream os;

	private String message;

	public Sender(OutputStream os) {
		this.os = os;
		start();
	}

	public synchronized void send(String msg) {
		message = msg;
		notify();
	}

	public synchronized void run() {
		while (true) {
			// If no client to deal, wait until one connects
			if (message == null) {
				try {
					wait();
				} catch (InterruptedException e) {
				}
			}

			if (message == null) {
				break;
			}

			try {
				os.write(message.getBytes());
				os.write("\r\n".getBytes());
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}

			// Completed client handling, return handler to pool and
			// mark for wait
			message = null;
		}
	}

	public synchronized void stop() {
		message = null;
		notify();
	}
}

package com.mikrodevre.jme.socket;

import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.io.Connector;
import javax.microedition.io.SocketConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Client implements Runnable {
	private SocketMIDlet parent;

	private boolean stop;

	InputStream is;

	OutputStream os;

	SocketConnection sc;

	Sender sender;

	private String address;

	private int port;

	public Client(SocketMIDlet m, String a, int p) {
		parent = m;
		address = a;
		port = p;
	}

	/**
	 * Start the client thread
	 */
	public void start() {
		Thread t = new Thread(this);
		t.start();
	}

	public void run() {
		String portString = String.valueOf(port);
		try {
			sc = (SocketConnection) Connector.open("socket://" + address + ":"
					+ portString);
			System.out.println("Connected to server " + address + " on port "
					+ portString);
			is = sc.openInputStream();
			os = sc.openOutputStream();

			// Start the thread for sending messages - see Sender's main
			// comment for explanation
			sender = new Sender(os);

			sender.send("Client messages");

			// Loop forever, receiving data
			while (true) {
				StringBuffer sb = new StringBuffer();
				int c;

				while (((c = is.read()) != '\n') && (c != -1)) {
					sb.append((char) c);
				}

				if (c == -1) {
					break;
				}

				// Display message to user
				System.out.println("Message received - " + sb.toString());
			}

			stop();
			System.out.println("Connection closed");
			parent.notifyDestroyed();
			parent.destroyApp(true);
		} catch (ConnectionNotFoundException cnfe) {
			System.out
					.println("Client Please run Server MIDlet first on server "
							+ address + " port " + portString);
		} catch (IOException ioe) {
			if (!stop) {
				ioe.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Close all open streams
	 */
	public void stop() {
		try {
			stop = true;

			if (sender != null) {
				sender.stop();
			}

			if (is != null) {
				is.close();
			}

			if (os != null) {
				os.close();
			}

			if (sc != null) {
				sc.close();
			}
		} catch (IOException ioe) {
		}
	}
}

Projenin Application Descriptor dosyasında aşağıdaki kayıtlar yer alıyor:


MIDlet-1: SocketMIDlet,,com.mikrodevre.jme.socket.SocketMIDlet
MIDlet-Jar-URL: JavaMeSocket.jar
MIDlet-Permission-2: javax.microedition.io.SocketProtocolPermission "socket://*:*"\n
MicroEdition-Configuration: CLDC-1.8
MIDlet-Permission-1: javax.microedition.io.SocketProtocolPermission "socket://:*"
MIDlet-Version: 1.0.0
Oracle-Demo-Network-Port: 5000
MIDlet-Vendor: MIDlet Suite Vendor
MIDlet-Name: JavaMeSocket MIDlet Suite
Oracle-Demo-Network-Address: localhost
MicroEdition-Profile: MEEP-8.0
Oracle-Demo-Network-Mode: Server

Uygulamayı aşağıdaki şekilde mikrodenetleyiciye transfer edip, çalıştırabiliriz:

free13


Resim 13

free14


Resim 14

Son resimde görüldüğü gibi, uygulama mikrodenetleyiciye aktarıldı ve çalışır durumda. COM6 üzerinden mikrodenetleyiciye bağlı olduğumda, aşağıdaki ekran çıktısını alıyorum:

free15


Resim 15

Uygulama 5000 numaralı port üzerinden haberleşmeye açık durumda. Mikrodenetleyici üzerinde çalışan socket uygulamasına şu şekilde bağlanabilir ve veri gönderebiliriz:

free16


Resim 16

Ve kullanıcı ile sunucunun aşağıdaki şekilde haberleşebildiklerini görmek mümkün hale geliyor…

free16


Resim 17

Eski Java ME ile yeni Java ME 8 i kıyasladığımızda, artık Java ile gerçek anlamda gömülü uygulamalar geliştirilebilecegini görmekteyiz. Bu artık Java’nın yavaş yavaş embedded dünyasını da ele geçireceği anlamına gelebilir. Java ile embedded dünyasında write ones, run everywhere paradigmasını uygulamak çok daha kolay. Bunun için gerekli olan sadece mikrodenetleyici üzerinde bir JVM. Kodu değiştirmek zorunda kalmadan, değişik mikrodenetleyiciler üzerinde aynı uygulamayı çalıştırmak mümkün. Oracle bunun mümkün olduğunu gösterdi. Artık benim yeni gözdem Java Embedded. Bu bana ayrıca embedded developer olma kapılarını açıyor. Bu konuda programcılara olan talebin yakında artacağını düşünüyorum.


EOF (End Of Fun)
Özcan Acar

4,169 toplam, 1 bugün içinde gösterim

Share Button
1 Yıldız2 Yıldız3 Yıldız4 Yıldız5 Yıldız (1 değerlendirme, ortalama: 5, toplam oy 5)
Loading ... Loading ...

Java Embedded 8 İle 32 Bit Mikrodenetleyici Programlama” üzerine 1 düşünce

Yoruma kapalı.