在Arduino上用Java编程
序
继两个星期前成功实现了java版JVM bytecode解释器TotoroVM(见:http://edisonlovecola.iteye.com/blog/1860545)之后,边着手在arduino平台上实现它c++版,边更新博客(由于忙着实现功能,拖延了更新,以后补上这部分内容)。写完了解释器的代码解释部分,就遇到了从class文件从哪里读取的问题。
Arduino Uno存储分为2K的RAM,1K的EEPROM和32K的Flash,根据java版解释器的经验,一套基本的java框架,至少包含Object, Class, String类,再加上系统功能调用的System和Arduino类,怎么说都不可能压缩到2K内存以下。也考虑过用SD卡来当外存在保存,细想一下,又会有读取速度和通用性的瓶颈,就在我设法压缩ConstantPool大小的过程中。一个新的想法诞生-何不干脆就放弃保存ConstantPool,将它的信息固化到代码中,再进一步,就是直接把java的bytecode直接编译成c++代码,再用avr-gcc进行二次编译,这样还可以充分利用avr-gcc的优化功能。
考虑之后,觉得这个方法可行,经过两个星期的努力,今天TotoroVM Compile版正式诞生。
先试编译一个简单的Arduino程序,类似Blink程序,让13号led灯一秒闪一次:
Main程序代码
package console; import arduino.Arduino; import arduino.Serial; public class Main extends Arduino { public Main() { pinMode(13, OUTPUT); } private boolean v = false; public void loop() { digitalWrite(13, v = !v); delay(1000); } public static void main(String[] args) { new Main().start(); } }
Arduino基本类:
package arduino; public abstract class Arduino { public static final int HIGH = 1; public static final int LOW = 0; public static final int INPUT = 0; public static final int OUTPUT = 1; public static final int INPUT_PULLUP = 2; public static final int SS = 10; public static final int MOSI = 11; public static final int MISO = 12; public static final int SCK = 13; public static final int SDA = 18; public static final int SCL = 19; public static final int LED_BUILTIN = 13; public static final int A0 = 14; public static final int A1 = 15; public static final int A2 = 16; public static final int A3 = 17; public static final int A4 = 18; public static final int A5 = 19; public static final int A6 = 20; public static final int A7 = 21; public static native void init(); public static native void pinMode(int pin, int mode); public static native void digitalWrite(int pin, boolean val); public static native boolean digitalRead(int pin); public static native void analogReference(int mode); public static native int analogRead(int pin); public static native void analogWrite(int pin, int val); public static native long millis(); public static native long micros(); public static native void delay(long ms); public static native void delayMicroseconds(int ms); public static native long pulseIn(int pin, int state, long timeout); public static native void shiftOut(int dataPin, int clockPin, int bitOrder, byte val); public static native byte shiftIn(int dataPin, int clockPin, int bitOrder); public Arduino() { init(); } public void loop() {} public void start() { for(;;) loop(); } }
编译结果:
#include "console_Main.h" // console/Main.() jboolean console_Main__implements_(jreference clz) { return arduino_Arduino__implements_(clz); } // console/Main. () jboolean console_Main__extends_(jreference clz) { if (clz == 72) return 1; return arduino_Arduino__extends_(clz); } // console/Main. () vfunc console_Main__functions_(jint index) { if (index == 1) return console_Main_loop__V; return arduino_Arduino__functions_(index); } // console/Main. () vfunc console_Main__interface_functions_(jreference intf, jint index) { return arduino_Arduino__interface_functions_(intf, index); } // console/Main. ()V void console_Main__init___V() { jint vi = si - 1; si = vi + 1; _0: // ALOAD_0 apush(avalv(0)); _1: // INVOKESPECIAL arduino_Arduino__init___V(); _4: // ALOAD_0 apush(avalv(0)); _5: // ICONST_0 ipush(0); _6: // PUTFIELD tmp1.z = zpop(); tmp2.a = apop(); field_z_console_Main_v(tmp2.a) = tmp1.z; _9: // BIPUSH ipush(13); _11: // ICONST_1 ipush(1); _12: // INVOKESTATIC arduino_Arduino_pinMode_II_V(); _15: // RETURN si = vi; return; } // console/Main.loop()V void console_Main_loop__V() { jint vi = si - 1; si = vi + 1; _0: // BIPUSH ipush(13); _2: // ALOAD_0 apush(avalv(0)); _3: // ALOAD_0 apush(avalv(0)); _4: // GETFIELD tmp1.a = apop(); zpush(field_z_console_Main_v(tmp1.a)); _7: // IFEQ if (! (ipop() == 0) ) { _10: // ICONST_0 ipush(0); _11: // GOTO goto _15; } _14: // ICONST_1 ipush(1); _15: // DUP_X1 dups(0, 1); dups(1, 2); dups(2, 0); si++; _16: // PUTFIELD tmp1.z = zpop(); tmp2.a = apop(); field_z_console_Main_v(tmp2.a) = tmp1.z; _19: // INVOKESTATIC arduino_Arduino_digitalWrite_IZ_V(); _22: // LDC2_W lpush(1000); _25: // INVOKESTATIC arduino_Arduino_delay_J_V(); _28: // RETURN si = vi; return; } // console/Main.main([Ljava/lang/String;)V void console_Main_main__Ljava_lang_String__V() { jint vi = si - 1; si = vi + 1; _0: // NEW apush(allocateInstance(72, 1)); _3: // DUP dups(0, 1); si++; _4: // INVOKESPECIAL console_Main__init___V(); _7: // INVOKEVIRTUAL getVirtualFunction(avals(1), 2)(); _10: // RETURN si = vi; return; }
在电脑上Windows系统中以MinGW编译通过,回家后实战测试Arduino平台!
放上编译结果的C++项目,MinGW和cygwin的gcc应该都可以用。
打算再过一段时候和java版翻译器一起开源,sourceforge还是github呢?求推荐!