esb mote extends general msp mote
This commit is contained in:
parent
09345f05ae
commit
c18afffd36
5 changed files with 1666 additions and 0 deletions
115
tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java
Normal file
115
tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2007, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ESBMote.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import org.apache.log4j.Logger;
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.interfaces.*;
|
||||
import se.sics.cooja.mspmote.interfaces.*;
|
||||
import se.sics.mspsim.platform.esb.ESBNode;
|
||||
|
||||
/**
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public class ESBMote extends MspMote {
|
||||
private static Logger logger = Logger.getLogger(ESBMote.class);
|
||||
|
||||
public ESBNode esbNode = null;
|
||||
|
||||
public ESBMote() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ESBMote(MoteType moteType, Simulation sim) {
|
||||
super((ESBMoteType) moteType, sim);
|
||||
}
|
||||
|
||||
protected boolean initEmulator(File fileELF) {
|
||||
try {
|
||||
createCPUAndMemory(fileELF);
|
||||
|
||||
esbNode = new ESBNode(getCPU());
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.fatal("Error when creating ESB mote: " + e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected MoteInterfaceHandler createMoteInterfaceHandler() {
|
||||
MoteInterfaceHandler moteInterfaceHandler = new MoteInterfaceHandler();
|
||||
// Add position interface
|
||||
Position motePosition = new Position(this);
|
||||
Random random = new Random();
|
||||
motePosition.setCoordinates(random.nextDouble()*100, random.nextDouble()*100, random.nextDouble()*100);
|
||||
moteInterfaceHandler.addActiveInterface(motePosition);
|
||||
|
||||
// Add log interface
|
||||
Log moteLog = new ESBLog(this);
|
||||
moteInterfaceHandler.addActiveInterface(moteLog);
|
||||
|
||||
// Add time interface
|
||||
Clock moteClock = new MspClock(this);
|
||||
moteInterfaceHandler.addActiveInterface(moteClock);
|
||||
|
||||
// Add led interface
|
||||
LED moteLed = new ESBLED(this);
|
||||
moteInterfaceHandler.addActiveInterface(moteLed);
|
||||
|
||||
// Add button interface
|
||||
Button moteButton = new ESBButton(this);
|
||||
moteInterfaceHandler.addActiveInterface(moteButton);
|
||||
|
||||
// Add ID interface
|
||||
MoteID moteID = new MspMoteID(this);
|
||||
moteInterfaceHandler.addActiveInterface(moteID);
|
||||
|
||||
// Add radio interface
|
||||
myRadio = new TR1001Radio(this);
|
||||
moteInterfaceHandler.addActiveInterface(myRadio);
|
||||
|
||||
return moteInterfaceHandler;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (getInterfaces().getMoteID() != null) {
|
||||
return "ESB Mote, ID=" + getInterfaces().getMoteID().getMoteID();
|
||||
} else {
|
||||
return "ESB Mote, ID=null";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2007, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ESBMoteType.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote;
|
||||
|
||||
import javax.swing.*;
|
||||
import org.apache.log4j.Logger;
|
||||
import se.sics.cooja.*;
|
||||
|
||||
@ClassDescription("ESB Mote Type")
|
||||
@AbstractionLevelDescription("Emulated level")
|
||||
public class ESBMoteType extends MspMoteType {
|
||||
private static Logger logger = Logger.getLogger(ESBMoteType.class);
|
||||
|
||||
public static final String target = "esb";
|
||||
public static final String targetNice = "ESB";
|
||||
|
||||
public ESBMoteType() {
|
||||
}
|
||||
|
||||
public ESBMoteType(String identifier) {
|
||||
setIdentifier(identifier);
|
||||
setDescription(targetNice + " Mote Type #" + identifier);
|
||||
}
|
||||
|
||||
public Mote generateMote(Simulation simulation) {
|
||||
return new ESBMote(this, simulation);
|
||||
}
|
||||
|
||||
public boolean configureAndInit(JFrame parentFrame, Simulation simulation,
|
||||
boolean visAvailable) throws MoteTypeCreationException {
|
||||
return configureAndInitMspType(parentFrame, simulation, visAvailable, target, targetNice);
|
||||
}
|
||||
|
||||
}
|
354
tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java
Normal file
354
tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright (c) 2007, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: MspMote.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.mspmote.interfaces.TR1001Radio;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
import se.sics.mspsim.core.MapTable;
|
||||
import se.sics.mspsim.util.ELF;
|
||||
|
||||
/**
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public abstract class MspMote implements Mote {
|
||||
private static Logger logger = Logger.getLogger(MspMote.class);
|
||||
|
||||
/* 2.4 MHz */
|
||||
public static int NR_CYCLES_PER_MSEC = 2365;
|
||||
|
||||
/* Cycle counter */
|
||||
public long cycleCounter = 0;
|
||||
|
||||
private Simulation mySimulation = null;
|
||||
private MSP430 myCpu = null;
|
||||
private MspMoteType myMoteType = null;
|
||||
private MspMoteMemory myMemory = null;
|
||||
private MoteInterfaceHandler myMoteInterfaceHandler = null;
|
||||
private ELF myELFModule = null;
|
||||
|
||||
protected TR1001Radio myRadio = null; /* TODO Only used by ESB (TR1001) */
|
||||
|
||||
/* Stack monitoring variables */
|
||||
private boolean stopNextInstruction = false;
|
||||
private boolean monitorStackUsage = false;
|
||||
private int stackPointerLow = Integer.MAX_VALUE;
|
||||
private int heapStartAddress;
|
||||
private StackOverflowObservable stackOverflowObservable = new StackOverflowObservable();
|
||||
|
||||
/**
|
||||
* Abort current tick immediately.
|
||||
* May for example be called by a breakpoint handler.
|
||||
*/
|
||||
public void stopNextInstruction() {
|
||||
stopNextInstruction = true;
|
||||
}
|
||||
|
||||
public MspMote() {
|
||||
myMoteType = null;
|
||||
mySimulation = null;
|
||||
myCpu = null;
|
||||
myMemory = null;
|
||||
myMoteInterfaceHandler = null;
|
||||
}
|
||||
|
||||
public MspMote(MspMoteType moteType, Simulation simulation) {
|
||||
myMoteType = moteType;
|
||||
mySimulation = simulation;
|
||||
|
||||
initEmulator(myMoteType.getELFFile());
|
||||
|
||||
myMoteInterfaceHandler = createMoteInterfaceHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MSP430 CPU
|
||||
*/
|
||||
public MSP430 getCPU() {
|
||||
return myCpu;
|
||||
}
|
||||
|
||||
public MoteMemory getMemory() {
|
||||
return myMemory;
|
||||
}
|
||||
|
||||
public void setMemory(MoteMemory memory) {
|
||||
myMemory = (MspMoteMemory) memory;
|
||||
}
|
||||
|
||||
public Simulation getSimulation() {
|
||||
return mySimulation;
|
||||
}
|
||||
|
||||
public void setSimulation(Simulation simulation) {
|
||||
mySimulation = simulation;
|
||||
}
|
||||
|
||||
/* Stack monitoring variables */
|
||||
public class StackOverflowObservable extends Observable {
|
||||
public void signalStackOverflow() {
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable stack monitoring
|
||||
*
|
||||
* @param monitoring Monitoring enabled
|
||||
*/
|
||||
public void monitorStack(boolean monitoring) {
|
||||
this.monitorStackUsage = monitoring;
|
||||
resetLowestStackPointer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Lowest SP since stack monitoring was enabled
|
||||
*/
|
||||
public int getLowestStackPointer() {
|
||||
return stackPointerLow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets lowest stack pointer variable
|
||||
*/
|
||||
public void resetLowestStackPointer() {
|
||||
stackPointerLow = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack overflow observable
|
||||
*/
|
||||
public StackOverflowObservable getStackOverflowObservable() {
|
||||
return stackOverflowObservable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates MSP430 CPU object and address memory for current object.
|
||||
* This method should normally not be called from outside constructor.
|
||||
*
|
||||
* @param fileELF ELF file
|
||||
* @throws IOException File loading failed
|
||||
*/
|
||||
protected void createCPUAndMemory(File fileELF) throws IOException {
|
||||
myCpu = new MSP430(0);
|
||||
myCpu.setMonitorExec(true);
|
||||
|
||||
int[] memory = myCpu.getMemory();
|
||||
|
||||
myELFModule = ELF.readELF(fileELF.getPath());
|
||||
myELFModule.loadPrograms(memory);
|
||||
MapTable map = myELFModule.getMap();
|
||||
myCpu.getDisAsm().setMap(map);
|
||||
myCpu.setMap(map);
|
||||
|
||||
/* TODO Need new memory type including size and type as well */
|
||||
|
||||
/* Create mote address memory */
|
||||
Properties varAddresses = new Properties();
|
||||
for (int i=0; i < map.functionNames.length; i++) {
|
||||
if (map.functionNames[i] != null) {
|
||||
varAddresses.put(map.functionNames[i], new Integer(i));
|
||||
}
|
||||
}
|
||||
myMemory = new MspMoteMemory(varAddresses, myCpu);
|
||||
|
||||
myCpu.reset();
|
||||
}
|
||||
|
||||
public void setState(State newState) {
|
||||
logger.warn("Msp motes can't change state");
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return Mote.State.ACTIVE;
|
||||
}
|
||||
|
||||
public MoteType getType() {
|
||||
return myMoteType;
|
||||
}
|
||||
|
||||
public void setType(MoteType type) {
|
||||
myMoteType = (MspMoteType) type;
|
||||
}
|
||||
|
||||
public void addStateObserver(Observer newObserver) {
|
||||
}
|
||||
|
||||
public void deleteStateObserver(Observer newObserver) {
|
||||
}
|
||||
|
||||
public MoteInterfaceHandler getInterfaces() {
|
||||
return myMoteInterfaceHandler;
|
||||
}
|
||||
|
||||
public void setInterfaces(MoteInterfaceHandler moteInterfaceHandler) {
|
||||
myMoteInterfaceHandler = moteInterfaceHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an interface handler object and registers interfaces to it.
|
||||
*
|
||||
* @return Interface handler
|
||||
*/
|
||||
protected abstract MoteInterfaceHandler createMoteInterfaceHandler();
|
||||
|
||||
/**
|
||||
* Initializes emulator by creating CPU, memory and node object.
|
||||
*
|
||||
* @param ELFFile ELF file
|
||||
* @return True if successful
|
||||
*/
|
||||
protected abstract boolean initEmulator(File ELFFile);
|
||||
|
||||
public void tick(int simTime) {
|
||||
// Let all interfaces act
|
||||
myMoteInterfaceHandler.doPassiveActionsBeforeTick();
|
||||
myMoteInterfaceHandler.doActiveActionsBeforeTick();
|
||||
|
||||
stopNextInstruction = false;
|
||||
|
||||
// Leave control to emulated CPU
|
||||
MSP430 cpu = getCPU();
|
||||
cycleCounter += NR_CYCLES_PER_MSEC;
|
||||
|
||||
if (monitorStackUsage) {
|
||||
// CPU loop with stack observer
|
||||
int newStack;
|
||||
while (!stopNextInstruction && cpu.step() < cycleCounter) {
|
||||
/* Check if radio has pending incoming bytes */
|
||||
if (myRadio != null && myRadio.hasPendingBytes()) {
|
||||
myRadio.tryDeliverNextByte(cpu.cycles);
|
||||
}
|
||||
|
||||
newStack = cpu.reg[MSP430.SP];
|
||||
if (newStack < stackPointerLow && newStack > 0) {
|
||||
stackPointerLow = cpu.reg[MSP430.SP];
|
||||
|
||||
// Check if stack is writing in memory
|
||||
if (stackPointerLow < heapStartAddress) {
|
||||
stackOverflowObservable.signalStackOverflow();
|
||||
stopNextInstruction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { /* Fast CPU loop */
|
||||
do {
|
||||
/* Check if radio has pending incoming bytes */
|
||||
if (myRadio != null && myRadio.hasPendingBytes()) {
|
||||
myRadio.tryDeliverNextByte(cpu.cycles);
|
||||
}
|
||||
} while (!stopNextInstruction && (cpu.step() < cycleCounter) );
|
||||
}
|
||||
|
||||
// Reset abort flag
|
||||
stopNextInstruction = false;
|
||||
|
||||
// Let all interfaces act after tick
|
||||
myMoteInterfaceHandler.doActiveActionsAfterTick();
|
||||
myMoteInterfaceHandler.doPassiveActionsAfterTick();
|
||||
}
|
||||
|
||||
public boolean setConfigXML(Simulation simulation, Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element: configXML) {
|
||||
String name = element.getName();
|
||||
|
||||
if (name.equals("motetype_identifier")) {
|
||||
|
||||
setSimulation(simulation);
|
||||
myMoteType = (MspMoteType) simulation.getMoteType(element.getText());
|
||||
getType().setIdentifier(element.getText());
|
||||
|
||||
initEmulator(myMoteType.getELFFile());
|
||||
myMoteInterfaceHandler = createMoteInterfaceHandler();
|
||||
|
||||
} else if (name.equals("interface_config")) {
|
||||
Class<? extends MoteInterface> moteInterfaceClass = simulation.getGUI().tryLoadClass(
|
||||
this, MoteInterface.class, element.getText().trim());
|
||||
|
||||
if (moteInterfaceClass == null) {
|
||||
logger.fatal("Could not load mote interface class: " + element.getText().trim());
|
||||
return false;
|
||||
}
|
||||
|
||||
MoteInterface moteInterface = getInterfaces().getInterfaceOfType(moteInterfaceClass);
|
||||
moteInterface.setConfigXML(element.getChildren(), visAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
Vector<Element> config = new Vector<Element>();
|
||||
|
||||
Element element;
|
||||
|
||||
// Mote type identifier
|
||||
element = new Element("motetype_identifier");
|
||||
element.setText(getType().getIdentifier());
|
||||
config.add(element);
|
||||
|
||||
// Active interface configs (if any)
|
||||
for (MoteInterface moteInterface: getInterfaces().getAllActiveInterfaces()) {
|
||||
element = new Element("interface_config");
|
||||
element.setText(moteInterface.getClass().getName());
|
||||
|
||||
Collection interfaceXML = moteInterface.getConfigXML();
|
||||
if (interfaceXML != null) {
|
||||
element.addContent(interfaceXML);
|
||||
config.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
// Passive interface configs (if any)
|
||||
for (MoteInterface moteInterface: getInterfaces().getAllPassiveInterfaces()) {
|
||||
element = new Element("interface_config");
|
||||
element.setText(moteInterface.getClass().getName());
|
||||
|
||||
Collection interfaceXML = moteInterface.getConfigXML();
|
||||
if (interfaceXML != null) {
|
||||
element.addContent(interfaceXML);
|
||||
config.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (c) 2007, Swedish Institute of Computer Science. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of the
|
||||
* Institute nor the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: MspMoteMemory.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote;
|
||||
|
||||
import java.util.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.AddressMemory;
|
||||
import se.sics.cooja.MoteMemory;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
|
||||
public class MspMoteMemory implements MoteMemory, AddressMemory {
|
||||
private static Logger logger = Logger.getLogger(MspMoteMemory.class);
|
||||
private final Properties variableAddresses;
|
||||
|
||||
private int TEMP_MEM_START;
|
||||
private MSP430 cpu;
|
||||
|
||||
public MspMoteMemory(Properties variableAddresses, MSP430 cpu) {
|
||||
this.variableAddresses = variableAddresses;
|
||||
|
||||
this.cpu = cpu;
|
||||
TEMP_MEM_START = 0;
|
||||
}
|
||||
|
||||
public String[] getVariableNames() {
|
||||
String[] names = new String[variableAddresses.size()];
|
||||
Enumeration nameEnum = variableAddresses.keys();
|
||||
for (int i = 0; i < variableAddresses.size(); i++) {
|
||||
names[i] = (String) nameEnum.nextElement();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public int getVariableAddress(String varName) {
|
||||
if (!variableAddresses.containsKey(varName)) {
|
||||
return -1;
|
||||
}
|
||||
return ((Integer) variableAddresses.get(varName)).intValue();
|
||||
}
|
||||
|
||||
public void clearMemory() {
|
||||
logger.fatal("clearMemory() not implemented");
|
||||
}
|
||||
|
||||
public byte[] getMemorySegment(int address, int size) {
|
||||
int[] ret = new int[size];
|
||||
|
||||
System.arraycopy(cpu.memory, address - TEMP_MEM_START, ret, 0, size);
|
||||
|
||||
// TODO XXX Slow method
|
||||
byte[] ret2 = new byte[size];
|
||||
for (int i=0; i < size; i++) {
|
||||
ret2[i] = (byte) ret[i];
|
||||
}
|
||||
|
||||
return ret2;
|
||||
}
|
||||
|
||||
public void setMemorySegment(int address, byte[] data) {
|
||||
// TODO XXX Slow method
|
||||
int[] intArr = new int[data.length];
|
||||
for (int i=0; i < data.length; i++) {
|
||||
intArr[i] = data[i];
|
||||
}
|
||||
|
||||
System.arraycopy(intArr, 0, cpu.memory, address - TEMP_MEM_START, data.length);
|
||||
}
|
||||
|
||||
public int getTotalSize() {
|
||||
return cpu.memory.length;
|
||||
}
|
||||
|
||||
public boolean variableExists(String varName) {
|
||||
return variableAddresses.containsKey(varName);
|
||||
}
|
||||
|
||||
public int getIntValueOf(String varName) {
|
||||
// Get start address of variable
|
||||
if (!variableAddresses.containsKey(varName)) {
|
||||
return -1;
|
||||
}
|
||||
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
|
||||
|
||||
byte[] varData = getMemorySegment(varAddr, 2);
|
||||
|
||||
int retVal = 0;
|
||||
int pos = 0;
|
||||
retVal += ((varData[pos++] & 0xFF)) << 8;
|
||||
retVal += ((varData[pos++] & 0xFF)) << 0;
|
||||
|
||||
return Integer.reverseBytes(retVal) >> 16; // Crop two bytes
|
||||
}
|
||||
|
||||
public void setIntValueOf(String varName, int newVal) {
|
||||
// Get start address of variable
|
||||
if (!variableAddresses.containsKey(varName)) {
|
||||
return;
|
||||
}
|
||||
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
|
||||
|
||||
// TODO Check if small/big-endian when coming from JNI?
|
||||
int newValToSet = Integer.reverseBytes(newVal);
|
||||
|
||||
// Create byte array
|
||||
int pos = 0;
|
||||
|
||||
byte[] varData = new byte[4];
|
||||
varData[pos++] = (byte) ((newValToSet & 0xFF000000) >> 24);
|
||||
varData[pos++] = (byte) ((newValToSet & 0xFF0000) >> 16);
|
||||
varData[pos++] = (byte) ((newValToSet & 0xFF00) >> 8);
|
||||
varData[pos++] = (byte) ((newValToSet & 0xFF) >> 0);
|
||||
|
||||
setMemorySegment(varAddr, varData);
|
||||
}
|
||||
|
||||
public byte getByteValueOf(String varName) {
|
||||
// Get start address of variable
|
||||
if (!variableAddresses.containsKey(varName)) {
|
||||
return -1;
|
||||
}
|
||||
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
|
||||
|
||||
byte[] varData = getMemorySegment(varAddr, 1);
|
||||
|
||||
return varData[0];
|
||||
}
|
||||
|
||||
public void setByteValueOf(String varName, byte newVal) {
|
||||
// Get start address of variable
|
||||
if (!variableAddresses.containsKey(varName)) {
|
||||
return;
|
||||
}
|
||||
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
|
||||
|
||||
byte[] varData = new byte[1];
|
||||
|
||||
varData[0] = newVal;
|
||||
|
||||
setMemorySegment(varAddr, varData);
|
||||
}
|
||||
|
||||
public byte[] getByteArray(String varName, int length) {
|
||||
// Get start address of variable
|
||||
if (!variableAddresses.containsKey(varName)) {
|
||||
return null;
|
||||
}
|
||||
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
|
||||
|
||||
// TODO Check if small/big-endian when coming from JNI?
|
||||
return getMemorySegment(varAddr, length);
|
||||
}
|
||||
|
||||
public void setByteArray(String varName, byte[] data) {
|
||||
// Get start address of variable
|
||||
if (!variableAddresses.containsKey(varName)) {
|
||||
return;
|
||||
}
|
||||
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
|
||||
|
||||
// TODO Check if small/big-endian when coming from JNI?
|
||||
setMemorySegment(varAddr, data);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,942 @@
|
|||
/*
|
||||
* Copyright (c) 2007, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: MspMoteType.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.dialogs.MessageList;
|
||||
|
||||
@ClassDescription("Msp Mote Type")
|
||||
public abstract class MspMoteType implements MoteType {
|
||||
private static Logger logger = Logger.getLogger(MspMoteType.class);
|
||||
|
||||
private static final String firmwareFileExtension = ".firmware";
|
||||
|
||||
/* Convenience: Preselecting last used directory */
|
||||
protected static File lastParentDirectory = null;
|
||||
|
||||
private String identifier = null;
|
||||
private String description = null;
|
||||
|
||||
/* If source file is defined, (re)compilation is performed */
|
||||
private File fileELF = null;
|
||||
private File fileSource = null;
|
||||
private String compileCommand = null;
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ELF file.
|
||||
*
|
||||
* @param file
|
||||
* ELF file
|
||||
*/
|
||||
public void setELFFile(File file) {
|
||||
this.fileELF = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set compile command.
|
||||
*
|
||||
* @param command
|
||||
* Compile command
|
||||
*/
|
||||
public void setCompileCommand(String command) {
|
||||
this.compileCommand = command;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ELF file
|
||||
*/
|
||||
public File getELFFile() {
|
||||
return fileELF;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Compile command
|
||||
*/
|
||||
public String getCompileCommand() {
|
||||
return compileCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source file
|
||||
*
|
||||
* @param file Source file
|
||||
*/
|
||||
public void setSourceFile(File file) {
|
||||
fileSource = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Source file
|
||||
*/
|
||||
public File getSourceFile() {
|
||||
return fileSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures and initialized Msp mote types.
|
||||
*
|
||||
* @param parentFrame Graphical parent frame
|
||||
* @param simulation Current simulation
|
||||
* @param visAvailable Enable graphical interfaces and user input
|
||||
* @param target Contiki target platform name
|
||||
* @param targetNice Nicer representation of target
|
||||
* @return True is successful
|
||||
* @throws MoteTypeCreationException Mote type creation failed
|
||||
*/
|
||||
protected boolean configureAndInitMspType(JFrame parentFrame, Simulation simulation,
|
||||
boolean visAvailable, String target, String targetNice)
|
||||
throws MoteTypeCreationException {
|
||||
boolean compileFromSource = false;
|
||||
|
||||
if (getIdentifier() == null && !visAvailable) {
|
||||
throw new MoteTypeCreationException("No identifier");
|
||||
}
|
||||
|
||||
/* Generate unique identifier */
|
||||
if (getIdentifier() == null) {
|
||||
int counter = 0;
|
||||
boolean identifierOK = false;
|
||||
while (!identifierOK) {
|
||||
counter++;
|
||||
setIdentifier(target + counter);
|
||||
identifierOK = true;
|
||||
|
||||
// Check if identifier is already used by some other type
|
||||
for (MoteType existingMoteType : simulation.getMoteTypes()) {
|
||||
if (existingMoteType != this
|
||||
&& existingMoteType.getIdentifier().equals(getIdentifier())) {
|
||||
identifierOK = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getDescription() == null) {
|
||||
setDescription(targetNice + " Mote Type #" + counter);
|
||||
}
|
||||
|
||||
/* Let user choose whether to compile or load existing binaries */
|
||||
Object[] options = { "Select", "Compile" };
|
||||
|
||||
String question = targetNice + " mote type depends on an ELF file.\n"
|
||||
+ "If you want to use an already existing file, click 'Select'.\n\n"
|
||||
+ "To compile this file from source, click 'Compile'";
|
||||
String title = "Select or compile " + targetNice + " firmware";
|
||||
int answer = JOptionPane.showOptionDialog(GUI.frame,
|
||||
question, title, JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
|
||||
|
||||
if (answer != JOptionPane.YES_OPTION && answer != JOptionPane.NO_OPTION) {
|
||||
return false;
|
||||
}
|
||||
compileFromSource = answer != JOptionPane.YES_OPTION;
|
||||
}
|
||||
|
||||
/* Description */
|
||||
if (getDescription() == null) {
|
||||
setDescription(targetNice + " Mote Type #" + getIdentifier());
|
||||
}
|
||||
|
||||
if (getSourceFile() != null) {
|
||||
compileFromSource = true;
|
||||
}
|
||||
|
||||
if (compileFromSource) {
|
||||
MspELFCompiler compiler = new MspELFCompiler(target);
|
||||
compiler.setCompileCommand(compileCommand);
|
||||
|
||||
if (visAvailable) {
|
||||
boolean success = compiler.showDialog(GUI.frame, this);
|
||||
if (success) {
|
||||
setSourceFile(compiler.getSourceFile());
|
||||
setELFFile(compiler.getOutputFile());
|
||||
setCompileCommand(compiler.getLastCompileCommand());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MessageList compilationOutput = new MessageList();
|
||||
try {
|
||||
compiler.compileFirmware(getSourceFile(), null, null, compilationOutput,
|
||||
true);
|
||||
} catch (Exception e) {
|
||||
MoteTypeCreationException newException = new MoteTypeCreationException(
|
||||
"Mote type creation failed: " + e.getMessage());
|
||||
newException = (MoteTypeCreationException) newException.initCause(e);
|
||||
newException.setCompilationOutput(compilationOutput);
|
||||
throw newException;
|
||||
}
|
||||
|
||||
/*File parentFile = getSourceFile().getParentFile();*/
|
||||
/*final String filenameNoExtension = getSourceFile().getName().substring(0,
|
||||
getSourceFile().getName().length() - 2);*/
|
||||
/*setELFFile(new File(parentFile, filenameNoExtension + firmwareFileExtension));*/
|
||||
|
||||
setSourceFile(compiler.getSourceFile());
|
||||
setELFFile(compiler.getOutputFile());
|
||||
setCompileCommand(compiler.getLastCompileCommand());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check dependency files
|
||||
if (getELFFile() == null || !getELFFile().exists()) {
|
||||
if (visAvailable) {
|
||||
JFileChooser fc = new JFileChooser();
|
||||
|
||||
// Select previous directory
|
||||
if (lastParentDirectory != null) {
|
||||
fc.setCurrentDirectory(lastParentDirectory);
|
||||
} else {
|
||||
fc.setCurrentDirectory(new java.io.File(GUI
|
||||
.getExternalToolsSetting("PATH_CONTIKI")));
|
||||
}
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.addChoosableFileFilter(new FileFilter() {
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String filename = f.getName();
|
||||
if (filename != null) {
|
||||
if (filename.endsWith(firmwareFileExtension)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "ELF file";
|
||||
}
|
||||
});
|
||||
fc.setDialogTitle("Select ELF file");
|
||||
|
||||
if (fc.showOpenDialog(parentFrame) == JFileChooser.APPROVE_OPTION) {
|
||||
lastParentDirectory = fc.getSelectedFile().getParentFile();
|
||||
setELFFile(fc.getSelectedFile());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
throw new MoteTypeCreationException("No ELF file was created");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static class MspELFCompiler {
|
||||
private static int LABEL_WIDTH = 170;
|
||||
|
||||
private static int LABEL_HEIGHT = 15;
|
||||
|
||||
private JButton cancelButton = new JButton("Cancel");
|
||||
|
||||
private JButton compileButton = new JButton("Compile");
|
||||
|
||||
private JButton createButton = new JButton("Create");
|
||||
|
||||
private JTextField sourceTextField = new JTextField();
|
||||
|
||||
private JTextField compileCommandTextField = new JTextField();
|
||||
|
||||
// private JFormattedTextField nodeIDTextField;
|
||||
// private NumberFormat integerFormat = NumberFormat.getIntegerInstance();
|
||||
|
||||
private String lastCompileCommand = null;
|
||||
|
||||
private File sourceFile = null;
|
||||
|
||||
private File ELFFile = null;
|
||||
|
||||
private String target;
|
||||
|
||||
private JDialog myDialog;
|
||||
|
||||
private String customizedCompileCommand = null;
|
||||
|
||||
static enum DialogState {
|
||||
NO_SOURCE, SELECTED_SOURCE, IS_COMPILING, COMPILED_SOURCE
|
||||
}
|
||||
|
||||
public MspELFCompiler(String target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
private String getCompileCommand(String filename) {
|
||||
if (customizedCompileCommand != null) {
|
||||
return customizedCompileCommand;
|
||||
}
|
||||
return GUI.getExternalToolsSetting("PATH_MAKE") + " " + filename + firmwareFileExtension + " TARGET=" + target;
|
||||
}
|
||||
|
||||
private void setCompileCommand(String command) {
|
||||
if (command == null || command.isEmpty()) {
|
||||
customizedCompileCommand = null;
|
||||
return;
|
||||
}
|
||||
customizedCompileCommand = command;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Compiler output
|
||||
*/
|
||||
public File getOutputFile() {
|
||||
return ELFFile;
|
||||
}
|
||||
|
||||
public File getSourceFile() {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
public String getLastCompileCommand() {
|
||||
return lastCompileCommand;
|
||||
}
|
||||
|
||||
private void updateDialog(DialogState dialogState) {
|
||||
switch (dialogState) {
|
||||
case NO_SOURCE:
|
||||
compileButton.setEnabled(false);
|
||||
createButton.setEnabled(false);
|
||||
compileCommandTextField.setText("");
|
||||
break;
|
||||
|
||||
case IS_COMPILING:
|
||||
compileButton.setEnabled(false);
|
||||
createButton.setEnabled(false);
|
||||
break;
|
||||
|
||||
case SELECTED_SOURCE:
|
||||
File sourceFile = new File(sourceTextField.getText());
|
||||
if (!sourceFile.exists()) {
|
||||
updateDialog(DialogState.NO_SOURCE);
|
||||
break;
|
||||
}
|
||||
|
||||
File parentDirectory = sourceFile.getParentFile();
|
||||
if (!parentDirectory.exists()) {
|
||||
updateDialog(DialogState.NO_SOURCE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!sourceFile.getName().endsWith(".c")) {
|
||||
updateDialog(DialogState.NO_SOURCE);
|
||||
break;
|
||||
}
|
||||
|
||||
String name = sourceFile.getName().substring(0,
|
||||
sourceFile.getName().length() - 2);
|
||||
|
||||
compileButton.setEnabled(true);
|
||||
createButton.setEnabled(false);
|
||||
compileCommandTextField.setText(getCompileCommand(name));
|
||||
compileButton.requestFocusInWindow();
|
||||
break;
|
||||
|
||||
case COMPILED_SOURCE:
|
||||
compileButton.setEnabled(true);
|
||||
createButton.setEnabled(true);
|
||||
|
||||
createButton.requestFocusInWindow();
|
||||
myDialog.getRootPane().setDefaultButton(createButton);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected void compileFirmware(final File sourceFile,
|
||||
final Action successAction, final Action failAction,
|
||||
MessageList compilationOutput, boolean synchronous) throws Exception {
|
||||
final File parentDirectory = sourceFile.getParentFile();
|
||||
final String filenameNoExtension = sourceFile.getName().substring(0,
|
||||
sourceFile.getName().length() - 2);
|
||||
|
||||
String command = getCompileCommand(filenameNoExtension);
|
||||
logger.info("Compile command: " + command);
|
||||
|
||||
compilationOutput.clearMessages();
|
||||
|
||||
try {
|
||||
String[] cmd = command.split(" ");
|
||||
|
||||
final Process compileProcess = Runtime.getRuntime().exec(cmd, null,
|
||||
parentDirectory);
|
||||
|
||||
final BufferedReader processNormal = new BufferedReader(
|
||||
new InputStreamReader(compileProcess.getInputStream()));
|
||||
final BufferedReader processError = new BufferedReader(
|
||||
new InputStreamReader(compileProcess.getErrorStream()));
|
||||
|
||||
final PrintStream listNormal = compilationOutput
|
||||
.getInputStream(MessageList.NORMAL);
|
||||
final PrintStream listError = compilationOutput
|
||||
.getInputStream(MessageList.ERROR);
|
||||
|
||||
final File ELFFile = new File(parentDirectory, filenameNoExtension + firmwareFileExtension);
|
||||
if (ELFFile.exists()) {
|
||||
ELFFile.delete();
|
||||
if (ELFFile.exists()) {
|
||||
listError.println("Error when deleting old " + ELFFile.getName());
|
||||
if (failAction != null) {
|
||||
failAction.actionPerformed(null);
|
||||
}
|
||||
throw new MoteTypeCreationException("Error when deleting old "
|
||||
+ ELFFile.getName());
|
||||
}
|
||||
}
|
||||
|
||||
Thread readInput = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
String readLine;
|
||||
try {
|
||||
while ((readLine = processNormal.readLine()) != null) {
|
||||
if (listNormal != null && readLine != null) {
|
||||
listNormal.println(readLine);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warn("Error while reading from process");
|
||||
}
|
||||
}
|
||||
}, "read input stream thread");
|
||||
|
||||
Thread readError = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
String readLine;
|
||||
try {
|
||||
while ((readLine = processError.readLine()) != null) {
|
||||
if (listError != null && readLine != null) {
|
||||
listError.println(readLine);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warn("Error while reading from process");
|
||||
}
|
||||
}
|
||||
}, "read input stream thread");
|
||||
|
||||
final MoteTypeCreationException syncException = new MoteTypeCreationException(
|
||||
"");
|
||||
Thread handleCompilationResultThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
|
||||
/* Wait for compilation to end */
|
||||
try {
|
||||
compileProcess.waitFor();
|
||||
} catch (Exception e) {
|
||||
syncException.setCompilationOutput(new MessageList());
|
||||
syncException.fillInStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check return value */
|
||||
if (compileProcess.exitValue() != 0) {
|
||||
listError.println("Process returned error code "
|
||||
+ compileProcess.exitValue());
|
||||
if (failAction != null) {
|
||||
failAction.actionPerformed(null);
|
||||
}
|
||||
syncException.setCompilationOutput(new MessageList());
|
||||
syncException.fillInStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ELFFile.exists()) {
|
||||
listError.println("Can't locate output file " + ELFFile);
|
||||
if (failAction != null) {
|
||||
failAction.actionPerformed(null);
|
||||
}
|
||||
syncException.setCompilationOutput(new MessageList());
|
||||
syncException.fillInStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
listNormal.println("");
|
||||
listNormal.println("Compilation succeded");
|
||||
if (successAction != null) {
|
||||
successAction.actionPerformed(null);
|
||||
}
|
||||
}
|
||||
}, "enable create button thread");
|
||||
|
||||
readInput.start();
|
||||
readError.start();
|
||||
handleCompilationResultThread.start();
|
||||
|
||||
if (synchronous) {
|
||||
try {
|
||||
handleCompilationResultThread.join();
|
||||
} catch (Exception e) {
|
||||
throw (MoteTypeCreationException) new MoteTypeCreationException(
|
||||
"Compilation error: " + e.getMessage()).initCause(e);
|
||||
}
|
||||
|
||||
if (syncException.hasCompilationOutput()) {
|
||||
throw (MoteTypeCreationException) new MoteTypeCreationException(
|
||||
"Compilation error").initCause(syncException);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
if (failAction != null) {
|
||||
failAction.actionPerformed(null);
|
||||
}
|
||||
throw (MoteTypeCreationException) new MoteTypeCreationException(
|
||||
"Compilation error: " + ex.getMessage()).initCause(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean showDialog(Frame parentFrame, final MspMoteType moteType) {
|
||||
myDialog = new JDialog(parentFrame, "Compile ELF file", true);
|
||||
final MessageList taskOutput = new MessageList();
|
||||
|
||||
// BOTTOM BUTTON PART
|
||||
Box buttonBox = Box.createHorizontalBox();
|
||||
buttonBox.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
|
||||
|
||||
buttonBox.add(Box.createHorizontalGlue());
|
||||
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
sourceFile = null;
|
||||
ELFFile = null;
|
||||
|
||||
myDialog.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
compileButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final File selectedSourceFile = new File(sourceTextField.getText());
|
||||
|
||||
/* Strip .c file extension */
|
||||
final String filenameNoExtension = selectedSourceFile.getName()
|
||||
.substring(0, selectedSourceFile.getName().length() - 2);
|
||||
|
||||
Action successAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updateDialog(DialogState.COMPILED_SOURCE);
|
||||
File parentFile = selectedSourceFile.getParentFile();
|
||||
|
||||
lastCompileCommand = getCompileCommand(filenameNoExtension);
|
||||
sourceFile = selectedSourceFile;
|
||||
ELFFile = new File(parentFile, filenameNoExtension + firmwareFileExtension);
|
||||
}
|
||||
};
|
||||
Action failAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updateDialog(DialogState.SELECTED_SOURCE);
|
||||
}
|
||||
};
|
||||
|
||||
updateDialog(DialogState.IS_COMPILING);
|
||||
try {
|
||||
compileFirmware(new File(sourceTextField.getText()), successAction,
|
||||
failAction, taskOutput, false);
|
||||
} catch (Exception e2) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
createButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myDialog.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
buttonBox.add(cancelButton);
|
||||
buttonBox.add(Box.createHorizontalStrut(5));
|
||||
buttonBox.add(compileButton);
|
||||
buttonBox.add(Box.createHorizontalStrut(5));
|
||||
buttonBox.add(createButton);
|
||||
|
||||
// MAIN DIALOG CONTENTS
|
||||
Box horizBox;
|
||||
JLabel label;
|
||||
Box vertBox = Box.createVerticalBox();
|
||||
|
||||
// Source
|
||||
horizBox = Box.createHorizontalBox();
|
||||
horizBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, LABEL_HEIGHT));
|
||||
horizBox.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
label = new JLabel("Contiki process sourcefile");
|
||||
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
|
||||
|
||||
sourceTextField.setText("");
|
||||
if (moteType.getSourceFile() != null) {
|
||||
sourceTextField.setText(moteType.getSourceFile().getAbsolutePath());
|
||||
}
|
||||
sourceTextField.setColumns(25);
|
||||
|
||||
sourceTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
updateDialog(DialogState.SELECTED_SOURCE);
|
||||
}
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
updateDialog(DialogState.SELECTED_SOURCE);
|
||||
}
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
updateDialog(DialogState.SELECTED_SOURCE);
|
||||
}
|
||||
});
|
||||
|
||||
JButton browseButton = new JButton("Browse");
|
||||
browseButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updateDialog(DialogState.NO_SOURCE);
|
||||
|
||||
JFileChooser fc = new JFileChooser();
|
||||
if (lastParentDirectory != null) {
|
||||
fc.setCurrentDirectory(lastParentDirectory);
|
||||
} else {
|
||||
fc.setCurrentDirectory(new java.io.File(GUI
|
||||
.getExternalToolsSetting("PATH_CONTIKI")));
|
||||
}
|
||||
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.addChoosableFileFilter(new FileFilter() {
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String filename = f.getName();
|
||||
if (filename != null) {
|
||||
if (filename.endsWith(".c")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "Contiki process source";
|
||||
}
|
||||
});
|
||||
fc.setDialogTitle("Select Contiki process source");
|
||||
|
||||
if (fc.showOpenDialog(myDialog) == JFileChooser.APPROVE_OPTION) {
|
||||
lastParentDirectory = null;
|
||||
sourceTextField.setText("");
|
||||
|
||||
File selectedFile = fc.getSelectedFile();
|
||||
if (!selectedFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedFile.getName().endsWith(".c")) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastParentDirectory = fc.getSelectedFile().getParentFile();
|
||||
sourceTextField.setText(fc.getSelectedFile().getAbsolutePath());
|
||||
updateDialog(DialogState.SELECTED_SOURCE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
horizBox.add(label);
|
||||
horizBox.add(Box.createHorizontalStrut(10));
|
||||
horizBox.add(sourceTextField);
|
||||
horizBox.add(browseButton);
|
||||
|
||||
vertBox.add(horizBox);
|
||||
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
|
||||
// Node ID
|
||||
/*
|
||||
* horizBox = Box.createHorizontalBox(); horizBox.setMaximumSize(new
|
||||
* Dimension(Integer.MAX_VALUE,LABEL_HEIGHT));
|
||||
* horizBox.setAlignmentX(Component.LEFT_ALIGNMENT); label = new
|
||||
* JLabel("Node ID (0=EEPROM)"); label.setPreferredSize(new
|
||||
* Dimension(LABEL_WIDTH,LABEL_HEIGHT));
|
||||
*
|
||||
* nodeIDTextField = new JFormattedTextField(integerFormat);
|
||||
* nodeIDTextField.setValue(new Integer(0));
|
||||
* nodeIDTextField.setColumns(25);
|
||||
* nodeIDTextField.addPropertyChangeListener("value", new
|
||||
* PropertyChangeListener() { public void
|
||||
* propertyChange(PropertyChangeEvent e) {
|
||||
* updateDialog(DialogState.SELECTED_SOURCE); } });
|
||||
*
|
||||
* horizBox.add(label); horizBox.add(Box.createHorizontalStrut(150));
|
||||
* horizBox.add(nodeIDTextField);
|
||||
*
|
||||
* vertBox.add(horizBox); vertBox.add(Box.createRigidArea(new
|
||||
* Dimension(0,5)));
|
||||
*/
|
||||
|
||||
// Compile command
|
||||
horizBox = Box.createHorizontalBox();
|
||||
horizBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, LABEL_HEIGHT));
|
||||
horizBox.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
label = new JLabel("Compile command");
|
||||
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
|
||||
|
||||
compileCommandTextField.setText("");
|
||||
compileCommandTextField.setColumns(25);
|
||||
compileCommandTextField.setEditable(true);
|
||||
|
||||
compileCommandTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
setCompileCommand(compileCommandTextField.getText());
|
||||
}
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
setCompileCommand(compileCommandTextField.getText());
|
||||
}
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
setCompileCommand(compileCommandTextField.getText());
|
||||
}
|
||||
});
|
||||
|
||||
horizBox.add(label);
|
||||
horizBox.add(Box.createHorizontalStrut(10));
|
||||
horizBox.add(compileCommandTextField);
|
||||
|
||||
vertBox.add(horizBox);
|
||||
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
|
||||
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
vertBox.add(new JLabel("Compilation output:"));
|
||||
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
|
||||
vertBox.add(new JScrollPane(taskOutput));
|
||||
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
|
||||
vertBox.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
Container contentPane = myDialog.getContentPane();
|
||||
contentPane.add(vertBox, BorderLayout.CENTER);
|
||||
contentPane.add(buttonBox, BorderLayout.SOUTH);
|
||||
|
||||
myDialog.pack();
|
||||
myDialog.setLocationRelativeTo(parentFrame);
|
||||
myDialog.getRootPane().setDefaultButton(compileButton);
|
||||
|
||||
// Dispose on escape key
|
||||
InputMap inputMap = myDialog.getRootPane().getInputMap(
|
||||
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false),
|
||||
"dispose");
|
||||
AbstractAction cancelAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
cancelButton.doClick();
|
||||
}
|
||||
};
|
||||
myDialog.getRootPane().getActionMap().put("dispose", cancelAction);
|
||||
|
||||
myDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
|
||||
myDialog.addWindowListener(new WindowListener() {
|
||||
public void windowDeactivated(WindowEvent e) {
|
||||
}
|
||||
|
||||
public void windowIconified(WindowEvent e) {
|
||||
}
|
||||
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
}
|
||||
|
||||
public void windowOpened(WindowEvent e) {
|
||||
}
|
||||
|
||||
public void windowClosed(WindowEvent e) {
|
||||
}
|
||||
|
||||
public void windowActivated(WindowEvent e) {
|
||||
}
|
||||
|
||||
public void windowClosing(WindowEvent e) {
|
||||
cancelButton.doClick();
|
||||
}
|
||||
});
|
||||
|
||||
updateDialog(DialogState.NO_SOURCE);
|
||||
if (moteType.getSourceFile() != null) {
|
||||
updateDialog(DialogState.SELECTED_SOURCE);
|
||||
if (customizedCompileCommand != null && !customizedCompileCommand.equals("")) {
|
||||
compileCommandTextField.setText(customizedCompileCommand);
|
||||
}
|
||||
compileButton.requestFocus();
|
||||
}
|
||||
|
||||
myDialog.setVisible(true);
|
||||
|
||||
return sourceFile != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public JPanel getTypeVisualizer() {
|
||||
JPanel panel = new JPanel();
|
||||
JLabel label = new JLabel();
|
||||
JPanel smallPane;
|
||||
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
|
||||
// Identifier
|
||||
smallPane = new JPanel(new BorderLayout());
|
||||
label = new JLabel("Identifier");
|
||||
smallPane.add(BorderLayout.WEST, label);
|
||||
label = new JLabel(getIdentifier());
|
||||
smallPane.add(BorderLayout.EAST, label);
|
||||
panel.add(smallPane);
|
||||
|
||||
// Description
|
||||
smallPane = new JPanel(new BorderLayout());
|
||||
label = new JLabel("Description");
|
||||
smallPane.add(BorderLayout.WEST, label);
|
||||
label = new JLabel(getDescription());
|
||||
smallPane.add(BorderLayout.EAST, label);
|
||||
panel.add(smallPane);
|
||||
|
||||
// ELF Hex file
|
||||
smallPane = new JPanel(new BorderLayout());
|
||||
label = new JLabel("ELF file");
|
||||
smallPane.add(BorderLayout.WEST, label);
|
||||
label = new JLabel(getELFFile().getName());
|
||||
label.setToolTipText(getELFFile().getPath());
|
||||
smallPane.add(BorderLayout.EAST, label);
|
||||
panel.add(smallPane);
|
||||
|
||||
// Source file
|
||||
smallPane = new JPanel(new BorderLayout());
|
||||
label = new JLabel("Source file");
|
||||
smallPane.add(BorderLayout.WEST, label);
|
||||
if (getSourceFile() != null) {
|
||||
label = new JLabel(getSourceFile().getName());
|
||||
label.setToolTipText(getSourceFile().getPath());
|
||||
} else {
|
||||
label = new JLabel("[not specified]");
|
||||
}
|
||||
smallPane.add(BorderLayout.EAST, label);
|
||||
panel.add(smallPane);
|
||||
|
||||
panel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
return panel;
|
||||
}
|
||||
|
||||
public ProjectConfig getConfig() {
|
||||
logger.warn("Msp mote type project config not implemented");
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
Vector<Element> config = new Vector<Element>();
|
||||
|
||||
Element element;
|
||||
|
||||
// Identifier
|
||||
element = new Element("identifier");
|
||||
element.setText(getIdentifier());
|
||||
config.add(element);
|
||||
|
||||
// Description
|
||||
element = new Element("description");
|
||||
element.setText(getDescription());
|
||||
config.add(element);
|
||||
|
||||
// Source file
|
||||
if (fileSource != null) {
|
||||
element = new Element("source");
|
||||
element.setText(fileSource.getPath());
|
||||
config.add(element);
|
||||
element = new Element("command");
|
||||
element.setText(compileCommand);
|
||||
config.add(element);
|
||||
} else {
|
||||
// ELF file
|
||||
element = new Element("elf");
|
||||
element.setText(fileELF.getPath());
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean setConfigXML(Simulation simulation,
|
||||
Collection<Element> configXML, boolean visAvailable)
|
||||
throws MoteTypeCreationException {
|
||||
for (Element element : configXML) {
|
||||
String name = element.getName();
|
||||
|
||||
if (name.equals("identifier")) {
|
||||
identifier = element.getText();
|
||||
} else if (name.equals("description")) {
|
||||
description = element.getText();
|
||||
} else if (name.equals("source")) {
|
||||
fileSource = new File(element.getText());
|
||||
} else if (name.equals("command")) {
|
||||
compileCommand = element.getText();
|
||||
} else if (name.equals("elf")) {
|
||||
fileELF = new File(element.getText());
|
||||
} else {
|
||||
logger.fatal("Unrecognized entry in loaded configuration: " + name);
|
||||
throw new MoteTypeCreationException(
|
||||
"Unrecognized entry in loaded configuration: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
return configureAndInit(GUI.frame, simulation, visAvailable);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue