PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : HaikuVM A Java VM for ARDUINO and other micros using the leJOS runtime.



haikuvm
28.10.2012, 15:34
Hallo,

ich möchte in diesem Forum HaikuVM (http://haiku-vm.sourceforge.net/) vorstellen.

HaikuVM ist eine weitere JAVA VM für Micros (ich habe mal mit ARDUINO und deshalb AVRs angefangen). In diesem Forum wurde schon mal NanoVM vorgestellt die das auch ähnlich konnte. Das Besondere ist, dass ich entschieden habe keine eigene Runtime zu bauen (viel zu aufwendig). Statt dessen nutze ich die von leJOS, einem großen JAVA Projekt für Lego Mindstorms Robotics Invention Kit Bausätze.

HaikuVM funktioniert indem JAVA bytecode nach C Code konvertiert wird um letztlich durch einen C cross compiler für die Zielplattform kompiliert zu werden.

Notwendige Software:

JAVA 1.6
WinAVR (C cross compiler für AVRs)
HaikuVM
Eclipse IDE (optional)


HaikuVM wurde für Hobbyisten gebaut welche Applikationen für den ARDUINO bauen, um für sie die Welt von JAVA zu öffnen.
Ja, mit HaikuVM kann man einen ARDUINO in JAVA programmieren!

Wer schon immer mal das LED seines ARDUINO Boards in einem parallelen Thread blinken lassen wollte ... so geht's:


package arduino.tutorial;

import static haiku.avr.lib.arduino.WProgram.*;

public class BlinkWithThread extends Thread {
static byte ledPin = 13; // LED connected to digital pin 13

public void run() // run over and over again
{
while (true) {
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}
}

public static void main(String[] args) {
pinMode(ledPin, OUTPUT); // sets the digital pin as output
new BlinkWithThread().start();
}
}



Features von HaikuVM:

Preemptive threads
Exceptions
Synchronization
double and float support
Arrays, including multidimensional ones
Recursion
Garbage collection
Supports inheritance and interfaces
Runs on AVR ATmega8, AVR ATmega328p (and Windows, UNIX)
Configurable 64, 32 or 16 bit data types including half precision float
Configurable 16 or 8 bit char type
Tested with Suns JAVA 1.6
Zero Assembler Code
Requires only down to 5k Bytes of code memory (includes HaikuVM and your Java program)
Needs only 250 Bytes RAM (the rest is for your JAVA application)
About 55k Java opcodes per second on 8 Mhz AVR ATmega8


Und noch was: HaikuVM ist so klein, dass es sogar auf einem Atmega8 und dem ASURO Roboter läuft.
Und ja, man kann damit auch einen ASURO Roboter mit JAVA programmieren!

Wer neugierig geworden ist und probieren will wie HaikuVM läuft finden hier (http://haiku-vm.sourceforge.net/) alles Nötige. Hilfe brauche ich vor Allem beim Test und bei der Portierung auf weitere Plattformen.

haikuvm
01.01.2013, 22:38
Schade, dass es hierzu bisher kein Feedback gegeben hat. Denn gerade bei der Roboterprogrammierung vermißt man schon mal schmerzlich Threading. Es geht zwar auch anders ... aber JAVA (und damit HaikuVM) bietet hierfür einen Sprachstandard (synchronized, wait(), etc.) und die Klasse Thread. Vielleicht sollte ich noch mal für HaikuVM werben und mache hiermit auf zwei Highlights aufmerksam:

1) Single line command interface
Nach dem Download genügt ein Einzeiler um ein JAVA Programm (z.B. BlinkWithThread) zu compileren, uploaden und zu starten wenn der Arduino z.B. an Port com5 angeschlossen ist:

C:\haikuVM\bin\haiku -v --Config arduino --Config:Port com5 -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\arduino\tutorial \BlinkWithThread.java

2) Direct memory access
Statische Felder welche mit @NativeCVariable# annotiert sind (wobei # in 8, 16, 32 oder 64) werden direkt auf gleichnamige C Variablen gemapt. Dadurch kann man mit HaikuVM auch hardwarenah programmieren (ohne extra C Code schreiben zu müssen):


...
public static final int UDRE0 = 5;
@NativeCVariable8 // tells HaikuVM to map UCSR0A to an AVR 8Bit C variable called UCSR0A
public static int UCSR0A;
@NativeCVariable8 // tells HaikuVM to map UDR0 to an AVR 8Bit C variable called UDR0
public static int UDR0;
...
public void write(int b) {
while ( (UCSR0A & (1 << UDRE0)) == 0 ) /*poll*/ ;
UDR0=b;
};

oderlachs
05.01.2013, 15:08
Hallo Haiku !
Also ich bin mal den Links gefolgt und mich mal ein bischen belesen , so gut es für mich als nur deutsch-lesender ging. Ist bestimmt nicht schlecht diese HaikuVM, aber ich komme mit der ArduinoIDE ganz gut, ansonsten macht es auch bascom oder avr-studio in gcc bzw. asm. darum werde ich mir nicht noch eine andere Variante der Programmierung annehmen, ohne sie negieren zu wollen....

Was nun die Codegrösse anbetrifft , darüber lässt sich diskutieren ob es dann eine andere Anwendung bei der Programmierung gerecht macht, was man an Speicher einspart...
Wer nun auf den 8K vom Asuro verharren möchte der findet bestimmt auch Wege, was ging früher alles mit dem C-64 und seinen "mickrigen" 64k...
Deine , oder diese VM-Idee ist bestimmt nicht schlecht, aber ich bleib bei meinen "alten Schuhen"...

Gerhard

haikuvm
07.01.2013, 20:49
Hallo Oberlachs,
ist ja mal nett, dass wenigstens einer drauf reagiert.

Deine Argumente versteh' ich nur zu gut. HaikuVM (http://haiku-vm.sourceforge.net/) soll dann auch nicht ArduinoIDE, bascom oder avr-studio mit gcc bzw. asm ersetzen. Sondern eben nur als weitere open-source Alternative zur Verfügung stehen. Vielleicht dann, wenn man mit den Anderen nicht oder nur umständlich weiter kommt (z.B. bei Hirnverzwirnern bei denen eigentlich eine knappe parallelisiert Lösung mit JAVA Threads am elegantesten wäre) oder wenn man mit seinem JAVA Schulwissen auch einen 8bit bzw. 16bit Microcontroller programmieren möchte.

Das mit einer JAVA VM für Microcontroller ist ja auch nicht meine Idee, sondern ich bin da ganz in den Fußstapfen von NanoVM (und anderen). Natürlich habe ich daraus gelernt und hoffe es noch ein bißchen besser (und für den Anwender bequemer) gemacht zu haben.

catweazel
15.01.2013, 23:22
Hi HaikuVM,

super Sache. Kenne die lejos VM vom Lego NXT - damit lässt sich diefinitiv mehr viel mehr aus dem Stein raushlone als mit NXTG.
Und noch besser so hat mein Sohnemann angefangen Java zu programmieren.

Bin dadurch zum FAN von Java geworden, weil viele Sache nicht so komplex sind wie bei C++.

Nun haben wir ein NIBObee bekommen (wegen Löten und näher an der Technik) und wollen natürlich die bewährte Eclipse/Java Umgebung auch für den NIBObee nutzen.
Hatte mich schon mal bei NanoVM eingelesen - sah aber recht fummelig aus.

Da kommt uns HaikuVM gerade recht - soll ja auf dem Asuro funktionieren also dann beim NIBObee allemal - oder ?
Gibt es etwas zu beachten ?

Vielleicht hast du ja ein paar Tips für den Anfang.
Auf jedenfall Fall weiter so -auch wenn noch nicht viele Posts gekommen sind - und nicht beirren lassen.

catweazel

haikuvm
19.01.2013, 14:05
Hallo catweazel,

Na klar geht es weiter! Z.Zt. integriere ich ProGuard in den haikufy Prozess. ProGuard optimiert Bytecode. C Compiler haben so was von Haus aus. JAVA Compiler überlassen das heute lieber der HotSpot VM und die hat HaikuVM eben nicht (wäre auch viel zu groß für einen Micro).

Den NIBObee habe ich nicht. Ich denke aber, dass auch NIBObee damit funktionieren sollte. Z.Zt. läuft HaikuVM definitiv für die Targets:

Atmega8
Atmega328p aber auch für
UBUNTU und
Windows
als Target Maschinen.

Du fragst nach Tipps:

1) Langsam anfangen.
Kopier Dir mit Eclipse das asuro Tutorial

C:\haikuVM\examples\src\main\java\asuro\tutorial

ins neue nibobee Tutorial

C:\haikuVM\examples\src\main\java\nibobee\tutorial

und fange darin an ein Programm nach dem anderen auf den NIBObee um zu schreiben.

2) Folgende Zeilen für NIBObee in HaikuVM.properties anhängen


# NIBObee
nibobee.Extends = avr
nibobee.Target = atmega16
nibobee.MemorySize = 700
nibobee.Clock = 15000000
nibobee.MicroKernel = haiku.avr.lib.asuro.lib2_8_0_rc1.HaikuMicroKernelE x
nibobee.Port = com7


Damit Du auch bequem die Programme aus Schritt 1 mit nur einer Zeile testen kannst:


C:\haikuVM\bin\haiku -v --Config nibobee -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\nibobee\tutorial \BlinkWithThread.java


Über Dein Feedback würde ich mich freuen.

catweazel
19.01.2013, 20:34
Hi Haiku,

danke für die ausführliche Antwort.
Wenn ich morgen Zeit habe, werde ich deine Tips mal umsetzen.

Melde mich wieder hier, wenn es Neuigkeiten/Fragen/Probleme gibt.

catweazel

janvp
31.01.2013, 20:52
Hallo haiku,

Ich würde dieses tolle Projekt gerne mal aus probieren. Leider weiß ich nicht wie ich dies unter Mac OS oder Linux machen soll, da die .bat Dateien auf den Systemen nicht funktionieren. Auf der Projektseite steht, dass haikuvm erfolgreich auf ubuntu Linux getestet worden ist. Gibt es dafür eine Anleitung?

LG Jan

haikuvm
03.02.2013, 22:21
Hallo janvp,

UNIX habe ich etwas vernachlässigt (obwohl ich aus dieser Ecke komme). Ich dachte, alle UNIXer brauchen nur einen Blick auf die bat-Dateien (haikuc, haikulink und haikuupload) werfen und können das schnell in ein shell-Skript übersetzen.

Ich hoffe, dass ich mit der nächsten Version auch UNIX shell-Skripte mitliefern werde. (Falls du bis dahin welche hast übernehme ich die gerne.)

haikuvm
09.02.2013, 22:13
Hallo janvp,

jetzt gibt es die Version 1.0.0 von HaikuVM. In der habe ich Linux Scripte hinzugefügt.
Genaueres zu Linux findet sich hier: http://haiku-vm.sourceforge.net/#Linux

Auf dein feedback bin ich gespannt.
Ansonsten viel Spaß damit.

PS:
Was hast du eigentlich genau vor? Wie soll dein Roboter aussehen?

janvp
13.02.2013, 14:02
Hi Haiku,

Vielen Dank für die Linux-Skripte. Am Wochenende werde ich es mal ausprobieren. Brauche ich einen ISP oder geht das auch mit dem eingebauten Programmer? HEX-Dateien kann man ja mit avrdude auf den Arduino übertragen.

Eigentlich hab ich nach einer Lösung zur Übertragung von Daten zwischen dem NXT und Arduino gesucht. Dabei bin ich über dieses interessante Projekt gestolpert. Die Übertragung hab ich jetzt per I2C gelöst.

kaijoe
13.02.2013, 14:59
Hallo Haiku,

ich habe einen Arduino Uno Selbstbau mit einem ATMega328P.
Benötige ich die Arduino Uno Firmware auf dem ATMega328P und die Arduino Software?


Gruß
Kai

haikuvm
13.02.2013, 22:01
@janvp,
eigentlich sollte alles gehen was der avrdude unterstützt.
- Avrdude für Windows ist im HaikuVM Download mit drin.
- Avrdude etc. für Linux muss man selbst installieren. Hier http://haiku-vm.sourceforge.net/#Linux steht wie's geht.
Als Commandline Parameter übergebe ich 'stk500v1'. Aber das kann man konfigurieren, indem man in 'HaikuVM.properties' die folgende Zeile an seine Bedürfnisse anpasst:


arduino.Upload = avrdude -pm328p -cstk500v1 -P$(HAIKU_PORT) -b57600 -Uflash:w:$(HAIKU_OUTPUT):a

Bei mir funktioniert genau das mit dem Duemilanove.
(Wenn ich das richtig verstehe nutzen die ARDUINO Tools unter der Haube auch avrdude. Vielleicht geht sogar


arduino.Upload = avrdude -pm328p -carduino -P$(HAIKU_PORT) -b57600 -Uflash:w:$(HAIKU_OUTPUT):a

)

Deine I2C Lösung für den Arduino ist z.Zt. in C geschrieben? Und du möchtest diese nach JAVA migrieren? Ist das der Hintergrund für Dein Interesse an HaikuVM?


@kaijoe,
ich kenne deinen Selbstbau nicht. Aber wenn du ihn heute (ohne HaikuVM) flashen kannst - ich nehme an mit avrdude - reicht das. D.h. du brauchst für HaikuVM keine 'Arduino Uno Firmware auf dem ATMega328P' und keine 'Arduino Software' um in JAVA programmieren zu können
Meine Empfehlung:
Kopiere in der Datei 'HaikuVM.properties' den Abschnitt arduino.* nach kaijoe.* . Im neuen kaijoe.* Abschnitt kannst du dann alles spezifisch an deinen Selbstbau anpassen z.B.:


kaijoe.Clock = 20000000

(Falls du abweichend einen 20Mhz Quarz nutzt.)
Wenn du dann beim Arbeiten dem HaikuVM Handbuch folgst, änderst du überall wo "--Config arduino" steht auf "--Config kaijoe" ab.


@janvp, @kaijoe, --> Zusammengefasst
HaikuVM nutzt zum flashen im Prinzip 'avrdude'. Dies ist aber in der Datei 'HaikuVM.properties' beliebig konfigurierbar. (So ist darin z.B. für den ASURO, das dort mitgelieferte flash Tool 'ASUROFlash155' konfiguriert.)

Auf euer Feedback oder Fragen bin ich gespannt.

janvp
15.02.2013, 18:02
Meine ersten Erfahrungen:

Zuerst einmal, ich besitze einen Arduino UNO SMD R2 und HaikuVM 1.0.1.
Deine Anleitung für Linux ist sehr gut verständlich. Ich habe sie auf Ubuntu 12.10 und leicht verändert auf Mac OS X Mountain Lion ausprobiert.
Leider habe ich immer zwei Probleme bemerkt:

Nach dem Aufruf von haikuupload habe ich immer "stk500 Programmer is not responding" angezeigt bekommen. Nach ein paar Recherchen hab ich rausgefunden, dass ich die Baudrate von 57600 auf 115200 ändern muss. Jetzt bekomme ich diese Fehlermeldung nicht mehr.

Aber leider schlägt haikulink davor immer fehl. Hier Die Ausgabe:


whiteapple:arduino jan$ /Users/jan/haikuVM/bin/haikulink -v --Config arduino -o BlinkWithThread.hex /Users/jan/haikuVM/examples/src/main/java/arduino/tutorial/BlinkWithThread
#
#
#
################################################## ###########
# generating c files
################################################## ###########
included; haiku.avr.lib.arduino.HaikuMicroKernelEx.main([Ljava/lang/String;)V
included: haiku.avr.lib.arduino.ArduinoLib.init()V
included: haiku.avr.AVRDefines.sei()V
included# haiku.avr.AVRDefines.<clinit>()V
included: haiku.avr.AVRDefines._BV(I)I
included: haiku.vm.MicroKernel.clinitHaikuMagic()V
included: haiku.avr.lib.arduino.HaikuMicroKernelEx.init()V
included: arduino.tutorial.BlinkWithThread.main([Ljava/lang/String;)V
included: haiku.avr.lib.arduino.WProgram.pinMode(BB)V
included: arduino.tutorial.BlinkWithThread.<init>()V
virtual : start()V
included# arduino.tutorial.BlinkWithThread.<clinit>()V
included# java.lang.Thread.start()V
included: java.lang.Thread.fork()I
virtual : run()V
virtual : stop()V
included# java.lang.Thread.run()V
included# java.lang.Thread.stop()V
included: java.lang.Thread.setStateAndSwitch(I)I
virtual : toString()Ljava/lang/String;
included# java.lang.Throwable.toString()Ljava/lang/String;
virtual : println(Ljava/lang/String;)V
included# java.io.PrintStream.println(Ljava/lang/String;)V
virtual : print(Ljava/lang/String;)V
virtual : print(C)V
included# java.io.PrintStream.print(C)V
virtual : write(I)V
included: java.lang.Thread.currentThread()Ljava/lang/Thread;
included# java.lang.String.toString()Ljava/lang/String;
#### rescan because new virtuals where found
included: haiku.avr.lib.arduino.HaikuMicroKernelEx$1.<init>()V
included: java.io.OutputStream.<init>()V
included# haiku.avr.lib.arduino.HaikuMicroKernelEx$1.write(I )V
included: java.io.PrintStream.<init>(Ljava/io/OutputStream;)V
included: haiku.avr.lib.arduino.HaikuMicroKernelEx$2.<init>()V
included: java.io.InputStream.<init>()V
included: java.lang.Object.<init>()V
included# java.lang.Object.toString()Ljava/lang/String;
included: java.lang.System.identityHashCode(Ljava/lang/Object;)I
included: java.lang.System.getDataAddress(Ljava/lang/Object;)I
included: java.lang.StringBuilder.<init>(Ljava/lang/String;)V
included: java.lang.StringBuilder.<init>()V
virtual : append(Ljava/lang/String;)Ljava/lang/StringBuilder;
included# java.lang.StringBuilder.toString()Ljava/lang/String;
included: java.lang.String.<init>([C)V
included# java.lang.StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
virtual : append(I)Ljava/lang/StringBuilder;
included: java.lang.Thread.<init>()V
included# arduino.tutorial.BlinkWithThread.run()V
included: haiku.avr.lib.arduino.WProgram.digitalWrite(BB)V
included: haiku.avr.lib.arduino.WProgram.delay(J)V
included: java.lang.Thread.nap(J)V
included: java.lang.System.currentTimeMillis()J
included# java.io.PrintStream.print(Ljava/lang/String;)V
virtual : charAt(I)C
virtual : length()I
included# java.lang.String.length()I
included# java.lang.String.charAt(I)C
#### rescan because new virtuals where found
included# java.lang.StringBuilder.append(I)Ljava/lang/StringBuilder;
included: java.lang.String.valueOf(I)Ljava/lang/String;
#### rescan because new virtuals where found
included: java.lang.String.valueOf(C)Ljava/lang/String;
#### rescan because new virtuals where found
included: java.lang.String.<init>(C)V
#### rescan because new virtuals where found
#################### closure complete!


Effective configuration for 'arduino':
Target = atmega328p
MemorySize = 1540
InitialMainThreadStackSize = 142
InitialOtherThreadStackSize = 45
Mode = HAIKU_16_32
Char = HAIKU_CHAR_8
InternalExceptionEnable = NullPointerException | NoSuchMethodError | OutOfMemoryError | ClassCastException | VirtualMachineError
InternalExceptionThrow = 0
Threads = 1
Extension = hex
Clock = 16000000
APP_NAME = BlinkWithThread
VM_BASE = ../../haikuVM
APP_BASE = /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/.
CC_OPT = $(HAIKU_CFLAGS) -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -mmcu=$(HAIKU_TARGET) -DF_CPU=$(HAIKU_CLOCK)UL -MMD -MP
Upload = avrdude -pm328p -cstk500v1 -P$(HAIKU_PORT) -b115200 -F -Uflash:w:$(HAIKU_OUTPUT):a
MicroKernel = haiku.avr.lib.arduino.HaikuMicroKernelEx
Config = arduino
IncrementalGCSlice = 10
Extends = avr
GC = HAIKU_StopTheWorldGC
Output = BlinkWithThread.hex
CFLAGS =
Port = /dev/tty.usbmodem1d171
CLIBS =
HAIKUVM4C = ./haikuVM
LDFLAGS =

link > haiku/avr/lib/arduino/HaikuMicroKernelEx from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
getProperty('InvokeShort')returned null
const class_t haiku_avr_lib_arduino_HaikuMicroKernelEx__class PROGMEM = {
& haiku_vm_MicroKernel__class,
sizeof(haiku_avr_lib_arduino_HaikuMicroKernelEx),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr/lib/arduino/HaikuMicroKernelEx.c

link > haiku/vm/MicroKernel from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_vm_MicroKernel__class PROGMEM = {
& java_lang_Object__class,
sizeof(haiku_vm_MicroKernel),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/vm/MicroKernel.c

link > java/lang/Object from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_Object__class PROGMEM = {
NULL,
sizeof(java_lang_Object),
1,
{
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_Object_toString_Ljava_lang_String)},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/Object.c

link > java/lang/System from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_System__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_System),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/System.c

link > java/io/PrintStream from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_io_PrintStream__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_io_PrintStream),
3,
{
{MSG_print__C_V, (ByteCode *)(&java_io_PrintStream_print_CV)},
{MSG_print__Ljava_lang_String__V, (ByteCode *)(&java_io_PrintStream_print_Ljava_lang_String_V)},
{MSG_println__Ljava_lang_String__V, (ByteCode *)(&java_io_PrintStream_println_Ljava_lang_String_V)},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/io/PrintStream.c

link > java/lang/String from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_String__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_String),
3,
{
{MSG_charAt__I_C, (ByteCode *)(&java_lang_String_charAt_IC)},
{MSG_length___I, (ByteCode *)(&java_lang_String_length_I)},
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_String_toString_Ljava_lang_String)},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/String.c

link > java/lang/StringBuilder from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_StringBuilder__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_StringBuilder),
3,
{
{MSG_append__I_Ljava_lang_StringBuilder, (ByteCode *)(&java_lang_StringBuilder_append_ILjava_lang_StringB uilder)},
{MSG_append__Ljava_lang_String__Ljava_lang_StringB uilder, (ByteCode *)(&java_lang_StringBuilder_append_Ljava_lang_String_L java_lang_StringBuilder)},
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_StringBuilder_toString_Ljava_lang_String )},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/StringBuilder.c

link > java/io/OutputStream from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_io_OutputStream__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_io_OutputStream),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/io/OutputStream.c

link > java/io/IOException from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_io_IOException__class PROGMEM = {
& java_lang_Exception__class,
sizeof(java_io_IOException),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/io/IOException.c

link > java/lang/Exception from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_lang_Exception__class PROGMEM = {
& java_lang_Throwable__class,
sizeof(java_lang_Exception),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/Exception.c

link > java/lang/Throwable from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_Throwable__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_Throwable),
1,
{
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_Throwable_toString_Ljava_lang_String)},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/Throwable.c

PREPROCESSING haikuReleaseLock: java.lang.Thread.haikuReleaseLock(Ljava/lang/Object;)V
link > java/lang/Thread from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_Thread__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_Thread),
3,
{
{MSG_run___V, (ByteCode *)(&java_lang_Thread_run_V)},
{MSG_start___V, (ByteCode *)(&java_lang_Thread_start_V)},
{MSG_stop___V, (ByteCode *)(&java_lang_Thread_stop_V)},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/Thread.c

link > java/lang/Runnable from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_lang_Runnable__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_Runnable),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang/Runnable.c

link > haiku/avr/lib/arduino/HaikuMicroKernelEx$1 from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_HaikuMicroKernelEx_1__class PROGMEM = {
& java_io_OutputStream__class,
sizeof(haiku_avr_lib_arduino_HaikuMicroKernelEx_1) ,
1,
{
{MSG_write__I_V, (ByteCode *)(&haiku_avr_lib_arduino_HaikuMicroKernelEx_1_write_I V)},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr/lib/arduino/HaikuMicroKernelEx$1.c

link > haiku/avr/lib/arduino/HaikuMicroKernelEx$2 from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_HaikuMicroKernelEx_2__class PROGMEM = {
& java_io_InputStream__class,
sizeof(haiku_avr_lib_arduino_HaikuMicroKernelEx_2) ,
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr/lib/arduino/HaikuMicroKernelEx$2.c

link > java/io/InputStream from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_io_InputStream__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_io_InputStream),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/io/InputStream.c

link > haiku/avr/lib/arduino/ArduinoLib from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_ArduinoLib__class PROGMEM = {
& haiku_avr_AVRDefines__class,
sizeof(haiku_avr_lib_arduino_ArduinoLib),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr/lib/arduino/ArduinoLib.c

link > haiku/avr/AVRDefines from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_AVRDefines__class PROGMEM = {
& java_lang_Object__class,
sizeof(haiku_avr_AVRDefines),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr/AVRDefines.c

link > arduino/tutorial/BlinkWithThread from /Users/jan/haikuVM/examples/src/main/java//arduino/tutorial/BlinkWithThread.class
const class_t arduino_tutorial_BlinkWithThread__class PROGMEM = {
& java_lang_Thread__class,
sizeof(arduino_tutorial_BlinkWithThread),
1,
{
{MSG_run___V, (ByteCode *)(&arduino_tutorial_BlinkWithThread_run_V)},
}
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/arduino/tutorial/BlinkWithThread.c

link > haiku/avr/lib/arduino/WProgram from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_WProgram__class PROGMEM = {
& haiku_avr_lib_arduino_ArduinoLib__class,
sizeof(haiku_avr_lib_arduino_WProgram),
0,
};
into /Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr/lib/arduino/WProgram.c

#### rescan because new virtuals where found
#################### closure complete!


#### rescan because new virtuals where found
#################### closure complete!


totalMethods= 49
totalBClength= 1050
totalConstLength= 260
totalClassesLength=216
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./bootloaders/atmega
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./bootloaders/atmega8
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./bootloaders/bt
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./bootloaders/caterina
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./bootloaders/lilypad/src
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./bootloaders/optiboot
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./bootloaders/stk500v2
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./cores/arduino
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./firmwares/arduino-usbdfu
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./firmwares/arduino-usbserial
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuC
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/arduino/tutorial
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr/lib/arduino
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/avr
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/haiku/vm
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/io
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuJava/java/lang
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuVM/native/haiku/vm
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuVM/native/java/lang
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/./haikuVM
################################################## ###########
# generated c files
################################################## ###########
#
#
#
################################################## ###########
# cross compiling
################################################## ###########
#
#
#
Building file: ../../bootloaders/atmega/ATmegaBOOT_168.c
Invoking: AVR Compiler
avr-gcc -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -I"/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/." -I"../../haikuVM" -MF"bootloaders/atmega/ATmegaBOOT_168.d" -MT"bootloaders/atmega/ATmegaBOOT_168.d" -c -o"bootloaders/atmega/ATmegaBOOT_168.o" "../../bootloaders/atmega/ATmegaBOOT_168.c"
../../bootloaders/atmega/ATmegaBOOT_168.c: In function 'main':
../../bootloaders/atmega/ATmegaBOOT_168.c:425:12: error: 'NUM_LED_FLASHES' undeclared (first use in this function)
../../bootloaders/atmega/ATmegaBOOT_168.c:425:12: note: each undeclared identifier is reported only once for each function it appears in
../../bootloaders/atmega/ATmegaBOOT_168.c:586:11: error: 'EEWE' undeclared (first use in this function)
../../bootloaders/atmega/ATmegaBOOT_168.c: In function 'getch':
../../bootloaders/atmega/ATmegaBOOT_168.c:975:15: error: 'MAX_TIME_COUNT' undeclared (first use in this function)
make: *** [bootloaders/atmega/ATmegaBOOT_168.o] Error 1
################################################## ###########
# error while cross compiling
################################################## ###########
whiteapple:arduino jan$

Ich vermute mal, dass etwas mit "NUM_LED_FLASHES", "EEWE" und "MAX_TIME_COUNT" noch nicht ganz funktioniert.

Also ich hab einen NXT mit leJOS und einen Arduino UNO. Diese wollte ich verbinden und bei ein paar Recherchen habe ich HaikuVM zufällig entdeckt. Eigentlich hat HaikuVM nichts mit meinem ursprünglichen Projekt zu tun, aber ich find HaikuVM sehr interessant und wollte es einfach mal ausprobieren. Natürlich werde ich jetzt versuchen, den Code, den ich für den Arduino geschrieben, habe auch in Java zu verwirklichen.

LG Jan

haikuvm
16.02.2013, 10:52
Hallo janvp,

danke für das Feedback.

1) Ach, läßt sich der 'Arduino UNO SMD R2' nur mit 115200 baud flashen? Das wußte ich gar nicht! Ist das auch bei den orginalen ARDUINO Tools für den 'Arduino UNO SMD R2' so?
Zusatzfrage: Läuft 'Arduino UNO SMD R2' auch mit 16Mhz? Wenn nein, musst du das auch in der Datei 'HaikuVM.properties' anpassen.

2) Es ist zwar nett wenn du schreibst "Deine Anleitung für Linux ist sehr gut verständlich.", aber ist sie wohl doch nicht!
Denn wenn ich deine Ausgabe richtig deute hast du
/Users/jan/haikuVM/bin/haikulink
in der aktuellen Directory:
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/
gestartet. (Was ist das überhaupt für eine Directory?)
In der Anleitung steht aber, dass man ausgehend von
/home/bob
dies in
cd haikuVM/myCProject
ausführen soll. Also übersetzt für dein System und deinen User in
/Users/jan/haikuVM/myCProject
Probier das mal. Und ich werde diesen Teil der Anleitung verbessern.

Erklärung:
Haikulink sucht und kompiliert rekursiv alle *.c und *.h Dateien die es in der aktuellen Directory findet. In
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/
scheint es schon einige *.c und *.h Dateien zu geben die nichts mit HaikuVM zu tun haben. (Ich sehe in deiner Ausgabe z.B. die fremde Datei './bootloaders/atmega/ATmegaBOOT_168.c'.) In denen befinden sich offenbar "NUM_LED_FLASHES", "EEWE" und "MAX_TIME_COUNT", die auch nichts mit HaikuVM zu tun haben und bleiben folglich "undeclared".

3) Soll der Arduino UNO bei der Kommunikation mit NXT als I2C master oder slave laufen?


PS:
Die fremde Directory
/Applications/Development/Arduino.app/Contents/Resources/Java/hardware/arduino/
wird jetzt durch deinen Lauf von haikulink "verschmutzt" sein. Tipp, bereinige diese vorsichtshalber indem du die neu entstanden HaikuVM Directories:

haikuC
haikuVM
haikuJava
target
wieder löschst.

kaijoe
16.02.2013, 23:43
Hallo,

ich habe jetzt mal versucht das AVR Blink Beispiel auf den ATMega zu kopieren.
Ich habe folgenden Aufruf verwendet:

C:\haikuVM\myCProject>c:\haikuVM\bin\haiku -v --Config kaijoe -o blink.hex C:\haikuVM\examples\src\main\java\avr\tutorial\Bli nk.java

Die Config dazu sieht wie folgt aus:

#
# Kaijoe: main(); init(); 57600 baud; System.in/out
#
#
kaijoe.arduino.Extends = avr
kaijoe.Target = atmega328p
kaijoe.MemorySize = 1540
kaijoe.Clock = 16000000
kaijoe.MicroKernel = haiku.avr.lib.arduino.HaikuMicroKernelEx
# a lot of \ are needed just to get the following:
# avrdude -pm328p -cstk500v1 -P\\\.\\com17 -b57600 -Uflash:w:SimpleThreading.hex:a
# ugly but works:
#arduino.Port = \\\\\\.\\com17
kaijoe.Port = usb
kaijoe.Upload = avrdude -pm328p -cstk500v1 -P$(HAIKU_PORT) -b57600 -Uflash:w:$(HAIKU_OUTPUT):a

Da ich einen AVRISP MKII verwende, habe ich keine COM-Schnittstelle, deshalb habe ich usb eingegeben.
Wenn ich nun Haiku aufrufe, bekomme ich folgende Fehlermeldung:

################################################## ###########
# generating c files
################################################## ###########
included; haiku.avr.lib.arduino.HaikuMicroKernelEx.main([Ljava/lang/String;)V
getProperty('InternalExceptionThrow')returned null
Exception in thread "main" java.lang.NullPointerException
at haikuvm.pc.tools.Haikufy.supre#################### ###################
ssExceptionSupport(Haikufy.java:395)
at haikuvm.pc.tools.Closure.collectFoos(Closure.java: 93)
at haikuvm.pc.tools.Closure.collectClass(Closure.java :58)
at haikuvm.pc.tools.Closure.collect#Fo#os#(##Cl#os#ur e#.ja#v#a:#131#)#
m #at# #h#a#i#k#u#v
# error while g.penerating c fc.tools.Closure.collectClass(Closureiles
#.java:58)
at haikuvm.pc.tools.Closure.root##################### ###################
##################(#C#
losure.java:35)
at haikuvm.pc.tools.HaikuVM.haikulink(HaikuVM.java:29 5)
at haikuvm.pc.tools.HaikuVM.main(HaikuVM.java:90)
c:\haikuVM\bin\../bin/haikuupload blink.hex
Das System kann den angegebenen Pfad nicht finden.
#ake: *** No rule to make target #`#u#p#l#o#a#d#'#.# # #S#t#o#p#.#
###########################################
# error while uploading files
################################################## ###########

Was mache ich falsch. Liegt das daran, dass ich keinen COM-Port habe?


Gruß
Kai

haikuvm
17.02.2013, 11:03
Hallo kaijoe,

danke für das Feedback.

1) Welche 'Config' meinst du? HaikuVM kennt nur die Konfigurationsdatei 'HaikuVM.properties'. Ich gehe mal davon aus, dass du die mit "Config" meinst.

2) Du schreibst "Die Config dazu sieht wie folgt aus:". Was ich da sehe ist eigentlich viel zu wenig. Wo bleibt der Rest von 'HaikuVM.properties', z.B. der Abschnitt avr.* auf den du dich mit der Zeile "kaijoe.arduino.Extends = avr" beziehst? Hast du den gelöscht? Ich gehe jetzt genauer davon aus, dass du mit "Config" wahrscheinlich deinen neuen Abschnitt kaijoe.* innerhalb der vorhandenen Datei 'HaikuVM.properties' meinst.

2a) Statt
kaijoe.arduino.Extends = avr
sollte es
kaijoe.Extends = avr
heißen.

2b) Die Zeile
kaijoe.Port = usb
kommt mir komisch vor. Welches Windows nutzt du? Meines kann mit der Portangabe "usb" nichts anfangen. Wie, mit welcher Portangabe oder Serial Port, hast du denn deinen Selbstbau ATMega328P bisher geflash?

3) Deine Ausgabe vom Aufruf von "c:\haikuVM\bin\haiku" ist für mich zu kurz und unleserlich. Da kann ich dann nur schlecht weiter helfen. Mach's wie das janvp oben gemacht hat: Kopiere die Ausgabe möglichst vollständig und setzte sie in ein Code-tag.

Bei weiteren Fragen, nur her damit! :-)

janvp
17.02.2013, 17:13
Zu 1: Der Arduino UNO SMD R2 läuft auch mit 16mhz.

Zu 2: Da hab ich wohl etwas übersehen. Leider bekomme ich immer noch einen Fehler, wenn ich es genauso wie beschrieben mache.


whiteapple:myCProject jan$ /Users/jan/haikuVM/bin/haikulink -v --Config arduino -o BlinkWithThread.hex /Users/jan/haikuVM/examples/src/main/java/arduino/tutorial/BlinkWithThread
#
#
#
################################################## ###########
# generating c files
################################################## ###########
included; haiku.avr.lib.arduino.HaikuMicroKernelEx.main([Ljava/lang/String;)V
included: haiku.avr.lib.arduino.ArduinoLib.init()V
included: haiku.avr.AVRDefines.sei()V
included# haiku.avr.AVRDefines.<clinit>()V
included: haiku.avr.AVRDefines._BV(I)I
included: haiku.vm.MicroKernel.clinitHaikuMagic()V
included: haiku.avr.lib.arduino.HaikuMicroKernelEx.init()V
included: arduino.tutorial.BlinkWithThread.main([Ljava/lang/String;)V
included: haiku.avr.lib.arduino.WProgram.pinMode(BB)V
included: arduino.tutorial.BlinkWithThread.<init>()V
virtual : start()V
included# arduino.tutorial.BlinkWithThread.<clinit>()V
included# java.lang.Thread.start()V
included: java.lang.Thread.fork()I
virtual : run()V
virtual : stop()V
included# java.lang.Thread.run()V
included# java.lang.Thread.stop()V
included: java.lang.Thread.setStateAndSwitch(I)I
virtual : toString()Ljava/lang/String;
included# java.lang.Throwable.toString()Ljava/lang/String;
virtual : println(Ljava/lang/String;)V
included# java.io.PrintStream.println(Ljava/lang/String;)V
virtual : print(Ljava/lang/String;)V
virtual : print(C)V
included# java.io.PrintStream.print(C)V
virtual : write(I)V
included: java.lang.Thread.currentThread()Ljava/lang/Thread;
included# java.lang.String.toString()Ljava/lang/String;
#### rescan because new virtuals where found
included: haiku.avr.lib.arduino.HaikuMicroKernelEx$1.<init>()V
included: java.io.OutputStream.<init>()V
included# haiku.avr.lib.arduino.HaikuMicroKernelEx$1.write(I )V
included: java.io.PrintStream.<init>(Ljava/io/OutputStream;)V
included: haiku.avr.lib.arduino.HaikuMicroKernelEx$2.<init>()V
included: java.io.InputStream.<init>()V
included: java.lang.Object.<init>()V
included# java.lang.Object.toString()Ljava/lang/String;
included: java.lang.System.identityHashCode(Ljava/lang/Object;)I
included: java.lang.System.getDataAddress(Ljava/lang/Object;)I
included: java.lang.StringBuilder.<init>(Ljava/lang/String;)V
included: java.lang.StringBuilder.<init>()V
virtual : append(Ljava/lang/String;)Ljava/lang/StringBuilder;
included# java.lang.StringBuilder.toString()Ljava/lang/String;
included: java.lang.String.<init>([C)V
included# java.lang.StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
virtual : append(I)Ljava/lang/StringBuilder;
included: java.lang.Thread.<init>()V
included# arduino.tutorial.BlinkWithThread.run()V
included: haiku.avr.lib.arduino.WProgram.digitalWrite(BB)V
included: haiku.avr.lib.arduino.WProgram.delay(J)V
included: java.lang.Thread.nap(J)V
included: java.lang.System.currentTimeMillis()J
included# java.io.PrintStream.print(Ljava/lang/String;)V
virtual : charAt(I)C
virtual : length()I
included# java.lang.String.length()I
included# java.lang.String.charAt(I)C
#### rescan because new virtuals where found
included# java.lang.StringBuilder.append(I)Ljava/lang/StringBuilder;
included: java.lang.String.valueOf(I)Ljava/lang/String;
#### rescan because new virtuals where found
included: java.lang.String.valueOf(C)Ljava/lang/String;
#### rescan because new virtuals where found
included: java.lang.String.<init>(C)V
#### rescan because new virtuals where found
#################### closure complete!


Effective configuration for 'arduino':
Target = atmega328p
MemorySize = 1540
InitialMainThreadStackSize = 142
InitialOtherThreadStackSize = 45
Mode = HAIKU_16_32
Char = HAIKU_CHAR_8
InternalExceptionEnable = NullPointerException | NoSuchMethodError | OutOfMemoryError | ClassCastException | VirtualMachineError
InternalExceptionThrow = 0
Threads = 1
Extension = hex
Clock = 16000000
APP_NAME = BlinkWithThread
VM_BASE = ../../haikuVM
APP_BASE = /Users/jan/haikuVM/myCProject/.
CC_OPT = $(HAIKU_CFLAGS) -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -mmcu=$(HAIKU_TARGET) -DF_CPU=$(HAIKU_CLOCK)UL -MMD -MP
Upload = avrdude -pm328p -cstk500v1 -P$(HAIKU_PORT) -b115200 -F -Uflash:w:$(HAIKU_OUTPUT):a
MicroKernel = haiku.avr.lib.arduino.HaikuMicroKernelEx
Config = arduino
IncrementalGCSlice = 10
Extends = avr
GC = HAIKU_StopTheWorldGC
Output = BlinkWithThread.hex
CFLAGS =
Port = /dev/tty.usbmodem1d171
CLIBS =
HAIKUVM4C = ./haikuVM
LDFLAGS =

link > haiku/avr/lib/arduino/HaikuMicroKernelEx from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
getProperty('InvokeShort')returned null
const class_t haiku_avr_lib_arduino_HaikuMicroKernelEx__class PROGMEM = {
& haiku_vm_MicroKernel__class,
sizeof(haiku_avr_lib_arduino_HaikuMicroKernelEx),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr/lib/arduino/HaikuMicroKernelEx.c

link > haiku/vm/MicroKernel from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_vm_MicroKernel__class PROGMEM = {
& java_lang_Object__class,
sizeof(haiku_vm_MicroKernel),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/haiku/vm/MicroKernel.c

link > java/lang/Object from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_Object__class PROGMEM = {
NULL,
sizeof(java_lang_Object),
1,
{
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_Object_toString_Ljava_lang_String)},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/Object.c

link > java/lang/System from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_System__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_System),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/System.c

link > java/io/PrintStream from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_io_PrintStream__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_io_PrintStream),
3,
{
{MSG_print__C_V, (ByteCode *)(&java_io_PrintStream_print_CV)},
{MSG_print__Ljava_lang_String__V, (ByteCode *)(&java_io_PrintStream_print_Ljava_lang_String_V)},
{MSG_println__Ljava_lang_String__V, (ByteCode *)(&java_io_PrintStream_println_Ljava_lang_String_V)},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/io/PrintStream.c

link > java/lang/String from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_String__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_String),
3,
{
{MSG_charAt__I_C, (ByteCode *)(&java_lang_String_charAt_IC)},
{MSG_length___I, (ByteCode *)(&java_lang_String_length_I)},
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_String_toString_Ljava_lang_String)},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/String.c

link > java/lang/StringBuilder from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_StringBuilder__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_StringBuilder),
3,
{
{MSG_append__I_Ljava_lang_StringBuilder, (ByteCode *)(&java_lang_StringBuilder_append_ILjava_lang_StringB uilder)},
{MSG_append__Ljava_lang_String__Ljava_lang_StringB uilder, (ByteCode *)(&java_lang_StringBuilder_append_Ljava_lang_String_L java_lang_StringBuilder)},
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_StringBuilder_toString_Ljava_lang_String )},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/StringBuilder.c

link > java/io/OutputStream from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_io_OutputStream__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_io_OutputStream),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/io/OutputStream.c

link > java/io/IOException from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_io_IOException__class PROGMEM = {
& java_lang_Exception__class,
sizeof(java_io_IOException),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/io/IOException.c

link > java/lang/Exception from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_lang_Exception__class PROGMEM = {
& java_lang_Throwable__class,
sizeof(java_lang_Exception),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/Exception.c

link > java/lang/Throwable from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_Throwable__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_Throwable),
1,
{
{MSG_toString___Ljava_lang_String, (ByteCode *)(&java_lang_Throwable_toString_Ljava_lang_String)},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/Throwable.c

PREPROCESSING haikuReleaseLock: java.lang.Thread.haikuReleaseLock(Ljava/lang/Object;)V
link > java/lang/Thread from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_lang_Thread__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_Thread),
3,
{
{MSG_run___V, (ByteCode *)(&java_lang_Thread_run_V)},
{MSG_start___V, (ByteCode *)(&java_lang_Thread_start_V)},
{MSG_stop___V, (ByteCode *)(&java_lang_Thread_stop_V)},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/Thread.c

link > java/lang/Runnable from /Users/jan/haikuVM/bin/../lib/nxt/classes.jar
const class_t java_lang_Runnable__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_lang_Runnable),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/lang/Runnable.c

link > haiku/avr/lib/arduino/HaikuMicroKernelEx$1 from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_HaikuMicroKernelEx_1__class PROGMEM = {
& java_io_OutputStream__class,
sizeof(haiku_avr_lib_arduino_HaikuMicroKernelEx_1) ,
1,
{
{MSG_write__I_V, (ByteCode *)(&haiku_avr_lib_arduino_HaikuMicroKernelEx_1_write_I V)},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr/lib/arduino/HaikuMicroKernelEx$1.c

link > haiku/avr/lib/arduino/HaikuMicroKernelEx$2 from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_HaikuMicroKernelEx_2__class PROGMEM = {
& java_io_InputStream__class,
sizeof(haiku_avr_lib_arduino_HaikuMicroKernelEx_2) ,
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr/lib/arduino/HaikuMicroKernelEx$2.c

link > java/io/InputStream from /Users/jan/haikuVM/bin/../lib/haikuvm/haikuRT.jar
const class_t java_io_InputStream__class PROGMEM = {
& java_lang_Object__class,
sizeof(java_io_InputStream),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/java/io/InputStream.c

link > haiku/avr/lib/arduino/ArduinoLib from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_ArduinoLib__class PROGMEM = {
& haiku_avr_AVRDefines__class,
sizeof(haiku_avr_lib_arduino_ArduinoLib),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr/lib/arduino/ArduinoLib.c

link > haiku/avr/AVRDefines from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_AVRDefines__class PROGMEM = {
& java_lang_Object__class,
sizeof(haiku_avr_AVRDefines),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr/AVRDefines.c

link > arduino/tutorial/BlinkWithThread from /Users/jan/haikuVM/examples/src/main/java//arduino/tutorial/BlinkWithThread.class
const class_t arduino_tutorial_BlinkWithThread__class PROGMEM = {
& java_lang_Thread__class,
sizeof(arduino_tutorial_BlinkWithThread),
1,
{
{MSG_run___V, (ByteCode *)(&arduino_tutorial_BlinkWithThread_run_V)},
}
};
into /Users/jan/haikuVM/myCProject/./haikuJava/arduino/tutorial/BlinkWithThread.c

link > haiku/avr/lib/arduino/WProgram from /Users/jan/haikuVM/bin/../lib/haikuvm/bootstrap.jar
const class_t haiku_avr_lib_arduino_WProgram__class PROGMEM = {
& haiku_avr_lib_arduino_ArduinoLib__class,
sizeof(haiku_avr_lib_arduino_WProgram),
0,
};
into /Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr/lib/arduino/WProgram.c

#### rescan because new virtuals where found
#################### closure complete!


#### rescan because new virtuals where found
#################### closure complete!


totalMethods= 49
totalBClength= 1050
totalConstLength= 260
totalClassesLength=216
/Users/jan/haikuVM/myCProject/./haikuC
/Users/jan/haikuVM/myCProject/./haikuJava/arduino/tutorial
/Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr/lib/arduino
/Users/jan/haikuVM/myCProject/./haikuJava/haiku/avr
/Users/jan/haikuVM/myCProject/./haikuJava/haiku/vm
/Users/jan/haikuVM/myCProject/./haikuJava/java/io
/Users/jan/haikuVM/myCProject/./haikuJava/java/lang
/Users/jan/haikuVM/myCProject/./haikuVM/native/haiku/vm
/Users/jan/haikuVM/myCProject/./haikuVM/native/java/lang
/Users/jan/haikuVM/myCProject/./haikuVM
################################################## ###########
# generated c files
################################################## ###########
#
#
#
################################################## ###########
# cross compiling
################################################## ###########
#
#
#
Building file: ../../haikuC/haikuConfig.c
Invoking: AVR Compiler
avr-gcc -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -I"/Users/jan/haikuVM/myCProject/." -I"../../haikuVM" -MF"haikuC/haikuConfig.d" -MT"haikuC/haikuConfig.d" -c -o"haikuC/haikuConfig.o" "../../haikuC/haikuConfig.c"
In file included from /Users/jan/haikuVM/myCProject/./haikuC/haikuConfig.h:1:0,
from ../../haikuC/haikuConfig.c:1:
../../haikuVM/haikuJ2C.h:355:20: error: expected declaration specifiers or '...' before '*' token
../../haikuVM/haikuJ2C.h:359:2: error: unknown type name 'BytecodeFoo'
../../haikuVM/haikuJ2C.h:364:9: error: unknown type name 'BytecodeFoo'
../../haikuVM/haikuJ2C.h:601:1: error: unknown type name 'BytecodeFoo'
In file included from ../../haikuC/haikuConfig.c:2:0:
../../haikuVM/Bytecodes.h: In function 'OPF_ANEWARRAY':
../../haikuVM/Bytecodes.h:107:10: warning: assignment from incompatible pointer type [enabled by default]
../../haikuVM/Bytecodes.h: In function 'OPF_CHECKCAST':
../../haikuVM/Bytecodes.h:256:19: warning: comparison between pointer and integer [enabled by default]
../../haikuVM/Bytecodes.h:257:3: warning: passing argument 2 of 'throwException' makes integer from pointer without a cast [enabled by default]
../../haikuVM/haikuJ2C.h:547:13: note: expected 'jint' but argument is of type 'jclass'
../../haikuVM/Bytecodes.h: In function 'OPF_IFNONNULL':
../../haikuVM/Bytecodes.h:1409:2: warning: passing argument 1 of 'compare' makes integer from pointer without a cast [enabled by default]
../../haikuVM/haikuJ2C.h:534:13: note: expected 'jint' but argument is of type 'jobject'
../../haikuVM/Bytecodes.h: In function 'OPF_IFNULL':
../../haikuVM/Bytecodes.h:1419:2: warning: passing argument 1 of 'compare' makes integer from pointer without a cast [enabled by default]
../../haikuVM/haikuJ2C.h:534:13: note: expected 'jint' but argument is of type 'jobject'
../../haikuVM/Bytecodes.h: In function 'OPF_IINC':
../../haikuVM/Bytecodes.h:1429:17: warning: initialization from incompatible pointer type [enabled by default]
../../haikuVM/Bytecodes.h: In function 'OPF_IINC1':
../../haikuVM/Bytecodes.h:1439:17: warning: initialization from incompatible pointer type [enabled by default]
../../haikuVM/Bytecodes.h: In function 'OPF_INSTANCEOF':
../../haikuVM/Bytecodes.h:1517:2: warning: passing argument 2 of 'instanceOf' makes pointer from integer without a cast [enabled by default]
../../haikuVM/haikuJ2C.h:554:13: note: expected 'jclass' but argument is of type 'int16_t'
../../haikuVM/Bytecodes.h: In function 'OPF_INVOKEINTERFACE':
../../haikuVM/Bytecodes.h:1529:18: warning: assignment from incompatible pointer type [enabled by default]
../../haikuVM/Bytecodes.h:1529:38: warning: assignment from incompatible pointer type [enabled by default]
../../haikuVM/Bytecodes.h:1531:2: warning: passing argument 1 of 'getMethod' from incompatible pointer type [enabled by default]
../../haikuVM/haikuJ2C.h:538:15: note: expected 'jobject' but argument is of type 'unsigned char *'
../../haikuVM/Bytecodes.h:1532:2: warning: implicit declaration of function 'invoke' [-Wimplicit-function-declaration]
../../haikuVM/Bytecodes.h: In function 'OPF_LDC_C':
../../haikuVM/Bytecodes.h:1847:10: warning: assignment makes pointer from integer without a cast [enabled by default]
../../haikuVM/Bytecodes.h: In function 'OPF_LOOKUPSWITCH':
../../haikuVM/Bytecodes.h:2039:6: warning: assignment makes pointer from integer without a cast [enabled by default]
../../haikuVM/Bytecodes.h:2043:8: warning: assignment makes pointer from integer without a cast [enabled by default]
../../haikuVM/Bytecodes.h: In function 'OPF_MULTIANEWARRAY':
../../haikuVM/Bytecodes.h:2221:2: warning: passing argument 1 of 'multiArray' from incompatible pointer type [enabled by default]
../../haikuVM/haikuJ2C.h:537:13: note: expected 'struct <anonymous> **' but argument is of type 'struct heap_t **'
../../haikuVM/Bytecodes.h: In function 'OPF_NEWARRAY':
../../haikuVM/Bytecodes.h:2242:10: warning: assignment from incompatible pointer type [enabled by default]
../../haikuVM/Bytecodes.h: In function 'OPF_TABLESWITCH':
../../haikuVM/Bytecodes.h:2473:8: warning: assignment makes pointer from integer without a cast [enabled by default]
../../haikuVM/Bytecodes.h:2478:5: warning: assignment makes pointer from integer without a cast [enabled by default]
In file included from ../../haikuC/haikuConfig.c:2:0:
../../haikuVM/Bytecodes.h: In function 'OPF_WIINC':
../../haikuVM/Bytecodes.h:2499:17: warning: initialization from incompatible pointer type [enabled by default]
../../haikuC/haikuConfig.c: At top level:
../../haikuC/haikuConfig.c:590:2: warning: initialization discards 'const' qualifier from pointer target type [enabled by default]
../../haikuC/haikuConfig.c:591:2: warning: initialization discards 'const' qualifier from pointer target type [enabled by default]
../../haikuC/haikuConfig.c:650:18: error: variable 'functionTable' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
make: *** [haikuC/haikuConfig.o] Error 1
################################################## ###########
# error while cross compiling
################################################## ###########
whiteapple:myCProject jan$


Wenn du irgendwelche Dateien wie haikuConfig haben möchtest, musst du es sagen, weil ich nicht so richtig weiß was wichtig ist.

Zu 3: Momentan läuft der Arduino als Slave und ich möchte dies auch weiter so beibehalten.

@kaijoe So eine ähnliche Ausgabe habe ich auch einmal bekommen. Nach dem Aufruf von dos2unix hat sich dies aber erledigt. Da du aber Windows benutzt kann ich nicht sagen, ob es bei dir auch so funktioniert.

haikuvm
17.02.2013, 20:54
Hallo janvp,

ich entnehme deiner Ausgabe zwei Probleme:

1)
../../haikuVM/haikuJ2C.h:355:20: error: expected declaration specifiers or '...' before '*' token
Ändere doch bitte in '/Users/jan/haikuVM/haikuVM/haikuJ2C.h' die Zeile 355
typedef prog_void (* BytecodeFoo)() ;
in
typedef void (* BytecodeFoo)() ;
Ich habe recherchiert und gefunden, dass für avr "prog_void typedef is now deprecated" gilt. Vielleicht liegt hier das Problem. Bei mir tut's allerdings. Deshalb die Frage welche avr-gcc Version du hast? Bei kommt folgendes:


genom2@unx1:~/haikuVM/myCProject$ avr-gcc --version
avr-gcc (GCC) 4.5.3
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.



2)
../../haikuC/haikuConfig.c:650:18: error: variable 'functionTable' must be const in order to be put into read-only section by means of '__attribute__((progmem))'
Ist mir ein Rätsel, denn 'functionTable' ist genau dort als const deklariert?! Vielleicht ist das aber mit 1) behoben.


3) Bevor du dann neu probierst lösche erst alle Directories in:
/Users/jan/haikuVM/myCProject
Denn nur dann wird deine Änderung aus 1) verwendet.

kaijoe
18.02.2013, 17:04
Hallo Haikuvm,

ich habe nicht den ganzen Output angehängt, weil das ziemlich viel.
Ist aber nicht schlimm, da ich den Fehler beseitigt habe.
Ich habe die Zeile kaijoe.arduino.Extends = avr in kaijoe.Extends = avr
geändert und jetzt läuft es durch. Ich habe usb verwendet, da ich keinen Seriellen Port für den
AVRISP MKII habe. Wenn man das Atmel Studio installiert, wird automatisch ein USB-Treiber installiert.
Dieser konfiguriert den MKII so, dass er mit dem ATMel Studion einwandfrei funktioniert, aber leider keinen COM-Port
erstellt. Dazu muss ich libusbW32 installieren, wenn ich das mache habe ich zwar einen COM-Port und die ganzen anderen Lösungen
wie HaikuVM, Arduino und avrdude laufen dann, aber eben das ATmel Studio nicht mehr.

Ich werde dann wohl mal libusb installieren und melde mich dann nochmal.

Gruß
Kai

janvp
18.02.2013, 18:57
Mit dem Ändern von prog_void zu void ist der erste Fehler behoben.

Hier meine avr-gcc Version:

whiteapple:myCProject jan$ avr-gcc --version
avr-gcc (GCC) 4.6.2
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Der zweite Fehler ist leider nicht behoben.

Ich hab mir die Datei haikuConfig.c mit dem Text-Editor angeguckt und da ist mir etwas sonderbares aufgefallen. Immer wenn ich versuche das Leerzeichen nach ByteCode bzw vor * zu entfernen, verschwindet auch der Raum zwischen * und functionTable[]:

Vorher:
const byteCode * functionTable[]..
Nach dem Entfernen von dem Leerzeichen:
const byteCode*functionTable[]..
Ich hätte jetzt gedacht, dass es dann so aussehen müsste:
const byteCode* functionTable[]..

Wenn ich das Leerzeichen bei
const char * functionDesc[]..
entferne, verhält es sich wie erwartet:
const char* functionDesc[]..

Auch scheint der Raum zwischen * und functionTable[] größer zu sein als zwischen * und functionDesc[].

Ich hoffe du verstehst, was ich meine. Vielleicht stimmt etwas mit der Formatierung nicht. Der verwendete Text-Editor heißt TextEdit und ist auf dem Mac vorinstalliert.
Hier kannst du meine haikuConfig.c angucken: link (http://dl.dropbox.com/u/54743553/haikuConfig.c)

Vielen Dank für deine Mühe

haikuvm
18.02.2013, 21:19
Hallo kaijoe,

1) leider sehe ich keinen Anhang in Post #20. (Aber da tut's ja jetzt alles und scheint nicht mehr nötig zu sein.)

2) Wenn ich dich richtig verstehe willst (mittels libusbW32) einen COM-Port für avrdude erzeugen?!
Das ist ok. Aber weshalb kannst du nicht AVRISP MKII für deinen Selbstbau weiter verwenden? So wie ich dich verstehe hat das doch zuvor funktioniert. Ich kenne mich mit AVRISP MKII zwar überhaupt nicht aus aber ich nehme mal an - mit viel Phantasie - du hast das circa so zum flashen genutzt:
avrisp.exe option1 option2 ... myHexFile.hex
Trag das doch mal (statt avrdude) in 'HaikuVM.properties' ein. Circa so:
kaijoe.Upload = avrisp.exe option1 option2 ... $(HAIKU_OUTPUT)
und berichte mir mal.

Wenn's funktioniert haben Andere und ich gleich ein Beispiel für AVRISP MKII. Würde mich freuen.

- - - Aktualisiert - - -

- - - Aktualisiert - - -

Hallo janvp,

1) Mit "avr-gcc (GCC) 4.6.2" habe ich ein Problem! Denn das gibt es (noch) nicht für mein UBUNTU 12. (Daher kommt auch das prog_void-Problem. Die haben das in dieser Version mit dem "deprecated" wahrscheinlich schon durchgezogen.) Da ich nicht hoch auf 4.6.2 komme, kann ich dich nur bitten runter auf 4.5.3 zu kommen.

Ich gehe davon aus, dass damit auch die zweite Fehlermeldung verschwindet:
../../haikuC/haikuConfig.c:650:18: error: variable 'functionTable' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

2) Das mit den sonderbaren Leerräumen liegt an TABs ('\t') und ist kein Problem. Zwischen "ByteCode *" ist ein Leerzeichen und zwischen "* functionTable[]" ist ein Tabulatorzeichen. Nimmst du das Leerzeichen weg verschiebt sich, in dem von dir verwendeten Editor, die Tabulatorgrenze. In diesem Fall scheint das TAB ganz zu kollabieren. Fürs Auge macht das was aus, für den C-Code nicht. ;-)

kaijoe
19.02.2013, 09:51
Hallo Haikuvm,

der AVRISPMKII ist der Programmer für die uC. AVRISP.EXE gibt es nicht. Ich weiß leider nicht
was das Atmel Studio 6 zum Übertragen nimmt. Der AVRISPMKII ist auf jeden Fall Hardware.
Ich habe es aber jetzt hinbekommen.

D.h. ich habe das Atmel Studio mit all seinen Komponenten, auch den USB Treibern, deinstalliert und danach
den Treiber libusbWin32 installiert.
Wenn ich jetzt den Programmer (AVRISPMKII) in den USB-Port meines Notebooks stecke,
wird er als libusb Device im Gerätemanager erkannt.
Nun habe ich mit libusbWIN32 aber auch das Problem, dass ich keinen COMPORT erstellt bekomme.
Allerdings ist es bei libusbWIN32 so, dass ich bei meinem kaijoe Abschnitt in der HAIKUVM.properties
als COMPORT usb angeben kann, statt eines COMPORTS.

D.h.

kaijoe.Port = \\\\\\.\\comX funktioniert nicht.

kaijoe.Port = usb funktioniert einwandfrei.


Ich konnte Beispielprogramme kompilieren und auch übertragen.

Jetzt kann ich mich mal damit beschäftigen eigene Programme zu schreiben.

Eine Frage hätte ich noch. Wird der Output von haiku.bat irgendwo protokolliert?
Ich bekomme Warnings angezeigt bei der Ausführung von haiku.bat. Da der output aber ziemlich schnell über den Bildschirm
scrollt und der Puffer der Eingabeaufforderung ziemlich klein ist kann ich im Moment nicht sagen was das
für Warnings sind.


Gruß
Kai

haikuvm
19.02.2013, 21:16
Hallo kaijoe,

1) suuuper, freut mich zu hören, dass es mit deinem Selbstbau klappt.

2) Also ich mache das so (stdout und stderr getrennt):
c:\haikuVM\bin\haiku -v --Config kaijoe -o blink.hex C:\haikuVM\examples\src\main\java\avr\tutorial\Bli nk.java >std.out 2>std.err
oder so (stdout und stderr zusammen):
c:\haikuVM\bin\haiku -v --Config kaijoe -o blink.hex C:\haikuVM\examples\src\main\java\avr\tutorial\Bli nk.java >std.outerr 2>&1

mlade
20.02.2013, 06:23
Hi,
ich versuche, den Nibobee mit Java zu programmieren. Einfache Dinge wie zum Beispiel die Ansteuerung der LED's gelingen mir auch ganz gut, Probleme machen mir - wie eigentlich zu erwarten - die Hardware-Interrupts.
Java ist ja nun nicht für die direkte Kommunikation mit der Hardware gedacht. Also war mein Gedanke, die Interrupt-Routinen in C zu schreiben, und diese dann per JNI in meine Java-Anwendung einzubinden. In C (und ASM) hab ich mit dem Asuro auch schon einige Erfahrungen sammeln können, auch die Bearbeitung von Interrupts. Mit Java und insbesondere mit dem JNI habe ich aber keine Erfahrungen.

Hat jemand einen Lösungsansatz für mich?

Versucht habe ich, die Interrupts irgendwie ohne JNI einzubinden, indem ich einfach per setMemory8 GICR, MCUCR und SREG konfiguriert und dann eine ISR (wie ich naiv glaubte) namens SIGNAL_SIG_INTERRUPT1 zu schreiben. IRGENDWAS tut der Robot auch bei dem Interrupt, ich bin mir allerdings ziemlich sicher, dass unmittelbar ein RESET folgt.

Übrigens: Ich nutze außer haiku.vm.MemoryAccess keine vorbereiteten Pakete, auch nicht die Asuro-Lib (weil zum Beispiel Sleep oder Msleep nicht funktioniert, der Asuro ist ja ganz anders konfiguriert).

kaijoe
20.02.2013, 08:18
Danke Haikuvm,

das mit der Umleitung werde ich ausprobieren.
Ich wusste nicht, dass das auch in Windows geht.

janvp
20.02.2013, 13:06
Hallo haikuvm,

Ich hab jetzt avr-gcc 4.5.1 und es funktioniert!
vielen Dank, nun kann ich mich zu eigenen Projekten vor wagen.

haikuvm
20.02.2013, 23:21
Hallo mlade,

ja, gerne helfe ich. Deutlich besser gelingt die Hilfe wenn ich viel Feedback kriege.

1) So habe ich in Post #6 schon mal was zum NIBObee geschrieben. Aber leider noch kein Feedback bekommen. Tut's das so, wie dort beschrieben, für dich?

2) Ja, wenn du nichts vom ASURO übernehmen willst, nimm einen noch einfacheren MicroKernel und trag das Folgende in Datei 'HaikuVM.properties' ein:


# NIBObee
nibobee.Extends = avr
nibobee.Target = atmega16
nibobee.MemorySize = 700
nibobee.Clock = 15000000
nibobee.MicroKernel = haiku.avr.lib.simple010.HaikuMicroKernel

3) Fang mit dem Programm 'avr/tutorial/BlinkSimple.java' an und steigere dich dann zu 'avr/tutorial/Blink.java'. Wahrscheinlich mußt du den Port änderen. Hin zu dem Port auf dem der NIBObee seine LEDs hat. (Deine Änderung würde mich als Feedback interessieren.) Mich würde auch interessieren wie du in 'avr/tutorial/Blink.java' den Wert für TCCR0B setzt, damit Thread.sleep(..), Thread.wait(..), System.currentTimeMillis() und der interne Thread Scheduler von HaikuVM den richtigen Millisekunden Takt bei 15Mhz bekommen?!

4) Interrupts ja! Aber wie du schon aus 3) erahnen kannst, bitte nicht 'TIMER0_OVF_vect' verwenden (findet sich in Datei './haikuVM/simpleOS.c'), denn den braucht HaikuVM selbst.

5) Ich werde auf der HaikuVM Page demnächst eine Serie kleiner Tutorials bringen. Eines davon wird Interrupts behandeln. Wir können ja hier - mit deiner Hilfe - damit beginnen ;-) :
Zu diesem Tutorial wird es die Datei './haikuVM/myCProject/tutorials/interrupt.c' geben. Ich bin aber noch nicht so weit und habe nur eine Skizze und erste Idee. Vielleicht kannst du mir beim vervollständigen helfen? Der einfache Plan (für Anfänger) lautet so: Es soll (in C) einen Interrupthandler für den TIMER2 geben der nichts weiter macht als die Interrupts zählen. Mit der HaikuVM-JNI Funktion 'native_avr_tutorial_Interrupt1_getTimer2_J(..)' wird der Zähler ausgelesen. Man braucht dann nur noch 'Java_avr_tutorial_Interrupt1_getTimer2( JNIEnv *env, jobject obj)' selbst zu schreiben.

Die Datei './haikuVM/myCProject/tutorials/interrupt.c' wird deshalb ca. so aussehen:


#include "haikuJ2C.h"
#include <avr/interrupt.h>

volatile static jlong timer2_interrupts = 0;

SIGNAL (SIG_OVERFLOW2)
{
timer2_interrupts ++;
}

jlong Java_avr_tutorial_Interrupt1_getTimer2( JNIEnv *env, jobject obj) {
jlong value;
uint8_t oldSREG = SREG;
cli();
value= timer2_interrupts;
SREG = oldSREG;
return value;
}

/**
* Automatic generated (see ./myCProject/haikuC/haikuJNI.c)
* getTimer2()J
*/
void native_avr_tutorial_Interrupt1_getTimer2_J(void) {
pushTop(); // Save variable top onto stack.
{
jobject obj = NULL;
JNIEnv *env = NULL;
top.j = Java_avr_tutorial_Interrupt1_getTimer2(env, obj);
}
// Variable top holds the return value. But we have to push the lower half.
pushTop0();
}

Im JAVA Programm des Tutorials 'avr/tutorial/Interrupt1.java' (sieht ähnlich aus wie 'avr/tutorial/Blink.java') wird die native Funktion getTimer2() deklariert:


public static native long getTimer2();

In der JAVA main(..) Methode von 'avr/tutorial/Interrupt1.java' wird zu Beginn der TIMER2 und sein Interrupt gesetzt ca.:


TCCR2 = _BV(WGM20) | _BV(WGM21) | _BV(COM20) | _BV(COM21) | _BV(CS20);
TIMSK |= _BV(TOIE2);

und dann in einer (Endlos-) Schleife getTime2() aufgerufen um den Wert (timer2_interrupts) auszulesen.

6) Vielleicht, mit deiner Hilfe würde ich auch gerne ein Interrupt Tutorial für den ADC machen.

mlade
21.02.2013, 04:51
Hi,
danke für die schnelle und vor allem umfangreiche Antwort.
Zu 1:
Ja, nach der Anleitung in diesem Post habe ich begonnen. Allerdings habe ich noch nie avrdude benutzt, und da das Hochladen so nicht auf Anhieb funktioniert hat, habe ich weiterhin den nibobee-programmer benutzt, indem ich die entstehende .hex-Datei aus dem Verzeichnis target\cross hochgeladen hab.
Ich bin jedoch schon bald darüber gestolpert, dass die in der Asurolib definierten Methoden Sleep() und Msleep() nicht funktionieren. Ich hab mir das bis jetzt noch nicht näher angesehen, sondern einfach eine Schleife benutzt, um Zeit zu verschlafen, denn ich wollte ja erst mal einfach nur mit einer LED blinken. Ich gehe mal davon aus, das die Konfiguration des Timers, so wie sie für den Asuro benutzt wird, nicht für den nibobee funktioniert.
Zu 2:
Ok, werd ich machen.
Zu 3:
Meine Umsetzung von "Blinksimple" besteht aus 2 Klassen. Led.java definiert die Klassenkonstanten PORTB und DDRB, welche die Adressen der gleichnamigen Register enthalten. Außerdem gibt es 3 Klassenmethoden, weche die Initialisierung der Hardware übernehmen, die 4 LED's ein- oder ausschalten oder von einer zur nächsten weiterschalten.
Led.java:


import static haiku.vm.MemoryAccess.*;

public class Led {
public static final int DDRB=(((0x17) + 0x20));
public static final int PORTB=(((0x18) + 0x20));

public static void LedInit() {
setMemory8(DDRB,(getMemory8(DDRB)| 0b00001111));
setMemory8(PORTB, 0b00000001);
}

public static void LedSwitch(){
int portb;
portb=getMemory8(PORTB);
if (portb < 0b00001111){
setMemory8(PORTB, (portb << 1));
}
else {
setMemory8(PORTB, 0b00000001);
}
}

public static void LedSet(int leds){
if (leds > 0b00001111){
leds=0b00001111;
}
setMemory8(PORTB,leds);
}
}

Die Klasse TestLed.java enthält eine Klassenmethode, welche die Schleife für die Wartezeit durchläuft (als simpler Ersatz für Sleep(), wird später natürlich über den Timer geregelt, da gehe ich als nächstes dran). Außerdem enthält sie main(), in welcher einfach nur eine Art Lauflicht gebaut wird, indem nach der Initialisierung Led nach der anderen an- und ausgeschaltet wird (ich hätte auch statt LedSet mit zaehler einfach LedSwitch ohne Argumente verwenden können):
TestLed.java:


public class TestLed {

private static void Sleep (int msec) {
int j;
for (int i=0; i<(msec*7); i++) {
j=i;
}
}

public static void main (String args[]){
int zaehler=0;
Led.LedInit(); // 1. Led an
while (true){
while (zaehler < 4){
Led.LedSet((0b00000001 << zaehler));
zaehler++;
Sleep(1000);
}
zaehler=0;
}
}
}

Zu 4-6: Ok, das ist doch mal ein Lösungsansatz, DANKE! :-) Ich werde damit mal rumspielen. Sobald was funktionierendes dabei rum kommt, poste ich selbstverständlich hier. Ich hab auch schon gleich die erste Frage: Was enthält top, die du mit pushTop() auf dem Stack ablegst (also bevor ...getTimer2() aufgerufen wird?
ADC ist der nächste Schritt, das ist klar. Sobald ich geradeaus fahren kann, steht natürlich Linienverfolgung auf dem "Grundschul"plan eines Roboterprogrammierers. ;-)

Vielen Dank nochmal für die Hilfe, bis demnächst!

haikuvm
21.02.2013, 20:02
Hallo mlade,

zu 1)
a) Die ASURO Methoden Sleep() und Msleep() - so wie sie in HaikuVM implementiert sind - funktionieren nur mit einem Atmega8.
b) Ich hatte die Hoffnung, dass der "nibobee-programmer" eine EXE Datei ist die auch Commandline Optionen versteht. Dann nämlich kann ich ihn in der nächsten Version als


nibobee.Upload = nibobee-programmer.exe option1 option2 ... $(HAIKU_OUTPUT)

in 'HaikuVM.properties' einbauen.

zu 3) Leider ist dein Code unleserlich. Editier doch bitte deine Post noch einmal und schließ ihn in einen CODE-Block ein. Würde mich freuen.

7) "nächste Frage" pushTop(): Zunächst einmal sollte an diesen automatisch generierten Funktionen 'native_*' wirklich nichts verändert werden, sonst kommt die HaikuVM durcheinander.
Die JAVA VM ist im Wesentlichen eine Stackmaschine (also auch HaikuVM). Alle Operationen geschehen auf dem Stack. Das ist ein ewiges auf und ab (push und pop). Beispiel 3 + 4:


push(3);
push(4);
push(pop() + pop());

Jetzt steht das Resultat 7 auf dem Stacktop und man hat dazu 5 push&pop gebraucht.

Besonders heiß geht es am Stacktop zu. Wenn man das weiß kann man push&pop sparen indem man den Stacktop gerade nicht auf dem Stack hält, sondern in einer Variablen (hier top):


push(top); top=3;
push(top); top=4;
top=(top + pop());

Jetzt steht das Resultat 7 in top und man hat nur 3 push&pop gebraucht. (Da ich push(top) oft brauche gibt es die Abkürzung pushTop().)
Jetzt zu deiner Frage:
Irgendwas ist immer in top. Da aber getTimer2() keinen Parameter braucht kann der Inhalt von top nicht für getTimer2() bestimmt sein. Deshalb muß ich top sichern ( und zwar auf den Stack mittels pushTop() ) bevor top von 'Java_avr_tutorial_Interrupt1_getTimer2(env, obj)' überschrieben wird.

8 ) Und ... ich muß dir widersprechen: HaikuVM ist unbedingt auch für die direkte Kommunikation mit der Hardware gedacht. Das was man in C sonst in Interrupt Routinen macht sollte man in HaikuVM mit parallelen Threads lösen. (Ähnlich wie die Propellerchips sehr gut ohne Interrupts aus kommen.)

mlade
22.02.2013, 20:45
So,
blinken mit Threads funktioniert jetzt.
Etwas verwirrt hat mich deine Frage nach der Einstellung von TCCR0B. Der nibobee ist standardmäßig mit einem atmega16 ausgestattet, der für den Timer0 nur ein TCCR hat. Ich war mir daher nicht sicher, ober der Timer0 überhaupt der richtige Timer für die Zeitmessung ist, wenn der atmega16 benutzt wird. Aber dein Hinweis auf SimpleOS.c hat da weiter geholfen.
Ich habe TCCR0 auf 3 gesetzt, also die beiden Clock-Select-Bits aktiviert und so den Prescaler clock/64 gewählt. Das bedeutet allerdings, dass meine Millisekunden in Wirklichkeit ca. 1,12 Millisekunden dauern. Soweit ich sehe, müsste ich für einen korrekten Wert SimpleOS.c anpassen. Genügt es, wenn ich dies in der Kopie in myProject\haikuvM mache, oder muss ich sonst noch etwas beachten?

Der Nibobee-Programmer nimmt, soweit ich erkennen kann, keine Commandline-Optionen an. Dahingehende Versuche hat er ignoriert.

Hier folgen noch meine Anpassungen an deiner avr\tutorial\BlinkAsync.java:


...
import haiku.vm.NativeCVariable8;
...
@NativeCVariable8
public static volatile int SREG;
...
// In main():
SREG |= (1 << 7); // Interrupts ein
// Timer-Konfiguration: Prescaler auf 1/64
TCCR0 |= (1 << CS01);
TCCR0 |= (1 << CS00);
TIMSK |= (1 << TOIE0); // Timer-Overflow-Interrupt-Enable Timer0
...


Ich werde als nächstes versuchen, für die beiden externen Interrupts INT0 und INT1 Routinen zu schreiben analog zu deiner Idee für den Timer2.

Vielen Dank für deine Hilfe, ohne wäre ich nicht weiter gekommen.

haikuvm
23.02.2013, 10:01
Hallo mlade,

1) Naja, ich kenne nicht jeden Microcontroller so genau und wußte nicht, dass der ATmega16 das Register TCCR0B nicht kennt. Sorry für das Stiften von Verwirrung.
In 'SimpleOS.c' findest du in der Funktion millis() die Zeile:


return m * 128 / 125;

Hier solltest du auf ((m * 128 / 125) * 1.12) ändern. (Also, ich habe rein rechnerisch den Faktor 1.066667!) Probiere deshalb doch mal:


return m * 71 / 65;

oder noch genauer


return m * 225 / 206;

oder noch genauer


return m * 2048 / 1875;

In der nächsten Version werde ich das dann via 'HaikuVM.properties' konfigurierbar machen. Aber berichte erst mal ob der Gedanke in der Praxis taugt.

2) Besser ist für dich wenn du die Änderung in 'haikuVM\SimpleOS.c' machst und dann (nur) 'myCProject\haikuVM\' löschst. Nur dann profitierst du auch bei deinem nächsten NIBOBEE Projekt ( vielleicht in 'myCProject2\' ) von dieser Änderung.

3) Wie heißt denn der Nibobee-Programmer genau. Dann kann ich ihn wenigstens bei der nächsten Version (eben ganz ohne Commandline-Option) eintragen. In der Hoffnung, dass es für NIBOBEEisten dann noch etwas bequemer wird.

4) Aah, und wie ich sehe bist du von get-/setMemory(..) zu direct memory access übergegangen. (Ist doch bequemer so, oder?)

5) (Ist als Info gedacht: ) Ach ja, noch was, allgemein sind die Interrupts bei HaikuVM schon enabled.


...
// In main():
SREG |= (1 << 7); // Interrupts ein
...

Schadet nicht, ist aber Doppeltgemoppelt. (SREG habe ich jetzt trotzdem in AVRConstants.java aufgenommen. Danke für den versteckten Tipp.)

mlade
24.02.2013, 10:02
Der Programmer heißt NIBObeeProgrammer.exe und wird standardmäßig in "C:\Program Files (x86)\NIBObeeLib" installiert.

Ich habe ein Problem beim Versuch, c einzubinden. So wie es aussieht, kennt der Compiler JNIEnv nicht. Die Fehlermeldungen lauten:


../../int0.c:11: error: expected ')' before '*' token
../../int0.c: In function 'native_IntTest_getCount0_J':
../../int0.c:30: error: 'JNIEnv' undeclared (first use in this function)
../../int0.c:30: error: (Each undeclared identifier is reported only once
../../int0.c:30: error: for each function it appears in.)
../../int0.c:30: error: 'env' undeclared (first use in this function)
../../int0.c:31: warning: implicit declaration of function 'Java_IntTest_getCount0'


int0.c:


#include "haikuJ2C.h" // Header-Datei statt jni.h?
#include <avr/interrupt.h>

volatile static jlong jl_intcount0 = 0;

SIGNAL (SIG_INTERRUPT0) //INT0_vect
{
jl_intcount0 ++;
}

jlong Java_IntTest_getCount0( JNIEnv *env, jobject obj) {
jlong value;
uint8_t oldSREG = SREG;
cli();
value= jl_intcount0;
SREG = oldSREG;
return value;
}


/**
* Automatic generated (see ./myCProject/haikuC/haikuJNI.c)
* getTimer2()J
*/

void native_IntTest_getCount0_J(void) {
pushTop(); // Save variable top onto stack.
{
jobject obj = NULL;
JNIEnv *env = NULL;
top.j = Java_IntTest_getCount0(env, obj);
}
// Variable top holds the return value. But we have to push the lower half.
pushTop0();
}


Ich vermute mal, dass alles ab Zeile 20 raus muss, aber allein daran liegt es nicht. Ich vermisse auch das Einbinden von jni.h. Irgendwie scheint ein Schritt zu fehlen...

haikuvm
24.02.2013, 14:23
Hallo mlade,

1) Danke für die Info zum Programmer. Wird gleich eingebaut.

2) Ja, das stimmt, noch gibt es JNIEnv nicht. (Sorry, noch bin ich nicht fertig mit dem Interrupt- und JNI-Tutorial und auch 'jni.h' gibt es noch nicht.)
JNIEnv bzw. env wird aber auch in 'int0.c' nicht gebraucht. Deshalb kannst du es in 'int0.c' wie folgt deklarieren:


typedef void JNIEnv;


3) Aber nein, alles ("ab Zeile 20") kann und muß drin bleiben. Du hast es dir nur schwer gemacht und 'native_IntTest_getCount0_J()' tatsächlich selbst geschrieben. Schau doch mal wirklich in './myCProject/haikuC/haikuJNI.c' nach. Da sollte diese Funktion, frisch generiert, drin stehen. (Falls du sie schon in Java (als native) deklariert hast.)

4) Welche IDE nutzt du? Falls Eclipse, hat dir das hier (http://haiku-vm.sourceforge.net/#Eclipse) geholfen?

janvp
24.02.2013, 14:37
Hallo haikuvm,
Ich wollte nun den NXT mit dem Arduino über I2C verbinden. Anscheinend gibt es mit haiku.avr.lib.arduino.save.TWI schon eine Klasse, die den Einstieg erleichtern soll.
Gibt es eine Dokumentation oder die Source zu zu dieser Klasse?
Den Arduino mit haikuvm möchte ich als Slave betreiben.

haikuvm
24.02.2013, 15:26
Hallo janvp,

1) Da habe ich wohl den Überblick verloren. Wo hast du 'haiku.avr.lib.arduino.save.TWI' denn her? Welcher download welches SVN release? Denn das wollte ich erst veröffentlichen wenn es wirklich funktioniert.

2) Statt dessen kann ich dir einen funktionierenden TWI Master für den LSM303DLM anbieten, rein in Java geschreiben. (Obwohl, wie man sieht, es ist ein gefühlvoll gemoddetes C Programm.) In der Hoffnung, das es dir hilft. Dies läuft z.Zt. am besten mit der arduino Config und dann mit einem putty auf 57600 baud.
Wenn du mit deinem TWI Slave fertig bist übernehme ich den gerne auch in die Gallerie. Und die wird beim nächtsten release mit veröffentlicht.


package avr.gallerie.twi;

import static haiku.avr.ATmega328p.*;
import static haiku.avr.lib.arduino.WProgram.*;
import static haiku.avr.lib.arduino.Print.*;
import static java.lang.Math.*;

/**
* http://www.pololu.com/catalog/product/1273
*
* arduino-1.0.2 -> Binäre Sketchgröße: 9.446 Bytes
* HaikuVM -> 15104 (with code reduced to the min: 11684)
*
*
*/
public class Compass {
/*
* compass: for the Orangutan LV, SV, SVP, and X2.
*
* This example program demonstrates how to use the LSM303DLM 3D compass and
* accelerometer carrier with an Orangutan robot controller.
*
* The LSM303DLM carrier should be connected to the Orangutan's I2C pins; on the
* LV and SV, these are PC5 and PC4 for SCL and SDA, respectively, and on the
* SVP and X2, these are PC0 and PC1, respectively. (PC0 and PC1 are LCD data
* lines on the X2, but this code will work on it if the LCD is not used, or
* used in 4-bit mode.)
*
* http://www.pololu.com
* http://forum.pololu.com

#include <avr/io.h>
#include <pololu/orangutan.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"

* This program assumes that the LSM303DLM carrier is oriented with X pointing
* to the right, Y pointing backward, and Z pointing down (toward the ground).
* The code compensates for tilts of up to 90 degrees away from horizontal.
* Vector p should be defined as pointing forward, parallel to the ground,
* with coordinates {X, Y, Z}.
*/
public static class vector {
public vector(double a, double b, double c) {
x = a;
y = b;
z = c;
}

public vector() {

}

public void show(String msg) {
print(msg+" (");
print(x); print(", ");
print(y); print(", ");
print(z); println(")");
}

public double x, y, z;
}

/**
* Newton's method
*/
static double xsqrt(double x) {
if (!(x > 0))
return (x == 0) ? x : Double.NaN;
double x0=0.1*x;
double x1=x0-(x0*x0-x)/(2*x0);
while(abs(x1/x0-1)>0.001) {
x0=x1;
x1=x0-(x0*x0-x)/(2*x0);
}
return x1;
}

static void vector_cross(final vector a, final vector b, vector out)
{
out.x = a.y * b.z - a.z * b.y;
out.y = a.z * b.x - a.x * b.z;
out.z = a.x * b.y - a.y * b.x;
}

static double vector_dot(final vector a, final vector b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}

static void vector_normalize(vector a)
{
double dot = vector_dot(a, a);
double mag = sqrt(dot);
//print("dot="); println(dot);
//print("mag="); println(mag);
a.x /= mag;
a.y /= mag;
a.z /= mag;
}

static vector p = new vector(0, -1, 0);

/*
* m_max and m_min are calibration values for the maximum and minimum
* measurements recorded on each magnetic axis, which can vary for each
* LSM303DLM. You should replace the values below with max and min readings from
* your particular device.
*
* To obtain the max and min values, you can use this program's
* calibration mode, which is enabled by pressing one of the pushbuttons. While
* calibration mode is active, point each of the axes of the LSM303DLM toward
* and away from the earth's North Magnetic Pole. Due to space constraints on an
* 8x2 LCD, only one axis is displayed at a time; each button selects an axis to
* display (top = X, middle = Y, bottom = Z), and pressing any button a second
* time exits calibration mode and returns to normal operation.
*/
static vector m_max = new vector(527, 419, 417);
static vector m_min = new vector(-472, -584, -562);

static String ribbon = " N NE E SE S SW W NW N "; // 42

static enum calibration_mode {CAL_NONE, CAL_X, CAL_Y, CAL_Z};

static void i2c_start() {
TWCR = (byte)((1 << TWINT) | (1 << TWSTA) | (1 << TWEN)); // send start condition
while (((TWCR & (1 << TWINT))==0));
}

static void i2c_write_byte(int b) {
TWDR = (byte)(b);
TWCR = (byte)((1 << TWINT) | (1 << TWEN)); // start address transmission
while (((TWCR & (1 << TWINT))==0));
}

static int i2c_read_byte() {
TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN); // start data reception, transmit ACK
while (((TWCR & (1 << TWINT))==0));
return TWDR&0xff;
}

static int i2c_read_last_byte() {
TWCR = (byte)((1 << TWINT) | (1 << TWEN)); // start data reception
while (((TWCR & (1 << TWINT))==0));
return TWDR&0xff;
}

static void i2c_stop() {
TWCR = (byte)((1 << TWINT) | (1 << TWSTO) | (1 << TWEN)); // send stop condition
}

// Returns a set of acceleration and raw magnetic readings from the cmp01a.
static void read_data_raw(vector a, vector m)
{
// read accelerometer values
i2c_start();
i2c_write_byte(0x30); // write acc
i2c_write_byte(0xa8); // OUT_X_L_A, MSB set to enable auto-increment
i2c_start(); // repeated start
i2c_write_byte(0x31); // read acc
/*unsigned*/ int axl = i2c_read_byte();
/*unsigned*/ int axh = i2c_read_byte();
/*unsigned*/ int ayl = i2c_read_byte();
/*unsigned*/ int ayh = i2c_read_byte();
/*unsigned*/ int azl = i2c_read_byte();
/*unsigned*/ int azh = i2c_read_last_byte();
i2c_stop();

// read magnetometer values
i2c_start();
i2c_write_byte(0x3C); // write mag
i2c_write_byte(0x03); // OUTXH_M
i2c_start(); // repeated start
i2c_write_byte(0x3D); // read mag
/*unsigned*/ int mxh = i2c_read_byte();
/*unsigned*/ int mxl = i2c_read_byte();
/*unsigned*/ int mzh = i2c_read_byte();
/*unsigned*/ int mzl = i2c_read_byte();
/*unsigned*/ int myh = i2c_read_byte();
/*unsigned*/ int myl = i2c_read_last_byte();
i2c_stop();

a.x = axh << 8 | axl;
a.y = ayh << 8 | ayl;
a.z = azh << 8 | azl;
m.x = mxh << 8 | mxl;
m.y = myh << 8 | myl;
m.z = mzh << 8 | mzl;
}

// Returns a set of acceleration and adjusted magnetic readings from the cmp01a.
static void read_data(vector a, vector m)
{
read_data_raw(a, m);

// shift and scale
m.x = ((m.x - m_min.x) / (m_max.x - m_min.x) * 2 - 1.0);
m.y = ((m.y - m_min.y) / (m_max.y - m_min.y) * 2 - 1.0);
m.z = ((m.z - m_min.z) / (m_max.z - m_min.z) * 2 - 1.0);
}

// Returns a heading (in degrees) given an acceleration vector a due to gravity, a magnetic vector m, and a facing vector p.
static int get_heading(final vector a, final vector m, final vector p)
{
vector E = new vector();
vector N = new vector();

// cross magnetic vector (magnetic north + inclination) with "down" (acceleration vector) to produce "east"
vector_cross(m, a, E);
vector_normalize(E);

// cross "down" with "east" to produce "north" (parallel to the ground)
vector_cross(a, E, N);
vector_normalize(N);

// compute heading
int heading = (int) Math.round(atan2(vector_dot(E, p), vector_dot(N, p)) * 180 / PI);
if (heading < 0)
heading += 360;
return heading;
}

/**
* @param args
*/
public static void main(String[] args)
{
DDRC = 0; // all inputs
PORTC = (byte)((1 << PORTC4) | (1 << PORTC5)); // enable pull-ups on SDA and SCL, respectively

TWSR = 0; // clear bit-rate prescale bits
TWBR = 17; // produces an SCL frequency of 400 kHz with a 20 MHz CPU clock speed

//clear();
//enable accelerometer
i2c_start();
i2c_write_byte(0x30); // write acc
i2c_write_byte(0x20); // CTRL_REG1_A
i2c_write_byte(0x27); // normal power mode, 50 Hz data rate, all axes enabled
i2c_stop();

//enable magnetometer
i2c_start();
i2c_write_byte(0x3C); // write mag
i2c_write_byte(0x02); // MR_REG_M
i2c_write_byte(0x00); // continuous conversion mode
i2c_stop();

vector a=new vector(), m=new vector();
//char ribbon_segment[] = new char[8];
/*unsigned*/ char button;
calibration_mode mode = calibration_mode.CAL_NONE;
vector cal_m_max = new vector();
vector cal_m_min = new vector();

println(ribbon);
while(true)
{
// see if a button was pressed to enable calibration mode
// each button displays max and min measurements for one axis:
// top = X, middle = Y, bottom = Z
// if any button is pressed a second time, return to normal mode
//while (Serial.available()==0);
if (Serial.available()>0) {
button = (char)Serial.read();
//println(":"+button);
} else {
button = ' ';
//println("-");
}

if (button=='x')
{
if (mode != calibration_mode.CAL_X)
mode = calibration_mode.CAL_X;
else
mode = calibration_mode.CAL_NONE;
}
else if (button=='y')
{
if (mode != calibration_mode.CAL_Y)
mode = calibration_mode.CAL_Y;
else
mode = calibration_mode.CAL_NONE;
}
else if (button=='z')
{
if (mode != calibration_mode.CAL_Z)
mode = calibration_mode.CAL_Z;
else
mode = calibration_mode.CAL_NONE;
}


if (mode == calibration_mode.CAL_NONE) // normal mode - display heading and compass ribbon
{
vector a_avg = new vector(), m_avg = new vector();

// take 5 acceleration and magnetic readings and average them
for(int i = 0; i < 5; i++)
{
read_data(a, m);

a_avg.x += a.x;
a_avg.y += a.y;
a_avg.z += a.z;
m_avg.x += m.x;
m_avg.y += m.y;
m_avg.z += m.z;
}

a_avg.x /= 5;
a_avg.y /= 5;
a_avg.z /= 5;
m_avg.x /= 5;
m_avg.y /= 5;
m_avg.z /= 5;

int heading = get_heading(a_avg, m_avg, p);

// select the portion of the ribbon to display
// strlcpy(ribbon_segment, &ribbon[(heading + 5) / 10], 8);

//clear();
//print("heading: "); println(heading);
heading=(heading + 5) / 10;
for (int i = 0; i < 42; i++) {
print(' ');
}
print('\r');
for (int i = 0; i < heading; i++) {
print(' ');
}
print('V'); // center indicator
print((char)8);


// lcd_goto_xy(4, 0);
// print('v'); // center indicator
// lcd_goto_xy(1, 1);
// print(ribbon_segment); // ribbon segment
}
else // calibration mode - record and display max/min measurements
{
read_data_raw(a, m);
if (m.x < cal_m_min.x) cal_m_min.x = m.x;
if (m.x > cal_m_max.x) cal_m_max.x = m.x;
if (m.y < cal_m_min.y) cal_m_min.y = m.y;
if (m.y > cal_m_max.y) cal_m_max.y = m.y;
if (m.z < cal_m_min.z) cal_m_min.z = m.z;
if (m.z > cal_m_max.z) cal_m_max.z = m.z;

//clear();

switch (mode)
{
case CAL_X:
print("Xmax: ");
print(cal_m_max.x);
print(" min: ");
println(cal_m_min.x);
break;
case CAL_Y:
print("Ymax: ");
print(cal_m_max.y);
print(" min: ");
println(cal_m_min.y);
break;
default:
print("Zmax: ");
print(cal_m_max.z);
print(" min: ");
println(cal_m_min.z);
break;
}
}

delay(100);
}
}
}


3) Mit welcher IDE arbeitest du?

janvp
28.02.2013, 16:27
Hallo haikuvm,

ich benutze Eclipse, aber wenn ich wie auf deiner Seite beschrieben vorgehe, bekommen ich immer die Ausgabe 'make not found'. Deswegen gebe ich die Befehle zum Ausführen immer noch im Terminal ein. Das funktioniert auch.

'haiku.avr.lib.arduino.save.TWI' befindet sich im bootstrap.jar von Version 1.0.1.

Zwei Sachen sind mir nochnicht ganz klar geworden:
Gibt es die Möglichkeit auf Interrups zu reagieren?
Wie schreibt man native code für haikuvm?

haikuvm
28.02.2013, 21:10
Hallo janvp,

uuups, in einer jar-Datei hatte es sich versteckt. Da bin ich nicht drauf gekommen! Danke!

1) 'make not found'
Tja, da bin ich ratlos. Irgendwie hat der Mac für die Commandozeile eine andere Umgebung als für Eclipse. Wenn Du da was raus kriegst, lass es mich wissen.

2) Ja, die Zusammenarbeit mit Interrupts geht. Und das geht nur mit native C code. Das habe ich mit mlade hier diskutiert. Ist da noch was unklar? Kann vielleicht mlade noch was dazu sagen, würde mich freuen?!
Darüber hinaus habe ich dazu schon was im Tutorial Bereich auf der neuen HaikuVM WEB page beschrieben. Die gibt's schon mal als Preview:
http://haiku-vm.sourceforge.net/preview.html
Vorsicht: die darin erwähnte Version 1.0.2 steht (noch) nicht zum Download bereit!

3) Willst Du den TWI Slave mit C code realisieren? Hat Dir für eine reine JAVA Lösung die Compass Klasse nicht genug geholfen?

janvp
12.03.2013, 17:22
Hallo haikuvm,

Ich habe jetzt die Wire-Library von Arduino (https://github.com/arduino/Arduino/tree/master/libraries/Wire) genommen und fast komplett in Java nachgebaut. Lediglich einen native Methode brauch ich noch, um auf den Interrupt TWI_vect zu reagieren. Denn wenn die Interrupt Routine SIGNAL(TWI_vect) (im c Code) aufgerufen wird, wird ein nur Integer auf 1 gesetzt. Diesen Integer frage ich im Java Programm in einem separaten Thread permanent ab. Wenn der Integer auf 1 springt, wird die java Methode SIGNAL() ausgeführt. Diese hat den selben Inhalt, wie die Routine aus twi.c.

Leider funktioniert einiges irgendwie nicht:
Wenn ich den Arduino als Slave und den NXT als Master betreibe, zeigt mir der NXT an, dass ein BUS Error vorliegt.
Wenn der Master trotzdem versucht etwas zu senden, wird auch onReceive(int numBytes) beim Slave aufgerufen, aber numBytes ist immer 0. D. h. es werden keine Daten empfangen.
Wenn der Master versucht etwas zu empfangen, wird onRequest() aufgerufen, aber der Master empfängt nichts.

Leider konnte ich den Arduino nicht als Master betreiben, weil ich keinen Slave besitze.

Weißt du woran es liegen könnte, dass es zu einem BUS Error kommt?

Hier sind meine Dateien (http://dl.dropbox.com/u/54743553/twi.zip), falls du mal einen Blick darauf werfen willst.

LG jan

haikuvm
14.03.2013, 22:42
Hallo Janvp,

puuuh, da hast Du zu Beginn gleich ein gewaltiges Projekt eröffnet. Die gesamte Wire-Library von Arduino, fast komplett ...!
Würde mich freuen wenn das funktioniert!!
Da habe ich aber auch eine gewaltige Menge von Fragen:
1) Funktioniert denn die reine C Lösung der Wire-Library von Arduino? D.h.:
1a) Hast Du das schon in der Arduino IDE probiert?
1b) Und gegen den NXT laufen sehen?

2) Welches Memorymodel von HaikuVM nutzt Du 16/32 oder 32/64? (Hast Du Dich da eingelesen auf der HaikuVM Page?)
Denn ich sehe da in Deinem Code: int TWI_FREQ = 100000;
(Das passt nicht in einen int16 falls 16/32 !!!)

3) Hast Du Erfahrung mit Interruptprogrammierung?
Denn Erfahrene schreiben eigentlich: volatile uint8_t newSignal = 0;

4) Geht es nicht auch ganz ohne Interrupt (denn Threads machen's möglich) also ohne setzen von TWIE (und damit auch ohne JNI Code)? Einfach das Bit in der run()-Schleife direkt testen.


if ( (TWCR & _BV(TWINT)) != 0 ) { SIGNAL(); };

(Hierbei nicht vergessen TWINT wieder zurück zu setzen.)

5) Kosmetik: Ich würde twi nicht von Thread ableiten sondern so schreiben:


public class twi implements Runnable, SlaveRxEvent, SlaveTxEvent{
...
Thread th = new Thread(this);
...
}

6) Ganz wichtig: Welche Version von HaikuVM nutzt Du?

janvp
27.03.2013, 12:58
Hallo Haikuvm,

Zu 2 und 3) Ich hab seit längerer Zeit nicht mehr in C programmiert. Aber nach diesem Projekt sollte wieder alles da sein :) Natürlich muss es ein long sein.
Zu 4) Nein es geht anscheinend nicht. Ich führe if(TWCR & _BV(TWINT)) != 0 ) in einem separaten Thread aus, aber es ist niemals "true". Kann es sein, dass es nicht oft genug aufgerufen wird?
Zu 6) 1.0.2

Zu 1) Mit der Wire-Library und der Arduino-Idee hab ich eine Verbindung zum NXT aufbauen können.
Wenn ich die Wire-Library in C anspreche, bekomme ich auch einen Bus-Error.. ](*,)
Deshalb hab ich noch einmal ganz vorne angefangen und meine eigene Interrupt-Routine in C geschrieben. Diese funktioniert nun auch einwandfrei (auch die Slave-Funktionen). Nun werde ich die Einzelteile langsam auf Java übertragen und gucken ob es diesmal funktioniert.

Edit:

Gibt es die Möglichkeit Java Methoden aus dem C Code aufzurufen oder muss ich immer eine Variable überprüfen und dann die Methode aufrufen?
Mit "@NativeCVariable8" kann man doch aus dem Java Code ohne JNI auf C Variablen zugreifen, oder?

haikuvm
27.03.2013, 21:48
Hallo janvp,

zu 1) Hab' ich mir fast gedacht, dass die - sonst sehr hübsche - Wire-Library ein Problem hat mit dem NXT.
zu 4) Das wundert mich allerdings sehr!
4.1) Kann es sein, dass Du, auch bei dieser Lösung TWI Interrupt enabled hast? Dann nämlich wird das TWINT gleich vom Interrupt wieder weggefressen.
4.2) Klappt das nie? Oder kommt es beim aller ersten Mal doch einmal zum Auftruf von SIGNAL()?

Nein, aus C heraus JAVA Methoden aufrufen geht nicht (ohne weiteres).
Du hast schon Recht, mit @NativeCVariable8 kann man direkt auf C Variablen zugreifen. Z. Zt. können das aber nur die sein die von AVR vordefiniert sind und nix eigenes. (Also z.B. Dein 'newSignal'.) Mich hat das auch schon gestört und ich werde es mit der nächsten Version ermöglichen.

Leider habe ich nur einen Arduino. Sonst könnte ich beim TWI Slave mit testen.

janvp
30.03.2013, 19:17
Ich habe jetzt ein kleines Testprogramm geschrieben.
Wenn ich es ausführe, wird leider niemals "it works" ausgegeben..

import static haiku.avr.ATmega328p.*;
import haiku.avr.lib.arduino.WProgram.Serial;

public class SoftTWI {

/**
* @param args
*/
public static void main(String[] args) {

Serial.begin(115200);

Serial.print("init...");

// Interne Pull-Ups aktivieren
DDRB = 0x00;
PORTB = 0xff;
DDRC = ((0 << DDC0) | (0 << DDC1) | (0 << DDC2) | (0 << DDC3) | (1 << DDC4) | (1 << DDC5));
PORTC = ((1 << DDC0) | (1 << DDC1) | (1 << DDC2) | (1 << DDC3) | (0 << DDC4) | (0 << DDC5));
DDRD = 0x00;
PORTD = 0xff;

// Adressregister (TWAR) auf Adresse setzen. Achtung: 1x links schieben, da Bit 0 für Global call verwendet wird
TWAR = (0x43 << 1);
//TWAR |= (1 << 0);
// Kein Interrupt erlauben und ACK auf Adresse aktivieren
//0<<twie kein Interrupt!
TWCR = (0 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (0 << TWIE);

Serial.println("finished");

while(true){
if( (TWCR & (1<<TWINT)) != 0 ){

Serial.println("it works!");
// ACK und reset TWINT
TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (0 << TWIE);
}
}
}

}
Wenn ich das ganze in C schreibe und den Interrupt aktiviere, wird die Interrupt-Routine aufgerufen. Die Initialisierung sollte also stimmen.

Hab ich irgendwas übersehen oder müsste eigentlich alles richtig sein?

Ich hab leider auch nur den NXT als Master. Bald werd ich mir aber einen zweiten AVR anschaffen. Vielleicht liegt es echt am NXT.

haikuvm
31.03.2013, 23:12
Hallo Janvp,

ich bin mit den Details von TWI echt überfragt. (Vielleicht können hier Andere besser helfen.) Aber, Du setzt in Deinem Beispiel zwei mal das TWCR Register. So weit so gut. Aber sollte es nicht beide male "TWCR = (1 << TWINT) | ..." heißen? Also:


TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (0 << TWIE);

janvp
05.04.2013, 12:57
Zuerst einmal:
Eigentlich müsste die erste Zuweisung richtig sein. Denn wenn man stattdessen "TWCR = (1 << TWINT)..." schreibt ist die Bedingung immer "true", auch wenn ich nichtmal eine Kabelverbindung habe. Die zweite Zuweisung wird ja leider nie aufgerufen, aber ich habe im Wissensbereich (oder im Mircrcontroller-Forum?) gelesen, dass TWCR zurück gesetzt wird, indem TWINT durch "TWCR = (1<<TWINT).." gelöscht wird. Ich habe das aber auch nicht so ganz verstanden..

Jetzt etwas neues:
Meine TWI-Slave-Lib funktioniert jetzt endlich. Sie basiert aber auf der Interrupt-Routine. Ich habe erst versucht, dass eine Methode im Java Programm aufgerufen wird, wenn etwas passiert. Dies scheint aber nicht zu funktionieren.

Wenn die Interrupt-Routine nicht auf das Java-Programm warten muss, gibt es keinen Bus-Error mehr und alles funktioniert.

So funktioniert es nun:
Empfang von Daten:
Jetzt werden alle Daten im C-Programm empfangen und in einen Buffer geschrieben, welcher dann an das Java-Programm weiter gegeben wird. Die Interrupt-Routine wird nicht unterbrochen, da dass Java-Programm die Abfrage des Buffers übernimmt.
Senden von Daten:
Wenn ein Request eingeht, wird eine Java Methode ausgelöst. Gleichzeitig geht's weiter: Wenn der txBuffer leer ist, wird ein bestimmtes Zeichen (-1) verschickt, woran der Master erkennen soll, dass der Slave die Daten noch nicht parat hat. Der Master muss solange den Slave abfragen, bis dieser was anderes als -1 schickt.
Wenn das Java Programm dann irgendwann mal den Buffer gefüllt hat wird dieser verschickt.
Der nächste Request kann ausgelöst werden.

Die Slave-Lib funktioniert jetzt wunderbar. Der Quellcode ist aber überhaupt nicht schön. Das muss noch behoben werden. Auch möchte ich noch ein Funktions-Diagramm machen, welches zeigt, wie der Master handeln sollte, damit alles funktioniert.


Mir ist da grad etwas eingefallen:
Früher hab ich ja im Interrupt eine Variable auf 1 gesetzt und dann mit einer Schleife solange gewartet, bis diese 0 ist. Das Java-Programm sollte sie nämlich abfragen und dann auf 0 ändern. Das ganze kann doch gar nicht funktionieren: Denn wenn der Interrupt läuft, kann ja gleichzeitig kein anderer Code ausgeführt werden. Der Interrupt hebelt somit das Java-Thread-System aus.


Jetzt hab ich mein erstes Teil-Ziel erreicht :) Ich würde die Library gerne Hochladen, aber mein Internet gibt zurzeit den Geist auf (Danke Vodafone!!!). Vielleicht wird es heute Abend was.
Edit: Hier ist sie: http://dl.dropbox.com/u/54743553/Archiv.zip
Eine Frage bleibt aber noch: Muss ich, damit ich die "Serial.println.." am PC auslesen kann, die Arduino IDE benutzen, oder gibt es dafür ein anderes Programm?

Vielen Dank :)

haikuvm
07.04.2013, 08:24
Suuuper, dass es funktioniert. Du bist auch ganz schön hartnäckig!! Das zahlt sich wohl aus.

zu) "Eigentlich müsste die erste Zuweisung richtig sein. ..."
Mich würde interessieren: Ist das jetzt vom grünen Tisch? Oder hast Du meinen Vorschlag von Post #44 geprüft und - in der Praxis - für untauglich/falsch befunden. (Ich meine natürlich mit bestehender(!) Kabelverbindung.) Denn ich hatte Dir in Post #36 ein praxiserprobtes Programm vorgestellt, das genau so (wie in Post #44) funktioniert, allerdings als (verkabelter) Master.

zu) "Früher hab ich ja im Interrupt eine Variable auf 1 ..."
Tja, das meinte ich mit meiner Bemerkung 4.1 (siehe Post #42).

zu) ... "Serial.println.." am PC auslesen ...
Für Windows gibt es Terminalprogramme:
a) Hyper Terminal
b) putty.exe
c) andere Terminalprogramme
Für UNIX gibt es natürlich auch Terminalprogramme, weiß aber nicht genau was gut funktioniert. Da brauche ich Deine Hilfe.

Benjaminn
09.06.2013, 06:45
hi,

Java ist ja nun nicht für die direkte Kommunikation mit der Hardware gedacht. Also war mein Gedanke, die Interrupt-Routinen in C zu schreiben, und diese dann per JNI in meine Java-Anwendung einzubinden. In C (und ASM) hab ich mit dem Asuro auch schon einige Erfahrungen sammeln können, auch die Bearbeitung von Interrupts. Mit Java und insbesondere mit dem JNI habe ich aber keine Erfahrungen.

Versucht habe ich, die Interrupts irgendwie ohne JNI einzubinden, indem ich einfach per setMemory8 GICR, MCUCR und SREG konfiguriert und dann eine ISR (wie ich naiv glaubte) namens SIGNAL_SIG_INTERRUPT1 zu schreiben. IRGENDWAS tut der Robot auch bei dem Interrupt, ich bin mir allerdings ziemlich sicher, dass unmittelbar ein RESET folgt.


-------------------------------
Awavo COM Port Monitor (http://www.awavo.com/com-port-monitor/)

haikuvm
18.06.2013, 21:13
Hallo Benjaminn,

eigentlich brauchst Du setMemory8 nicht, die Verwendung ist unbequem. Denn Du kannst die Variablen GICR, MCUCR und SREG auch direkt in JAVA/HaikuVM ansprechen. Wie sieht denn Dein Versuch von SIGNAL_SIG_INTERRUPT1 aus? Zeig doch bitte mal Deinen Quellcode.

connochaetes
16.11.2014, 07:46
Hallo.

Ich interessiere mich dafür, einen Arduino Mega 2560 mit Java zu programmieren (favorisiertes OS: Debian GNU/LInux). Dazu habe ichHaikuVM heruntergeladen und versuche nun gemäß dem Absatz "Arduino IDE" im Tutorial von "http://haiku-vm.sourceforge.net" vorzugehen. Das ist bisher leider nicht erfolgreich. Das Problem kann vielfältig gelagert sein:

- Bibliotheken wurden nicht eingebunden. (Das kann in meinem Fall auch am falschen Setzen des Java-Classpath liegen.)

- Konfiguration und vorhandene Umgebung passen nicht zusammen.

Da ich in mancherlei Hinsicht Neuling in diesem Feld bin, bitte ich um Nachsicht. Details/Fehlermeldungen reiche ich selbstverständlich gern nach; allerdings ist mir momentan noch nicht klar, wo der erste Fehler aufgetreten ist. Über Hilfe würde ich mich sehr freuen.

Gruß, connochaetes.