หน้าเว็บ

วันอาทิตย์ที่ 16 ตุลาคม พ.ศ. 2554

วิธีแก้บั๊ก TinyOS two source files specified (PLATFORM_MICAZ and BOARD_MICASB) make: *** [exe0] Error 1

ปัญหาเกิดจากผมทำการอัพเดท Ubuntu 11.04 ไปเป็น 11.10 พออัพเดทแล้วลองคอมไพล์โปรแกรมปรากฏว่าคอมไพล์ไม่ผ่านโดยขึ้น error ประมาณนี้ครับ

two source files specified (PLATFORM_MICAZ and BOARD_MICASB)
make: *** [sim-exe] Error 1


ซึ่งตัว PLATFORM_ กับ BOARD_ อาจเป็นอื่นๆได้ เช่น PLATFORM_IRIS เป็นต้น

ปัญหานี้เกิดจากการที่ gcc ถูกอัพเกรดเป็นเวอร์ชัน 4.6 ซึ่งจะถูกเรียกใช้ในขั้นตอนของการคอมไพล์ TinyOS โปรแกรม

ปัญหาคือ gcc 4.6 จะเพิ่ม space 1 ตัว ไประหว่าง option -D กับ argument ทำให้ปกติแล้วในของเก่า gcc จะสร้าง -DPLATFORM_MICAZ กับ -DBOARD_MICASB ออกมา เพื่อให้ nescc (nesC compiler) เอาไปใช้งานต่อ แต่ของใหม่จะสร้าง -D PLATFORM_MICAZ กับ -D BOARD_MICASB ออกมาแทน ซึ่งทำให้ nescc คอมไพล์ไม่ได้และเกิด error ดังข้างบน

วิธีแก้คือ
1) ดาวน์โหลด nescc ตัวใหม่มา (ของผมที่ใหม่สุดคือ 1.3.2) http://sourceforge.net/projects/nescc/files/nescc/v1.3.2/nesc-1.3.2.tar.gz/download?_test=goal

2) แตกไฟล์ออกมา แล้วไปแก้ source code ที่ไฟล์ nesc-1.3.2/src/nesc-compile

3) หาบรรทัด

($i, $idir) = &extractarg($i);
push @nesc_args, "-I$idir";
}
elsif (/^-o/) {
($i, $objtarget) = &extractarg($i);
}


แก้โดยเพิ่มอีกเงื่อนไขไปเป็น

($i, $idir) = &extractarg($i);
push @nesc_args, "-I$idir";
}
elsif (/^-D/) {
($i, $ddef) = &extractarg($i);
pop @nesc_args;
push @nesc_args, "-D$ddef";
}
elsif (/^-o/) {
($i, $objtarget) = &extractarg($i);
}


4) เสร็จแล้วให้ออกมาที่โฟลเดอร์หลัก nesc-1.3.2 ทำการคอมไพล์โค้ด

./configure
make
sudo make install


5) ลองทดสอบดูว่า nescc ตัวใหม่ติดตั้งแล้วหรือยังโดยสั่ง

ncc --version

ผลลัพธ์ควรจะแจ้งเวอร์ชันของ nescc ออกมาเป็น 1.3.2

ถ้ายังไม่เป็นให้เรา move binary ใหม่ไปแทนเอง

sudo cp /usr/bin/nescc /usr/bin/nescc.old
sudo cp /path/to/nesc-1.3.2/tools/nescc /usr/bin/nescc


6) เมื่อเสร็จแล้วก็ลองสั่งคอมไพล์ TinyOS โปรแกรมใหม่อีกรอบ เช่น

make micaz sim

ก็น่าจะคอมไพล์ผ่านเรียบร้อย

ระบบที่ทดสอบ
OS: Ubuntu 11.10
TinyOS: 2.1.1
ncc: 1.2.4
gcc: 4.6.1
nescc: 1.3.2

อ้างอิง
http://sourceforge.net/tracker/index.php?func=detail&aid=3153727&group_id=56288&atid=480036

วันอังคารที่ 29 กรกฎาคม พ.ศ. 2551

การสร้าง Java class เพื่อใช้กับประเภทข้อมูลของ TinyOS

ในการเขียนโปรแกรมภาษา nesC นั้นส่วนใหญ่จะมีการสร้างประเภทตัวแปรไว้สำหรับจัดการกับ message ที่ส่งในระบบ หรือมีการประกาศค่าคงที่ต่างๆที่จะนำไปใช้ได้ โดยมักจะประกาศในไฟล์ .h หรือ header ไฟล์ เช่นเดียวกับภาษา C
แต่ถ้าเราจะเขียนโปรแกรมภาษาจาวาเพื่อทำการติดต่อข้อมูลกับระบบ sensor network ที่เขียนด้วยภาษา nesC นั้น เราก็จะต้องมีการสร้าง class บนภาษา Java เพื่อมารองรับ message นั้นๆ
ซึ่งใน TinyOS นั้นจะมี tool ที่ช่วยให้เราทำงานนี้ได้สบายขึ้น คือ MIG และ NCG

MIG
- Message Interface Generator
ตัวนี้จะเป็นตัวที่ใช้สร้าง class Java เพื่อจะรองรับ message ที่เราสร้างขึ้น

NCG- NesC Constant Generator
ตัวนี้จะทำหน้าที่ดึงค่า constant ต่างๆที่เราประกาศไว้ออกมาใส่ใน class Java

ก่อนอื่นผมขอสมมติว่า ผมทำ nesC app ไว้ที่ /opt/tinyos-1.x/apps/MyApp
โดยใน MyApp มีโฟลเดอร์ชื่่อ types ที่ใช้เก็บ header file ที่ใช้ประกาศประเภทข้อมูล message เอาไว้
และใน types มีไฟล์ชื่อ MyMsg.h ซึ่งภายในไฟล์มีการประกาศค่าคงที่ AM_TYPE และ message ไว้ คือ
// ไฟล์ MyMsg.h
enum AM_TYPE
{
AM_PINGMSG = 20,
AM_PINGREPLYMSG = 21,
};

typedef struct PingMsg
{
uint16_t hostid;
uint16_t seqno;
} PingMsg;

typedef struct PingReplyMsg
{
uint16_t hostid;
uint16_t seqno;
uint16_t origin;
uint16_t parent;
uint16_t depth;
} PingReplyMsg;

คราวนี้เราจะมาสร้าง class java โดยใช้ structure จากค่าเหล่านี้กัน

สมมติว่าเราจะสร้าง class java เอาไว้ใน MyApp/java ให้ทำการสร้างไฟล์ชื่อ Makefile เอาไว้ใน MyApp/java โดยมีเนื้อหาดังนี้ (สำหรับใครที่อ่านแล้วงงๆ ลองศึกษาเรื่องมีวิธีการทำ Makefile http://frank.mtsu.edu/~csdept/FacilitiesAndResources/make.htm)
// ไฟล์ Makefile
TOS = $(shell ncc -print-tosdir)
APPDIR = $(TOS)/../apps/MyApp

MIG = mig java
NCG = ncg java

MSGS = PingMsg.java ReplyPingMsg.java
CONST = PingConst.java

INITIAL_TARGETS = $(MSGS) $(CONST)

OTHER_CLEAN = cleanmig

ROOT = ../../../tools/java
include $(ROOT)/Makefile.include

PingMsg.java:
$(MIG) -java-classname=PingMsg $(APPDIR)/types/MyMsg.h PingMsg -o $@
$(JAVAC) $@

PingReplyMsg.java:
$(MIG) -java-classname=PingReplyMsg $(APPDIR)/types/MyMsg.h PingReplyMsg -o $@
$(JAVAC) $@

PingConst.java:
$(NCG) -java-classname=PingConst $(APPDIR)/types/MyMsg.h AM_PINGMSG AM_PINGREPLYMSG -o $@
$(JAVAC) $@

cleanmig:
rm -f $(MSGS) $(CONST)

โดยมีส่วนที่สำคัญคือ
MIG = mig java
NCG = ncg java

จะเป็นการสร้างค่าเพื่อใช้เรียกคำสั่ง mig และ ncg โดยให้สร้างเป็น class ประเภท java
MSGS = PingMsg.java ReplyPingMsg.java
CONST = PingConst.java

เป็นการระบุว่าเราจะสร้าง class ชื่ออะไรออกมาบ้าง ในที่นี่คือ PingMsg.java, ReplyPingMsg.java และ PingConst.java เพื่อเป็นประโยชน์เวลาสั่ง clean จะได้ตามลบได้หมดทุกตัว นั่นคือมันจะทำการ clean ทุกไฟล์ที่มีการประกาศไว้ใน MSGS และ CONST (ดูในโค้ด makefile ส่วนที่เป็น cleanmig ด้านล่างสุด) เพราะเวลาเราสั่ง make clean มันจะดูที่ค่าคงที่ OTHER_CLEAN ที่ประกาศไว้ ซึ่งในที่นี้เราให้เป็น cleanmig มันก็จะไปทำ cleanmig ซึ่งลบทุกอย่างที่ประกาศไว้ใน MSGS และ CONST นั่นเอง

include $(ROOT)/Makefile.include
ใช้ในการระบุ makefile ที่จะใช้ในการ compile java โดยไฟล์นี้จะชี้ไปที่ /opt/tinyos-1.x/tools/java/Makefile.include

PingMsg.java:
$(MIG) -java-classname=PingMsg $(APPDIR)/types/MyMsg.h PingMsg -o $@
$(JAVAC) $@

ทำการสร้างไฟล์ชื่อ PingMsg.java โดย
-java-classname เป็นการระบุชื่อไฟล์ java
$(APPDIR)/types/MyMsg.h เป็นการระบุ nesC header ไฟล์ที่เราต้องการจะดึงค่าออกมา
PingMsg เป็นชื่อ struct ที่เราประกาศไว้ใน nesC ไฟล์และจะเอามาทำเป็น java class
-o $@ สร้าง output ชื่อว่า PingMsg.java (@ คือชื่อที่เขียนไว้ที่บรรทัด PingMsg.java:)
$(JAVAC) $@ ทำการคอมไพล์ (ข้อควรระวัง เว้นวรรคด้านหน้านั้น ให้ใช้ tab(\t) หนึ่งครั้ง ห้ามเป็นเครื่องหมาย space ต่อกันหลายครั้ง)

ส่วนกรณีของ NCG นั้นก็จะคล้ายกัน แต่เปลียนจาก MIG เป็น NCG และสามารถระบุค่าคงที่ได้หลายตัวว่าจะเอาค่าอะไรออกมาบ้าง

พอสุดท้ายเราก็จะได้ PingMsg.java PingMsg.class PingReplyMsg.java PingReplyMsg.class PingConst.java และ PingConst.class เพื่อเอาไปใช้ในโปรแกรม java ของเราได้

ระบบที่ใช้ทดสอบ
TinyOS: 1.1.15 on cygwin