Merge pull request #628 from ejoerns/pull-req/cooja-memory
[Cooja] Rewrote Coojas mote memory management
This commit is contained in:
commit
2a0ccf2c6b
42 changed files with 3173 additions and 1714 deletions
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig. All rights reserved.
|
||||
* Copyright (c) 2009, Swedish Institute of Computer Science. All rights
|
||||
* reserved.
|
||||
*
|
||||
|
@ -28,158 +29,196 @@
|
|||
|
||||
package org.contikios.cooja.avrmote;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.contikios.cooja.AddressMemory;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import avrora.arch.avr.AVRProperties;
|
||||
import avrora.core.SourceMapping;
|
||||
import avrora.core.SourceMapping.Location;
|
||||
import avrora.sim.AtmelInterpreter;
|
||||
import avrora.sim.Simulator.Watch;
|
||||
import avrora.sim.State;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor.EventType;
|
||||
import org.contikios.cooja.mote.memory.MemoryLayout;
|
||||
/**
|
||||
* @author Joakim Eriksson
|
||||
* @author Joakim Eriksson, Fredrik Osterlind, David Kopf, Enrico Jorns
|
||||
*/
|
||||
public class AvrMoteMemory implements MoteMemory, AddressMemory {
|
||||
private static Logger logger = Logger.getLogger(AvrMoteMemory.class);
|
||||
public class AvrMoteMemory implements MemoryInterface {
|
||||
private static Logger logger = Logger.getLogger(AvrMoteMemory.class);
|
||||
private static final boolean DEBUG = logger.isDebugEnabled();
|
||||
|
||||
private final SourceMapping memoryMap;
|
||||
private final AVRProperties avrProperties;
|
||||
private final AtmelInterpreter interpreter;
|
||||
private final ArrayList<AvrByteMonitor> memoryMonitors = new ArrayList<>();
|
||||
private final MemoryLayout memLayout = new MemoryLayout(ByteOrder.LITTLE_ENDIAN, MemoryLayout.ARCH_8BIT, 2);
|
||||
|
||||
private boolean coojaIsAccessingMemory;
|
||||
|
||||
private SourceMapping memoryMap;
|
||||
private AtmelInterpreter interpreter;
|
||||
private AVRProperties avrProperties;
|
||||
|
||||
public AvrMoteMemory(SourceMapping map, AVRProperties avrProperties, AtmelInterpreter interpreter) {
|
||||
memoryMap = map;
|
||||
this.interpreter = interpreter;
|
||||
this.avrProperties = avrProperties;
|
||||
}
|
||||
|
||||
public void insertWatch(Watch w, int address) {
|
||||
interpreter.getSimulator().insertWatch(w, address);
|
||||
}
|
||||
|
||||
public void clearMemory() {
|
||||
logger.fatal("not implemented");
|
||||
@Override
|
||||
public int getTotalSize() {
|
||||
return avrProperties.sram_size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getMemory() throws MoteMemoryException {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getMemorySegment(long address, int size) throws MoteMemoryException {
|
||||
/*logger.info("getMemorySegment(" + String.format("0x%04x", address) +
|
||||
", " + size + ")");*/
|
||||
if (!accessInRange(address, size)) {
|
||||
throw new MoteMemoryException(
|
||||
"Getting memory segment [0x%x,0x%x] failed: Out of range",
|
||||
address, address + size - 1);
|
||||
}
|
||||
|
||||
public byte[] getMemorySegment(int address, int size) {
|
||||
logger.fatal("getMemorySegment is not implemented");
|
||||
return null;
|
||||
/* XXX Unsure whether this is the appropriate method to use, as it
|
||||
* triggers memoryRead monitor. Right now I'm using a flag to indicate
|
||||
* that Cooja (as opposed to Contiki) read the memory, to avoid infinite
|
||||
* recursion. */
|
||||
coojaIsAccessingMemory = true;
|
||||
byte[] data = new byte[(int) size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
data[i] = (byte) (interpreter.getDataByte((int) address + i) & 0xff);
|
||||
}
|
||||
coojaIsAccessingMemory = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMemorySegment(long address, byte[] data) throws MoteMemoryException {
|
||||
if (!accessInRange(address, data.length)) {
|
||||
throw new MoteMemoryException(
|
||||
"Writing memory segment [0x%x,0x%x] failed: Out of range",
|
||||
address, address + data.length - 1);
|
||||
}
|
||||
|
||||
public int getTotalSize() {
|
||||
return 0;
|
||||
/* XXX See comment in getMemorySegment. */
|
||||
coojaIsAccessingMemory = true;
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
interpreter.writeDataByte((int) address + i, data[i]);
|
||||
}
|
||||
coojaIsAccessingMemory = false;
|
||||
if (DEBUG) {
|
||||
logger.debug(String.format(
|
||||
"Wrote memory segment [0x%x,0x%x]",
|
||||
address, address + data.length - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearMemory() {
|
||||
setMemorySegment(0L, new byte[avrProperties.sram_size]);
|
||||
}
|
||||
|
||||
private boolean accessInRange(long address, int size) {
|
||||
return (address >= 0) && (address + size <= avrProperties.sram_size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartAddr() {
|
||||
return 0;// XXX
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Symbol> getSymbolMap() {
|
||||
// XXX do not fetch in function!
|
||||
Map<String, Symbol> symbols = new HashMap<>();
|
||||
for (Iterator<Location> iter = memoryMap.getIterator(); iter.hasNext();) {
|
||||
Location loc = iter.next();
|
||||
if (loc == null || (loc.section.equals(".text"))) {
|
||||
continue;
|
||||
}
|
||||
symbols.put(loc.name, new Symbol(Symbol.Type.VARIABLE, loc.name, loc.section, loc.vma_addr & 0x7fffff, -1));
|
||||
}
|
||||
return symbols;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MemoryLayout getLayout() {
|
||||
return memLayout;
|
||||
}
|
||||
|
||||
class AvrByteMonitor extends Watch.Empty {
|
||||
|
||||
/** start address to monitor */
|
||||
final long address;
|
||||
/** size to monitor */
|
||||
final int size;
|
||||
/** Segment monitor to notify */
|
||||
final SegmentMonitor mm;
|
||||
/** MonitorType we are listening to */
|
||||
final EventType flag;
|
||||
|
||||
public AvrByteMonitor(long address, int size, SegmentMonitor mm, EventType flag) {
|
||||
this.address = address;
|
||||
this.size = size;
|
||||
this.mm = mm;
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public void setMemorySegment(int address, byte[] data) {
|
||||
logger.fatal("setMemorySegment is not implemented");
|
||||
@Override
|
||||
public void fireAfterRead(State state, int data_addr, byte value) {
|
||||
if (flag == EventType.WRITE || coojaIsAccessingMemory) {
|
||||
return;
|
||||
}
|
||||
mm.memoryChanged(AvrMoteMemory.this, EventType.READ, data_addr);
|
||||
}
|
||||
|
||||
public byte[] getByteArray(String varName, int length)
|
||||
throws UnknownVariableException {
|
||||
return null;
|
||||
@Override
|
||||
public void fireAfterWrite(State state, int data_addr, byte value) {
|
||||
if (flag == EventType.READ || coojaIsAccessingMemory) {
|
||||
return;
|
||||
}
|
||||
mm.memoryChanged(AvrMoteMemory.this, EventType.WRITE, data_addr);
|
||||
}
|
||||
}
|
||||
|
||||
public byte getByteValueOf(String varName) throws UnknownVariableException {
|
||||
return (byte) getValueOf(varName, 1);
|
||||
@Override
|
||||
public boolean addSegmentMonitor(EventType flag, long address, int size, SegmentMonitor mm) {
|
||||
AvrByteMonitor mon = new AvrByteMonitor(address, size, mm, flag);
|
||||
|
||||
memoryMonitors.add(mon);
|
||||
/* logger.debug("Added AvrByteMonitor " + Integer.toString(mon.hashCode()) + " for addr " + mon.address + " size " + mon.size + " with watch" + mon.watch); */
|
||||
|
||||
/* Add byte monitor (watch) for every byte in range */
|
||||
for (int idx = 0; idx < mon.size; idx++) {
|
||||
interpreter.getSimulator().insertWatch(mon, (int) mon.address + idx);
|
||||
/* logger.debug("Inserted watch " + Integer.toString(mon.watch.hashCode()) + " for " + (mon.address + idx)); */
|
||||
}
|
||||
|
||||
private int getValueOf(String varName, int len) throws UnknownVariableException {
|
||||
Location mem = memoryMap.getLocation(varName);
|
||||
if (mem == null) throw new UnknownVariableException("Variable does not exist: " + varName);
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println("Variable:" + varName + " in section: " + mem.section);
|
||||
System.out.println("LMA: " + Integer.toHexString(mem.lma_addr));
|
||||
System.out.println("VMA: " + Integer.toHexString(mem.vma_addr));
|
||||
|
||||
System.out.println("Data: " + interpreter.getDataByte(mem.lma_addr & 0xfffff));
|
||||
System.out.println("Flash: " + interpreter.getFlashByte(mem.lma_addr & 0xfffff));
|
||||
int data = 0;
|
||||
if (mem.vma_addr > 0xfffff) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
data = (data << 8) + (interpreter.getDataByte((mem.vma_addr & 0xfffff) + len - i - 1) & 0xff);
|
||||
System.out.println("Read byte: " + interpreter.getDataByte((mem.vma_addr & 0xfffff) + i) +
|
||||
" => " + data);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
data = (data << 8) + interpreter.getFlashByte(mem.vma_addr + len - i - 1) & 0xff;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
@Override
|
||||
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor mm) {
|
||||
for (AvrByteMonitor mcm : memoryMonitors) {
|
||||
if (mcm.mm != mm || mcm.address != address || mcm.size != size) {
|
||||
continue;
|
||||
}
|
||||
for (int idx = 0; idx < mcm.size; idx++) {
|
||||
interpreter.getSimulator().removeWatch(mcm, (int) mcm.address + idx);
|
||||
/* logger.debug("Removed watch " + Integer.toString(mcm.watch.hashCode()) + " for " + (mcm.address + idx)); */
|
||||
}
|
||||
memoryMonitors.remove(mcm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setValue(String varName, int val, int len) throws UnknownVariableException {
|
||||
Location mem = memoryMap.getLocation(varName);
|
||||
if (mem == null) throw new UnknownVariableException("Variable does not exist: " + varName);
|
||||
|
||||
int data = val;
|
||||
if (mem.vma_addr > 0xfffff) {
|
||||
// write LSB first.
|
||||
for (int i = 0; i < len; i++) {
|
||||
interpreter.writeDataByte((mem.vma_addr & 0xfffff) + i, (byte) (data & 0xff));
|
||||
System.out.println("Wrote byte: " + (data & 0xff));
|
||||
data = data >> 8;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
interpreter.writeFlashByte(mem.vma_addr + i, (byte) (data & 0xff));
|
||||
data = data >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getIntValueOf(String varName) throws UnknownVariableException {
|
||||
return getValueOf(varName, 2);
|
||||
}
|
||||
|
||||
public int getIntegerLength() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int getVariableAddress(String varName)
|
||||
throws UnknownVariableException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String[] getVariableNames() {
|
||||
ArrayList<String> symbols = new ArrayList<String>();
|
||||
for (Iterator i = memoryMap.getIterator(); i.hasNext();) {
|
||||
symbols.add(((Location) i.next()).name);
|
||||
}
|
||||
return symbols.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public void setByteArray(String varName, byte[] data)
|
||||
throws UnknownVariableException {
|
||||
}
|
||||
|
||||
public void setByteValueOf(String varName, byte newVal)
|
||||
throws UnknownVariableException {
|
||||
setValue(varName, newVal, 1);
|
||||
}
|
||||
|
||||
public void setIntValueOf(String varName, int newVal)
|
||||
throws UnknownVariableException {
|
||||
setValue(varName, newVal, 2);
|
||||
}
|
||||
|
||||
public boolean variableExists(String varName) {
|
||||
return memoryMap.getLocation(varName) != null;
|
||||
}
|
||||
|
||||
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) {
|
||||
logger.warn("Not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) {
|
||||
}
|
||||
|
||||
public int parseInt(byte[] memorySegment) {
|
||||
logger.warn("Not implemented");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteInterface;
|
||||
import org.contikios.cooja.MoteInterfaceHandler;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.MoteType;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.motes.AbstractEmulatedMote;
|
||||
import avrora.arch.avr.AVRProperties;
|
||||
import avrora.core.LoadableProgram;
|
||||
|
@ -264,11 +264,12 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote {
|
|||
return config;
|
||||
}
|
||||
|
||||
public MoteMemory getMemory() {
|
||||
@Override
|
||||
public MemoryInterface getMemory() {
|
||||
return myMemory;
|
||||
}
|
||||
|
||||
public void setMemory(MoteMemory memory) {
|
||||
public void setMemory(AvrMoteMemory memory) {
|
||||
myMemory = (AvrMoteMemory) memory;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,16 +38,15 @@ import javax.swing.JPanel;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import avrora.sim.State;
|
||||
import avrora.sim.Simulator.Watch;
|
||||
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteTimeEvent;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.TimeEvent;
|
||||
import org.contikios.cooja.avrmote.AvrMoteMemory;
|
||||
import org.contikios.cooja.avrmote.MicaZMote;
|
||||
import org.contikios.cooja.interfaces.MoteID;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
public class MicaZID extends MoteID {
|
||||
|
||||
|
@ -57,7 +56,7 @@ public class MicaZID extends MoteID {
|
|||
|
||||
private int moteID = -1; /* TODO Implement */
|
||||
|
||||
private AvrMoteMemory moteMem;
|
||||
private VarMemory moteMem;
|
||||
boolean tosID = false;
|
||||
boolean contikiID = false;
|
||||
private MicaZMote mote;
|
||||
|
@ -80,23 +79,26 @@ public class MicaZID extends MoteID {
|
|||
|
||||
public MicaZID(Mote mote) {
|
||||
this.mote = (MicaZMote) mote;
|
||||
this.moteMem = (AvrMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
|
||||
if (moteMem.variableExists("node_id")) {
|
||||
contikiID = true;
|
||||
|
||||
int addr = moteMem.getVariableAddress("node_id");
|
||||
moteMem.insertWatch(new Watch() {
|
||||
public void fireAfterRead(State arg0, int arg1, byte arg2) {
|
||||
System.out.println("Read from node_id: " + arg2);
|
||||
int addr = (int) moteMem.getVariableAddress("node_id");
|
||||
moteMem.addVarMonitor(
|
||||
SegmentMonitor.EventType.READWRITE,
|
||||
"node_id",
|
||||
new SegmentMonitor() {
|
||||
|
||||
@Override
|
||||
public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
|
||||
if (type == EventType.READ) {
|
||||
System.out.println("Read from node_id.");
|
||||
} else {
|
||||
System.out.println("Writing to node_id.");
|
||||
}
|
||||
}
|
||||
public void fireAfterWrite(State arg0, int arg1, byte arg2) {
|
||||
}
|
||||
public void fireBeforeRead(State arg0, int arg1) {
|
||||
}
|
||||
public void fireBeforeWrite(State arg0, int arg1, byte arg2) {
|
||||
System.out.println("Writing to node_id: " + arg2);
|
||||
}}, addr);
|
||||
});
|
||||
}
|
||||
|
||||
if (moteMem.variableExists("TOS_NODE_ID")) {
|
||||
|
|
|
@ -45,12 +45,12 @@ import org.contikios.cooja.Cooja;
|
|||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteInterface;
|
||||
import org.contikios.cooja.MoteInterfaceHandler;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.MoteType;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.Watchpoint;
|
||||
import org.contikios.cooja.WatchpointMote;
|
||||
import org.contikios.cooja.interfaces.IPAddress;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.motes.AbstractEmulatedMote;
|
||||
import org.contikios.cooja.mspmote.interfaces.Msp802154Radio;
|
||||
import org.contikios.cooja.mspmote.interfaces.MspSerial;
|
||||
|
@ -185,12 +185,13 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
myCpu = cpu;
|
||||
}
|
||||
|
||||
public MoteMemory getMemory() {
|
||||
@Override
|
||||
public MemoryInterface getMemory() {
|
||||
return myMemory;
|
||||
}
|
||||
|
||||
public void setMemory(MoteMemory memory) {
|
||||
myMemory = (MspMoteMemory) memory;
|
||||
public void setMemory(MspMoteMemory memory) {
|
||||
myMemory = memory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig. All rights reserved.
|
||||
* Copyright (c) 2007, Swedish Institute of Computer Science. All rights
|
||||
* reserved.
|
||||
*
|
||||
|
@ -28,21 +29,27 @@
|
|||
|
||||
package org.contikios.cooja.mspmote;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.contikios.cooja.AddressMemory;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor.EventType;
|
||||
import org.contikios.cooja.mote.memory.MemoryLayout;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
import se.sics.mspsim.core.Memory.AccessMode;
|
||||
import se.sics.mspsim.core.Memory.AccessType;
|
||||
import se.sics.mspsim.util.MapEntry;
|
||||
|
||||
public class MspMoteMemory implements MoteMemory, AddressMemory {
|
||||
public class MspMoteMemory implements MemoryInterface {
|
||||
private static Logger logger = Logger.getLogger(MspMoteMemory.class);
|
||||
private final ArrayList<MapEntry> mapEntries;
|
||||
private final MemoryLayout memLayout;
|
||||
|
||||
private final MSP430 cpu;
|
||||
|
||||
|
@ -56,143 +63,85 @@ public class MspMoteMemory implements MoteMemory, AddressMemory {
|
|||
}
|
||||
|
||||
this.cpu = cpu;
|
||||
memLayout = new MemoryLayout(ByteOrder.LITTLE_ENDIAN, MemoryLayout.ARCH_16BIT, 2);
|
||||
}
|
||||
|
||||
public String[] getVariableNames() {
|
||||
String[] names = new String[mapEntries.size()];
|
||||
for (int i = 0; i < mapEntries.size(); i++) {
|
||||
names[i] = mapEntries.get(i).getName();
|
||||
}
|
||||
return names;
|
||||
@Override
|
||||
public int getTotalSize() {
|
||||
return cpu.memory.length;
|
||||
}
|
||||
|
||||
private MapEntry getMapEntry(String varName) throws UnknownVariableException {
|
||||
for (MapEntry entry: mapEntries) {
|
||||
if (entry.getName().equals(varName)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
throw new UnknownVariableException(varName);
|
||||
@Override
|
||||
public byte[] getMemory() throws MoteMemoryException {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
public int getVariableAddress(String varName) throws UnknownVariableException {
|
||||
MapEntry entry = getMapEntry(varName);
|
||||
return entry.getAddress();
|
||||
}
|
||||
|
||||
public int getIntegerLength() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public void clearMemory() {
|
||||
logger.fatal("clearMemory() not implemented");
|
||||
}
|
||||
|
||||
public byte[] getMemorySegment(int address, int size) {
|
||||
@Override
|
||||
public byte[] getMemorySegment(long address, int size) {
|
||||
int[] memInts = new int[size];
|
||||
|
||||
System.arraycopy(cpu.memory, address, memInts, 0, size);
|
||||
System.arraycopy(cpu.memory, (int) address, memInts, 0, size);
|
||||
|
||||
/* Convert to byte array */
|
||||
byte[] memBytes = new byte[size];
|
||||
for (int i=0; i < size; i++) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
memBytes[i] = (byte) memInts[i];
|
||||
}
|
||||
|
||||
return memBytes;
|
||||
}
|
||||
|
||||
public void setMemorySegment(int address, byte[] data) {
|
||||
@Override
|
||||
public void setMemorySegment(long address, byte[] data) {
|
||||
/* Convert to int array */
|
||||
int[] memInts = new int[data.length];
|
||||
for (int i=0; i < data.length; i++) {
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
memInts[i] = data[i];
|
||||
}
|
||||
|
||||
System.arraycopy(memInts, 0, cpu.memory, address, data.length);
|
||||
System.arraycopy(memInts, 0, cpu.memory, (int) address, data.length);
|
||||
}
|
||||
|
||||
public int getTotalSize() {
|
||||
return cpu.memory.length;
|
||||
@Override
|
||||
public void clearMemory() {
|
||||
Arrays.fill(cpu.memory, 0);
|
||||
}
|
||||
|
||||
public boolean variableExists(String varName) {
|
||||
for (MapEntry entry: mapEntries) {
|
||||
if (entry.getName().equals(varName)) {
|
||||
return true;
|
||||
@Override
|
||||
public long getStartAddr() {
|
||||
return 0;// XXXX
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Symbol> getSymbolMap() {
|
||||
Map<String, Symbol> vars = new HashMap<>();
|
||||
for (MapEntry entry : mapEntries) {
|
||||
if (entry.getType() != MapEntry.TYPE.variable) {
|
||||
continue;
|
||||
}
|
||||
vars.put(entry.getName(), new Symbol(
|
||||
Symbol.Type.VARIABLE,
|
||||
entry.getName(),
|
||||
entry.getAddress(),
|
||||
entry.getSize()));
|
||||
}
|
||||
|
||||
return false;
|
||||
return vars;
|
||||
}
|
||||
|
||||
/* TODO Check correct variable size in below methods */
|
||||
|
||||
public int getIntValueOf(String varName) throws UnknownVariableException {
|
||||
MapEntry entry = getMapEntry(varName);
|
||||
|
||||
int varAddr = entry.getAddress();
|
||||
byte[] varData = getMemorySegment(varAddr, 2);
|
||||
return parseInt(varData);
|
||||
@Override
|
||||
public MemoryLayout getLayout() {
|
||||
return memLayout;
|
||||
}
|
||||
|
||||
public void setIntValueOf(String varName, int newVal) throws UnknownVariableException {
|
||||
MapEntry entry = getMapEntry(varName);
|
||||
int varAddr = entry.getAddress();
|
||||
private final ArrayList<MemoryCPUMonitor> cpuMonitorArray = new ArrayList<>();
|
||||
|
||||
int newValToSet = Integer.reverseBytes(newVal);
|
||||
|
||||
// Create byte array
|
||||
int pos = 0;
|
||||
|
||||
byte[] varData = new byte[2];
|
||||
varData[pos++] = (byte) ((newValToSet & 0xFF000000) >> 24);
|
||||
varData[pos++] = (byte) ((newValToSet & 0xFF0000) >> 16);
|
||||
|
||||
setMemorySegment(varAddr, varData);
|
||||
}
|
||||
|
||||
public byte getByteValueOf(String varName) throws UnknownVariableException {
|
||||
MapEntry entry = getMapEntry(varName);
|
||||
int varAddr = entry.getAddress();
|
||||
|
||||
byte[] varData = getMemorySegment(varAddr, 1);
|
||||
|
||||
return varData[0];
|
||||
}
|
||||
|
||||
public void setByteValueOf(String varName, byte newVal) throws UnknownVariableException {
|
||||
MapEntry entry = getMapEntry(varName);
|
||||
int varAddr = entry.getAddress();
|
||||
|
||||
byte[] varData = new byte[1];
|
||||
|
||||
varData[0] = newVal;
|
||||
|
||||
setMemorySegment(varAddr, varData);
|
||||
}
|
||||
|
||||
public byte[] getByteArray(String varName, int length) throws UnknownVariableException {
|
||||
MapEntry entry = getMapEntry(varName);
|
||||
int varAddr = entry.getAddress();
|
||||
|
||||
return getMemorySegment(varAddr, length);
|
||||
}
|
||||
|
||||
public void setByteArray(String varName, byte[] data) throws UnknownVariableException {
|
||||
MapEntry entry = getMapEntry(varName);
|
||||
int varAddr = entry.getAddress();
|
||||
|
||||
setMemorySegment(varAddr, data);
|
||||
}
|
||||
|
||||
private ArrayList<MemoryCPUMonitor> cpuMonitorArray = new ArrayList<MemoryCPUMonitor>();
|
||||
class MemoryCPUMonitor extends se.sics.mspsim.core.MemoryMonitor.Adapter {
|
||||
public final MemoryMonitor mm;
|
||||
|
||||
public final SegmentMonitor mm;
|
||||
public final int address;
|
||||
public final int size;
|
||||
|
||||
public MemoryCPUMonitor(MemoryMonitor mm, int address, int size) {
|
||||
public MemoryCPUMonitor(SegmentMonitor mm, int address, int size) {
|
||||
this.mm = mm;
|
||||
this.address = address;
|
||||
this.size = size;
|
||||
|
@ -200,49 +149,39 @@ public class MspMoteMemory implements MoteMemory, AddressMemory {
|
|||
|
||||
@Override
|
||||
public void notifyReadAfter(int address, AccessMode mode, AccessType type) {
|
||||
mm.memoryChanged(MspMoteMemory.this, MemoryEventType.READ, address);
|
||||
mm.memoryChanged(MspMoteMemory.this, EventType.READ, address);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyWriteAfter(int dstAddress, int data, AccessMode mode) {
|
||||
mm.memoryChanged(MspMoteMemory.this, MemoryEventType.WRITE, dstAddress);
|
||||
mm.memoryChanged(MspMoteMemory.this, EventType.WRITE, dstAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) {
|
||||
MemoryCPUMonitor t = new MemoryCPUMonitor(mm, address, size);
|
||||
@Override
|
||||
public boolean addSegmentMonitor(EventType type, long address, int size, SegmentMonitor mm) {
|
||||
MemoryCPUMonitor t = new MemoryCPUMonitor(mm, (int) address, size);
|
||||
cpuMonitorArray.add(t);
|
||||
|
||||
for (int a = address; a < address+size; a++) {
|
||||
for (int a = (int) address; a < address + size; a++) {
|
||||
cpu.addWatchPoint(a, t);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) {
|
||||
for (MemoryCPUMonitor mcm: cpuMonitorArray) {
|
||||
@Override
|
||||
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor mm) {
|
||||
for (MemoryCPUMonitor mcm : cpuMonitorArray) {
|
||||
if (mcm.mm != mm || mcm.address != address || mcm.size != size) {
|
||||
continue;
|
||||
}
|
||||
for (int a = address; a < address+size; a++) {
|
||||
for (int a = (int) address; a < (int) address + size; a++) {
|
||||
cpu.removeWatchPoint(a, mcm);
|
||||
}
|
||||
cpuMonitorArray.remove(mcm);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int parseInt(byte[] memorySegment) {
|
||||
if (memorySegment.length < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int retVal = 0;
|
||||
int pos = 0;
|
||||
retVal += ((memorySegment[pos++] & 0xFF)) << 8;
|
||||
retVal += ((memorySegment[pos++] & 0xFF)) << 0;
|
||||
|
||||
return Integer.reverseBytes(retVal) >> 16;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,9 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.ClassDescription;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.interfaces.Log;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
import org.contikios.cooja.mspmote.MspMote;
|
||||
import org.contikios.cooja.mspmote.MspMoteMemory;
|
||||
import se.sics.mspsim.core.Memory;
|
||||
import se.sics.mspsim.core.MemoryMonitor;
|
||||
|
||||
|
@ -64,24 +65,24 @@ public class MspDebugOutput extends Log {
|
|||
private final static String CONTIKI_POINTER = "cooja_debug_ptr";
|
||||
|
||||
private MspMote mote;
|
||||
private MspMoteMemory mem;
|
||||
private VarMemory mem;
|
||||
|
||||
private String lastLog = null;
|
||||
private MemoryMonitor memoryMonitor = null;
|
||||
|
||||
public MspDebugOutput(Mote mote) {
|
||||
this.mote = (MspMote) mote;
|
||||
this.mem = (MspMoteMemory) this.mote.getMemory();
|
||||
this.mem = new VarMemory(this.mote.getMemory());
|
||||
|
||||
if (!mem.variableExists(CONTIKI_POINTER)) {
|
||||
/* Disabled */
|
||||
return;
|
||||
}
|
||||
this.mote.getCPU().addWatchPoint(mem.getVariableAddress(CONTIKI_POINTER),
|
||||
this.mote.getCPU().addWatchPoint((int) mem.getVariableAddress(CONTIKI_POINTER),
|
||||
memoryMonitor = new MemoryMonitor.Adapter() {
|
||||
@Override
|
||||
public void notifyWriteAfter(int adr, int data, Memory.AccessMode mode) {
|
||||
String msg = extractString(mem, data);
|
||||
String msg = extractString(MspDebugOutput.this.mote.getMemory(), data);
|
||||
if (msg != null && msg.length() > 0) {
|
||||
lastLog = "DEBUG: " + msg;
|
||||
setChanged();
|
||||
|
@ -91,7 +92,7 @@ public class MspDebugOutput extends Log {
|
|||
});
|
||||
}
|
||||
|
||||
private String extractString(MspMoteMemory mem, int address) {
|
||||
private String extractString(MemoryInterface mem, int address) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (true) {
|
||||
byte[] data = mem.getMemorySegment(address, 8);
|
||||
|
@ -136,7 +137,7 @@ public class MspDebugOutput extends Log {
|
|||
super.removed();
|
||||
|
||||
if (memoryMonitor != null) {
|
||||
mote.getCPU().removeWatchPoint(mem.getVariableAddress(CONTIKI_POINTER), memoryMonitor);
|
||||
mote.getCPU().removeWatchPoint((int) mem.getVariableAddress(CONTIKI_POINTER), memoryMonitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ import org.apache.log4j.Logger;
|
|||
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.interfaces.MoteID;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
import org.contikios.cooja.mspmote.MspMote;
|
||||
import org.contikios.cooja.mspmote.MspMoteMemory;
|
||||
import se.sics.mspsim.core.Memory;
|
||||
import se.sics.mspsim.core.MemoryMonitor;
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class MspMoteID extends MoteID {
|
|||
private static Logger logger = Logger.getLogger(MspMoteID.class);
|
||||
|
||||
private MspMote mote;
|
||||
private MspMoteMemory moteMem = null;
|
||||
private VarMemory moteMem = null;
|
||||
|
||||
private boolean writeFlashHeader = true;
|
||||
private int moteID = -1;
|
||||
|
@ -69,7 +69,7 @@ public class MspMoteID extends MoteID {
|
|||
*/
|
||||
public MspMoteID(Mote m) {
|
||||
this.mote = (MspMote) m;
|
||||
this.moteMem = (MspMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public int getMoteID() {
|
||||
|
@ -144,7 +144,7 @@ public class MspMoteID extends MoteID {
|
|||
byte[] id = new byte[2];
|
||||
id[0] = (byte) (moteID & 0xff);
|
||||
id[1] = (byte) ((moteID >> 8) & 0xff);
|
||||
moteMem.setMemorySegment(dstAddress & ~1, id);
|
||||
mote.getMemory().setMemorySegment(dstAddress & ~1, id);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -201,7 +201,7 @@ public class MspMoteID extends MoteID {
|
|||
|
||||
private void addMonitor(String variable, MemoryMonitor monitor) {
|
||||
if (moteMem.variableExists(variable)) {
|
||||
int address = moteMem.getVariableAddress(variable);
|
||||
int address = (int) moteMem.getVariableAddress(variable);
|
||||
if ((address & 1) != 0) {
|
||||
// Variable can not be a word - must be a byte
|
||||
} else {
|
||||
|
@ -213,7 +213,7 @@ public class MspMoteID extends MoteID {
|
|||
|
||||
private void removeMonitor(String variable, MemoryMonitor monitor) {
|
||||
if (moteMem.variableExists(variable)) {
|
||||
int address = moteMem.getVariableAddress(variable);
|
||||
int address = (int) moteMem.getVariableAddress(variable);
|
||||
mote.getCPU().removeWatchPoint(address, monitor);
|
||||
mote.getCPU().removeWatchPoint(address + 1, monitor);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ PATH_JAVAC = javac
|
|||
DEFAULT_PROJECTDIRS = [CONTIKI_DIR]/tools/cooja/apps/mrm;[CONTIKI_DIR]/tools/cooja/apps/mspsim;[CONTIKI_DIR]/tools/cooja/apps/avrora;[CONTIKI_DIR]/tools/cooja/apps/serial_socket;[CONTIKI_DIR]/tools/cooja/apps/collect-view;[CONTIKI_DIR]/tools/cooja/apps/powertracker
|
||||
|
||||
PARSE_WITH_COMMAND=false
|
||||
PARSE_COMMAND=nm -a $(LIBFILE)
|
||||
MAPFILE_DATA_START = ^.data[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$
|
||||
MAPFILE_DATA_SIZE = ^.data[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$
|
||||
MAPFILE_BSS_START = ^.bss[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$
|
||||
|
@ -35,11 +34,19 @@ MAPFILE_VAR_ADDRESS_1 = ^[ \t]*0x([0-9A-Fa-f]*)[ \t]*
|
|||
MAPFILE_VAR_ADDRESS_2 = [ \t]*$
|
||||
MAPFILE_VAR_SIZE_1 = ^
|
||||
MAPFILE_VAR_SIZE_2 = [ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$
|
||||
COMMAND_VAR_NAME_ADDRESS = ^([0-9A-Fa-f][0-9A-Fa-f]*)[ \t][^Tt][ \t]([^ ._][^ ]*)
|
||||
COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]d[ \t].data$
|
||||
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_edata$
|
||||
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]A[ \t]__bss_start$
|
||||
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_end$
|
||||
|
||||
PARSE_COMMAND=nm -aP $(LIBFILE)
|
||||
COMMAND_VAR_NAME_ADDRESS_SIZE = ^([^.].*?) <SECTION> ([0-9a-fA-F]+) ([0-9a-fA-F])*
|
||||
COMMAND_VAR_SEC_DATA = [DdGg]
|
||||
COMMAND_VAR_SEC_BSS = [Bb]
|
||||
COMMAND_VAR_SEC_COMMON = [C]
|
||||
COMMAND_VAR_SEC_READONLY = [Rr]
|
||||
COMMAND_DATA_START = ^.data[ \t]d[ \t]([0-9A-Fa-f]*)[ \t]*$
|
||||
COMMAND_DATA_END = ^_edata[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
|
||||
COMMAND_BSS_START = ^__bss_start[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
|
||||
COMMAND_BSS_END = ^_end[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
|
||||
COMMAND_READONLY_START = ^.rodata[ \t]r[ \t]([0-9A-Fa-f]*)[ \t]*$
|
||||
COMMAND_READONLY_END = ^.eh_frame_hdr[ \t]r[ \t]([0-9A-Fa-f]*)[ \t]*$
|
||||
|
||||
VISUALIZER_DEFAULT_SKINS=\
|
||||
org.contikios.cooja.plugins.skins.IDVisualizerSkin;\
|
||||
|
|
|
@ -6,8 +6,14 @@ COMPILER_ARGS=-D__int64\="long long" -Wall -I'$(JAVA_HOME)/include' -I'$(JAVA_HO
|
|||
LINK_COMMAND_1 = mingw32-gcc -shared -Wl,-Map=$(MAPFILE) -Wl,--add-stdcall-alias -o $(LIBFILE)
|
||||
LINK_COMMAND_2 = -L/usr/lib/mingw
|
||||
PARSE_WITH_COMMAND = true
|
||||
PARSE_COMMAND=nm -n -C $(LIBFILE)
|
||||
COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_start__$
|
||||
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_end__$
|
||||
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_start__$
|
||||
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_end__$
|
||||
|
||||
# Hack: nm with arguments -S --size-sort does not display __data_start symbols
|
||||
PARSE_COMMAND=sh -c "/bin/nm -aP --size-sort -S $(LIBFILE) && /bin/nm -aP $(LIBFILE)"
|
||||
|
||||
COMMAND_VAR_NAME_ADDRESS_SIZE = ^[_]([^.].*?)[ \t]<SECTION>[ \t]([0-9a-fA-F]+)[ \t]([0-9a-fA-F]+)
|
||||
COMMAND_DATA_START = ^__data_start__[ \t]D[ \t]([0-9A-Fa-f]*)
|
||||
COMMAND_DATA_END = ^__data_end__[ \t]D[ \t]([0-9A-Fa-f]*)
|
||||
COMMAND_BSS_START = ^__bss_start__[ \t]B[ \t]([0-9A-Fa-f]*)
|
||||
COMMAND_BSS_END = ^__bss_end__[ \t]B[ \t]([0-9A-Fa-f]*)
|
||||
COMMAND_READONLY_START = ^.rodata[ \t]r[ \t]([0-9A-Fa-f]*)
|
||||
COMMAND_READONLY_END = ^.eh_frame_hdr[ \t]r[ \t]([0-9A-Fa-f]*)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</appender>
|
||||
|
||||
<root>
|
||||
<priority value="debug"/>
|
||||
<priority value="info"/>
|
||||
<appender-ref ref="logfile"/>
|
||||
<appender-ref ref="stdout"/>
|
||||
</root>
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.contikios.cooja;
|
||||
|
||||
public interface AddressMemory {
|
||||
|
||||
/**
|
||||
* @return All variable names known and residing in this memory
|
||||
*/
|
||||
public String[] getVariableNames();
|
||||
|
||||
/**
|
||||
* Checks if given variable exists in memory.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return True if variable exists, false otherwise
|
||||
*/
|
||||
public boolean variableExists(String varName);
|
||||
|
||||
/**
|
||||
* Returns address of variable with given name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return Variable address
|
||||
* @throws UnknownVariableException Variable does not exist
|
||||
*/
|
||||
public int getVariableAddress(String varName) throws UnknownVariableException;
|
||||
|
||||
/**
|
||||
* Returns a value of the byte variable with the given name.
|
||||
*
|
||||
* @param varName Name of byte variable
|
||||
* @return Value of byte variable
|
||||
* @throws UnknownVariableException Variable does not exist
|
||||
*/
|
||||
public byte getByteValueOf(String varName) throws UnknownVariableException;
|
||||
|
||||
/**
|
||||
* Set byte value of variable with given name.
|
||||
*
|
||||
* @param varName Name of byte variable
|
||||
* @param newVal New value of byte
|
||||
* @throws UnknownVariableException Variable does not exist
|
||||
*/
|
||||
public void setByteValueOf(String varName, byte newVal) throws UnknownVariableException;
|
||||
|
||||
/**
|
||||
* Returns byte array of given length and with the given name.
|
||||
*
|
||||
* @param varName Name of array
|
||||
* @param length Length of array
|
||||
* @return Data of array
|
||||
* @throws UnknownVariableException Variable does not exist
|
||||
*/
|
||||
public byte[] getByteArray(String varName, int length) throws UnknownVariableException;
|
||||
|
||||
/**
|
||||
* Set byte array of the variable with the given name.
|
||||
*
|
||||
* @param varName Name of array
|
||||
* @param data New data of array
|
||||
* @throws UnknownVariableException Variable does not exist
|
||||
*/
|
||||
public void setByteArray(String varName, byte[] data) throws UnknownVariableException;
|
||||
|
||||
/**
|
||||
* @return Number of bytes in an integer
|
||||
*/
|
||||
public int getIntegerLength();
|
||||
|
||||
/**
|
||||
* Returns a value of the integer variable with the given name.
|
||||
*
|
||||
* @param varName Name of integer variable
|
||||
* @return Value of integer variable
|
||||
* @throws UnknownVariableException Variable does not exist
|
||||
*/
|
||||
public int getIntValueOf(String varName) throws UnknownVariableException;
|
||||
|
||||
/**
|
||||
* Set integer value of variable with given name.
|
||||
*
|
||||
* @param varName Name of integer variable
|
||||
* @param newVal New integer value
|
||||
* @throws UnknownVariableException Variable does not exist
|
||||
*/
|
||||
public void setIntValueOf(String varName, int newVal) throws UnknownVariableException;
|
||||
|
||||
/**
|
||||
* Unknown variable name exception.
|
||||
*/
|
||||
public class UnknownVariableException extends RuntimeException {
|
||||
public UnknownVariableException(String varName) {
|
||||
super("Unknown variable name: " + varName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -274,7 +274,7 @@ public class Cooja extends Observable {
|
|||
"MAPFILE_VAR_SIZE_1", "MAPFILE_VAR_SIZE_2",
|
||||
|
||||
"PARSE_COMMAND",
|
||||
"COMMAND_VAR_NAME_ADDRESS",
|
||||
"COMMAND_VAR_NAME_ADDRESS_SIZE",
|
||||
"COMMAND_DATA_START", "COMMAND_DATA_END",
|
||||
"COMMAND_BSS_START", "COMMAND_BSS_END",
|
||||
"COMMAND_COMMON_START", "COMMAND_COMMON_END",
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
package org.contikios.cooja;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
@ -63,7 +64,7 @@ public interface Mote {
|
|||
* @see #setMemory(MoteMemory)
|
||||
* @return Mote memory
|
||||
*/
|
||||
public MoteMemory getMemory();
|
||||
public MemoryInterface getMemory();
|
||||
|
||||
/**
|
||||
* Returns mote type.
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.contikios.cooja;
|
||||
|
||||
|
||||
/**
|
||||
* This interface represents a mote memory.
|
||||
*
|
||||
* Mote memory is represented by byte arrays and this
|
||||
* interface provides a few of basic operations.
|
||||
*
|
||||
* Note that this memory internally may consist of several
|
||||
* different memory sections, not covering the entire range
|
||||
* between the start address and the end address of this memory.
|
||||
*
|
||||
* @see org.contikios.cooja.SectionMoteMemory
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public interface MoteMemory extends AddressMemory {
|
||||
|
||||
/**
|
||||
* Clears the entire memory.
|
||||
*/
|
||||
public void clearMemory();
|
||||
|
||||
/**
|
||||
* Returns a memory segment.
|
||||
*
|
||||
* @param address Start address of memory segment
|
||||
* @param size Size of memory segment
|
||||
* @return Memory segment or null if segment not available
|
||||
*/
|
||||
public byte[] getMemorySegment(int address, int size);
|
||||
|
||||
/**
|
||||
* Sets a memory segment.
|
||||
*
|
||||
* @param address Start address of memory segment
|
||||
* @param data Data
|
||||
*/
|
||||
public void setMemorySegment(int address, byte[] data);
|
||||
|
||||
/**
|
||||
* Returns the sum of all byte array sizes in this memory.
|
||||
* This is not neccessarily the the same as the total memory range,
|
||||
* since the entire memory range may not be handled by this memory.
|
||||
*
|
||||
* @return Total size
|
||||
*/
|
||||
public int getTotalSize();
|
||||
|
||||
public abstract int parseInt(byte[] memorySegment);
|
||||
|
||||
public enum MemoryEventType { READ, WRITE };
|
||||
|
||||
public interface MemoryMonitor {
|
||||
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address);
|
||||
}
|
||||
|
||||
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm);
|
||||
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm);
|
||||
}
|
|
@ -1,431 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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.
|
||||
*/
|
||||
|
||||
package org.contikios.cooja;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Represents a mote memory consisting of non-overlapping memory sections with
|
||||
* symbol addresses.
|
||||
* <p>
|
||||
* When an non-existing memory segment is written, a new section is automatically
|
||||
* created for this segment.
|
||||
* <p>
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public class SectionMoteMemory implements MoteMemory, AddressMemory {
|
||||
private static Logger logger = Logger.getLogger(SectionMoteMemory.class);
|
||||
|
||||
private ArrayList<MoteMemorySection> sections = new ArrayList<MoteMemorySection>();
|
||||
|
||||
/* readonly memory is never written to Contiki core, and is used to provide
|
||||
* access to, for instance, strings */
|
||||
private ArrayList<MoteMemorySection> readonlySections = new ArrayList<MoteMemorySection>();
|
||||
|
||||
private final HashMap<String, Integer> addresses;
|
||||
|
||||
/* used to map Cooja's address space to native (Contiki's) addresses */
|
||||
private final int offset;
|
||||
|
||||
/**
|
||||
* @param addresses Symbol addresses
|
||||
* @param offset Offset for internally used addresses
|
||||
*/
|
||||
public SectionMoteMemory(HashMap<String, Integer> addresses, int offset) {
|
||||
this.addresses = addresses;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public String[] getVariableNames() {
|
||||
return addresses.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
public int getVariableAddress(String varName) throws UnknownVariableException {
|
||||
/* Cooja address space */
|
||||
if (!addresses.containsKey(varName)) {
|
||||
throw new UnknownVariableException(varName);
|
||||
}
|
||||
|
||||
return addresses.get(varName).intValue() + offset;
|
||||
}
|
||||
|
||||
public int getIntegerLength() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public void clearMemory() {
|
||||
sections.clear();
|
||||
}
|
||||
|
||||
public byte[] getMemorySegment(int address, int size) {
|
||||
/* Cooja address space */
|
||||
address -= offset;
|
||||
|
||||
for (MoteMemorySection section : sections) {
|
||||
if (section.includesAddr(address)
|
||||
&& section.includesAddr(address + size - 1)) {
|
||||
return section.getMemorySegment(address, size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if in readonly section */
|
||||
for (MoteMemorySection section : readonlySections) {
|
||||
if (section.includesAddr(address)
|
||||
&& section.includesAddr(address + size - 1)) {
|
||||
return section.getMemorySegment(address, size);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setMemorySegmentNative(int address, byte[] data) {
|
||||
setMemorySegment(address+offset, data);
|
||||
}
|
||||
|
||||
public void setMemorySegment(int address, byte[] data) {
|
||||
/* Cooja address space */
|
||||
address -= offset;
|
||||
|
||||
/* TODO XXX Sections may overlap */
|
||||
for (MoteMemorySection section : sections) {
|
||||
if (section.includesAddr(address)
|
||||
&& section.includesAddr(address + data.length - 1)) {
|
||||
section.setMemorySegment(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
sections.add(new MoteMemorySection(address, data));
|
||||
}
|
||||
|
||||
public void setReadonlyMemorySegment(int address, byte[] data) {
|
||||
/* Cooja address space */
|
||||
address -= offset;
|
||||
|
||||
readonlySections.add(new MoteMemorySection(address, data));
|
||||
}
|
||||
|
||||
public int getTotalSize() {
|
||||
int totalSize = 0;
|
||||
for (MoteMemorySection section : sections) {
|
||||
totalSize += section.getSize();
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of sections in this memory.
|
||||
*
|
||||
* @return Number of sections
|
||||
*/
|
||||
public int getNumberOfSections() {
|
||||
return sections.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get start address of given section in native address space.
|
||||
*
|
||||
* @param sectionNr Section position
|
||||
* @return Start address of section
|
||||
*/
|
||||
public int getSectionNativeAddress(int sectionNr) {
|
||||
if (sectionNr >= sections.size()) {
|
||||
return -1;
|
||||
}
|
||||
return sections.get(sectionNr).getStartAddr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of section at given position.
|
||||
*
|
||||
* @param sectionNr Section position
|
||||
* @return Size of section
|
||||
*/
|
||||
public int getSizeOfSection(int sectionNr) {
|
||||
if (sectionNr >= sections.size()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sections.get(sectionNr).getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data of section at given position.
|
||||
*
|
||||
* @param sectionNr Section position
|
||||
* @return Data at section
|
||||
*/
|
||||
public byte[] getDataOfSection(int sectionNr) {
|
||||
if (sectionNr >= sections.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return sections.get(sectionNr).getData();
|
||||
}
|
||||
|
||||
public boolean variableExists(String varName) {
|
||||
return addresses.containsKey(varName);
|
||||
}
|
||||
|
||||
public int getIntValueOf(String varName) throws UnknownVariableException {
|
||||
int varAddr = getVariableAddress(varName);
|
||||
byte[] varData = getMemorySegment(varAddr, 4);
|
||||
|
||||
if (varData == null) {
|
||||
throw new UnknownVariableException(varName);
|
||||
}
|
||||
|
||||
return parseInt(varData);
|
||||
}
|
||||
|
||||
public void setIntValueOf(String varName, int newVal) throws UnknownVariableException {
|
||||
int varAddr = getVariableAddress(varName);
|
||||
|
||||
/* TODO Correct for all platforms? */
|
||||
int newValToSet = Integer.reverseBytes(newVal);
|
||||
|
||||
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) throws UnknownVariableException {
|
||||
int varAddr = getVariableAddress(varName);
|
||||
byte[] varData = getMemorySegment(varAddr, 1);
|
||||
|
||||
if (varData == null) {
|
||||
throw new UnknownVariableException(varName);
|
||||
}
|
||||
|
||||
return varData[0];
|
||||
}
|
||||
|
||||
public void setByteValueOf(String varName, byte newVal) throws UnknownVariableException {
|
||||
int varAddr = getVariableAddress(varName);
|
||||
byte[] varData = new byte[1];
|
||||
|
||||
varData[0] = newVal;
|
||||
|
||||
setMemorySegment(varAddr, varData);
|
||||
}
|
||||
|
||||
public byte[] getByteArray(String varName, int length) throws UnknownVariableException {
|
||||
int varAddr = getVariableAddress(varName);
|
||||
return getMemorySegment(varAddr, length);
|
||||
}
|
||||
|
||||
public void setByteArray(String varName, byte[] data) throws UnknownVariableException {
|
||||
int varAddr = getVariableAddress(varName);
|
||||
setMemorySegment(varAddr, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* A memory section contains a byte array and a start address.
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
private static class MoteMemorySection {
|
||||
private byte[] data = null;
|
||||
private final int startAddr;
|
||||
|
||||
/**
|
||||
* Create a new memory section.
|
||||
*
|
||||
* @param startAddr
|
||||
* Start address of section
|
||||
* @param data
|
||||
* Data of section
|
||||
*/
|
||||
public MoteMemorySection(int startAddr, byte[] data) {
|
||||
this.startAddr = startAddr;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns start address of this memory section.
|
||||
*
|
||||
* @return Start address
|
||||
*/
|
||||
public int getStartAddr() {
|
||||
return startAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns size of this memory section.
|
||||
*
|
||||
* @return Size
|
||||
*/
|
||||
public int getSize() {
|
||||
return data.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entire byte array which defines this section.
|
||||
*
|
||||
* @return Byte array
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if given address is part of this memory section.
|
||||
*
|
||||
* @param addr
|
||||
* Address
|
||||
* @return True if given address is part of this memory section, false
|
||||
* otherwise
|
||||
*/
|
||||
public boolean includesAddr(int addr) {
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (addr >= startAddr && addr < (startAddr + data.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns memory segment.
|
||||
*
|
||||
* @param addr
|
||||
* Start address of memory segment
|
||||
* @param size
|
||||
* Size of memory segment
|
||||
* @return Memory segment
|
||||
*/
|
||||
public byte[] getMemorySegment(int addr, int size) {
|
||||
byte[] ret = new byte[size];
|
||||
System.arraycopy(data, addr - startAddr, ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a memory segment.
|
||||
*
|
||||
* @param addr
|
||||
* Start of memory segment
|
||||
* @param data
|
||||
* Data of memory segment
|
||||
*/
|
||||
public void setMemorySegment(int addr, byte[] data) {
|
||||
System.arraycopy(data, 0, this.data, addr - startAddr, data.length);
|
||||
}
|
||||
|
||||
public MoteMemorySection clone() {
|
||||
byte[] dataClone = new byte[data.length];
|
||||
System.arraycopy(data, 0, dataClone, 0, data.length);
|
||||
|
||||
MoteMemorySection clone = new MoteMemorySection(startAddr, dataClone);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
public SectionMoteMemory clone() {
|
||||
ArrayList<MoteMemorySection> sectionsClone = new ArrayList<MoteMemorySection>();
|
||||
for (MoteMemorySection section : sections) {
|
||||
sectionsClone.add(section.clone());
|
||||
}
|
||||
|
||||
SectionMoteMemory clone = new SectionMoteMemory(addresses, offset);
|
||||
clone.sections = sectionsClone;
|
||||
clone.readonlySections = readonlySections;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
private ArrayList<PolledMemorySegments> polledMemories = new ArrayList<PolledMemorySegments>();
|
||||
public void pollForMemoryChanges() {
|
||||
for (PolledMemorySegments mem: polledMemories.toArray(new PolledMemorySegments[0])) {
|
||||
mem.notifyIfChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private class PolledMemorySegments {
|
||||
public final MemoryMonitor mm;
|
||||
public final int address;
|
||||
public final int size;
|
||||
private byte[] oldMem;
|
||||
|
||||
public PolledMemorySegments(MemoryMonitor mm, int address, int size) {
|
||||
this.mm = mm;
|
||||
this.address = address;
|
||||
this.size = size;
|
||||
|
||||
oldMem = getMemorySegment(address, size);
|
||||
}
|
||||
|
||||
private void notifyIfChanged() {
|
||||
byte[] newMem = getMemorySegment(address, size);
|
||||
if (Arrays.equals(oldMem, newMem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mm.memoryChanged(SectionMoteMemory.this, MemoryEventType.WRITE, address);
|
||||
oldMem = newMem;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) {
|
||||
PolledMemorySegments t = new PolledMemorySegments(mm, address, size);
|
||||
polledMemories.add(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) {
|
||||
for (PolledMemorySegments mcm: polledMemories) {
|
||||
if (mcm.mm != mm || mcm.address != address || mcm.size != size) {
|
||||
continue;
|
||||
}
|
||||
polledMemories.remove(mcm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public int parseInt(byte[] memorySegment) {
|
||||
int retVal = 0;
|
||||
int pos = 0;
|
||||
retVal += ((memorySegment[pos++] & 0xFF)) << 24;
|
||||
retVal += ((memorySegment[pos++] & 0xFF)) << 16;
|
||||
retVal += ((memorySegment[pos++] & 0xFF)) << 8;
|
||||
retVal += ((memorySegment[pos++] & 0xFF)) << 0;
|
||||
|
||||
retVal = Integer.reverseBytes(retVal);
|
||||
return retVal;
|
||||
}
|
||||
}
|
|
@ -38,10 +38,10 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteInterface;
|
||||
import org.contikios.cooja.MoteInterfaceHandler;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.MoteType;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.motes.AbstractWakeupMote;
|
||||
|
||||
/**
|
||||
|
@ -83,10 +83,12 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
|
|||
requestImmediateWakeup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID() {
|
||||
return myInterfaceHandler.getMoteID().getMoteID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoteInterfaceHandler getInterfaces() {
|
||||
return myInterfaceHandler;
|
||||
}
|
||||
|
@ -95,14 +97,16 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
|
|||
myInterfaceHandler = newInterfaces;
|
||||
}
|
||||
|
||||
public MoteMemory getMemory() {
|
||||
@Override
|
||||
public MemoryInterface getMemory() {
|
||||
return myMemory;
|
||||
}
|
||||
|
||||
public void setMemory(MoteMemory memory) {
|
||||
myMemory = (SectionMoteMemory) memory;
|
||||
public void setMemory(SectionMoteMemory memory) {
|
||||
myMemory = memory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoteType getType() {
|
||||
return myType;
|
||||
}
|
||||
|
@ -121,6 +125,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
|
|||
*
|
||||
* @param simTime Current simulation time
|
||||
*/
|
||||
@Override
|
||||
public void execute(long simTime) {
|
||||
|
||||
/* Poll mote interfaces */
|
||||
|
@ -154,6 +159,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
|
|||
*
|
||||
* @return Current simulation config
|
||||
*/
|
||||
@Override
|
||||
public Collection<Element> getConfigXML() {
|
||||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
@ -173,6 +179,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
|
|||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setConfigXML(Simulation simulation, Collection<Element> configXML, boolean visAvailable) {
|
||||
setSimulation(simulation);
|
||||
myMemory = myType.createInitialMemory();
|
||||
|
@ -212,6 +219,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Contiki " + getID();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -44,10 +44,11 @@ import org.apache.log4j.Logger;
|
|||
import org.jdom.Element;
|
||||
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.Beeper;
|
||||
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Beeper mote interface.
|
||||
|
@ -70,7 +71,7 @@ import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
|
|||
*/
|
||||
public class ContikiBeeper extends Beeper implements ContikiMoteInterface, PolledAfterActiveTicks {
|
||||
private Mote mote = null;
|
||||
private SectionMoteMemory moteMem = null;
|
||||
private VarMemory moteMem = null;
|
||||
private static Logger logger = Logger.getLogger(ContikiBeeper.class);
|
||||
|
||||
/**
|
||||
|
@ -83,7 +84,7 @@ public class ContikiBeeper extends Beeper implements ContikiMoteInterface, Polle
|
|||
*/
|
||||
public ContikiBeeper(Mote mote) {
|
||||
this.mote = mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public boolean isBeeping() {
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.contikios.cooja.*;
|
|||
import org.contikios.cooja.contikimote.ContikiMote;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.Button;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Button mote interface.
|
||||
|
@ -62,7 +63,7 @@ import org.contikios.cooja.interfaces.Button;
|
|||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public class ContikiButton extends Button implements ContikiMoteInterface {
|
||||
private SectionMoteMemory moteMem;
|
||||
private VarMemory moteMem;
|
||||
private ContikiMote mote;
|
||||
|
||||
private static Logger logger = Logger.getLogger(ContikiButton.class);
|
||||
|
@ -76,7 +77,7 @@ public class ContikiButton extends Button implements ContikiMoteInterface {
|
|||
*/
|
||||
public ContikiButton(Mote mote) {
|
||||
this.mote = (ContikiMote) mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.*;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Contiki FileSystem (CFS) interface (such as external flash).
|
||||
|
@ -71,7 +72,7 @@ public class ContikiCFS extends MoteInterface implements ContikiMoteInterface, P
|
|||
|
||||
public int FILESYSTEM_SIZE = 4000; /* Configure CFS size here and in cfs-cooja.c */
|
||||
private Mote mote = null;
|
||||
private SectionMoteMemory moteMem = null;
|
||||
private VarMemory moteMem = null;
|
||||
|
||||
private int lastRead = 0;
|
||||
private int lastWritten = 0;
|
||||
|
@ -85,7 +86,7 @@ public class ContikiCFS extends MoteInterface implements ContikiMoteInterface, P
|
|||
*/
|
||||
public ContikiCFS(Mote mote) {
|
||||
this.mote = mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -37,13 +37,14 @@ import org.apache.log4j.Logger;
|
|||
import org.jdom.Element;
|
||||
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.contikimote.ContikiMote;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.Clock;
|
||||
import org.contikios.cooja.interfaces.PolledAfterAllTicks;
|
||||
import org.contikios.cooja.interfaces.PolledBeforeActiveTicks;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Clock mote interface. Controls Contiki time.
|
||||
|
@ -71,7 +72,7 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
|
|||
|
||||
private Simulation simulation;
|
||||
private ContikiMote mote;
|
||||
private SectionMoteMemory moteMem;
|
||||
private VarMemory moteMem;
|
||||
|
||||
private long moteTime; /* Microseconds */
|
||||
private long timeDrift; /* Microseconds */
|
||||
|
@ -85,7 +86,7 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
|
|||
public ContikiClock(Mote mote) {
|
||||
this.simulation = mote.getSimulation();
|
||||
this.mote = (ContikiMote) mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
timeDrift = 0;
|
||||
moteTime = 0;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.*;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Contiki EEPROM interface
|
||||
|
@ -73,7 +74,7 @@ public class ContikiEEPROM extends MoteInterface implements ContikiMoteInterface
|
|||
|
||||
public int EEPROM_SIZE = 1024; /* Configure EEPROM size here and in eeprom.c. Should really be multiple of 16 */
|
||||
private Mote mote = null;
|
||||
private SectionMoteMemory moteMem = null;
|
||||
private VarMemory moteMem = null;
|
||||
|
||||
private int lastRead = 0;
|
||||
private int lastWritten = 0;
|
||||
|
@ -87,7 +88,7 @@ public class ContikiEEPROM extends MoteInterface implements ContikiMoteInterface
|
|||
*/
|
||||
public ContikiEEPROM(Mote mote) {
|
||||
this.mote = mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.contikios.cooja.*;
|
|||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.LED;
|
||||
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* LEDs mote interface.
|
||||
|
@ -64,7 +65,7 @@ public class ContikiLED extends LED implements ContikiMoteInterface, PolledAfter
|
|||
private static Logger logger = Logger.getLogger(ContikiLED.class);
|
||||
|
||||
private Mote mote = null;
|
||||
private SectionMoteMemory moteMem = null;
|
||||
private VarMemory moteMem = null;
|
||||
private byte currentLedValue = 0;
|
||||
|
||||
private static final byte LEDS_GREEN = 1;
|
||||
|
@ -91,7 +92,7 @@ public class ContikiLED extends LED implements ContikiMoteInterface, PolledAfter
|
|||
*/
|
||||
public ContikiLED(Mote mote) {
|
||||
this.mote = mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.*;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.MoteID;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Mote ID interface: 'node_id'.
|
||||
|
@ -60,7 +61,7 @@ import org.contikios.cooja.interfaces.MoteID;
|
|||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public class ContikiMoteID extends MoteID implements ContikiMoteInterface {
|
||||
private SectionMoteMemory moteMem = null;
|
||||
private VarMemory moteMem = null;
|
||||
private static Logger logger = Logger.getLogger(ContikiMoteID.class);
|
||||
|
||||
private int moteID = 0;
|
||||
|
@ -77,7 +78,7 @@ public class ContikiMoteID extends MoteID implements ContikiMoteInterface {
|
|||
*/
|
||||
public ContikiMoteID(Mote mote) {
|
||||
this.mote = mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -37,10 +37,11 @@ import javax.swing.JButton;
|
|||
import javax.swing.JPanel;
|
||||
import org.jdom.Element;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.contikimote.ContikiMote;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.PIR;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Passive IR sensor mote interface.
|
||||
|
@ -65,7 +66,7 @@ import org.contikios.cooja.interfaces.PIR;
|
|||
public class ContikiPIR extends PIR implements ContikiMoteInterface {
|
||||
|
||||
private ContikiMote mote;
|
||||
private SectionMoteMemory moteMem;
|
||||
private VarMemory moteMem;
|
||||
|
||||
/**
|
||||
* Creates an interface to the PIR at mote.
|
||||
|
@ -77,7 +78,7 @@ public class ContikiPIR extends PIR implements ContikiMoteInterface {
|
|||
*/
|
||||
public ContikiPIR(Mote mote) {
|
||||
this.mote = (ContikiMote) mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.contikios.cooja.contikimote.ContikiMote;
|
|||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.dialogs.SerialUI;
|
||||
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Contiki mote serial port and log interfaces.
|
||||
|
@ -68,7 +69,7 @@ public class ContikiRS232 extends SerialUI implements ContikiMoteInterface, Poll
|
|||
private static Logger logger = Logger.getLogger(ContikiRS232.class);
|
||||
|
||||
private ContikiMote mote = null;
|
||||
private SectionMoteMemory moteMem = null;
|
||||
private VarMemory moteMem = null;
|
||||
|
||||
static final int SERIAL_BUF_SIZE = 1024; /* rs232.c:40 */
|
||||
|
||||
|
@ -82,7 +83,7 @@ public class ContikiRS232 extends SerialUI implements ContikiMoteInterface, Poll
|
|||
*/
|
||||
public ContikiRS232(Mote mote) {
|
||||
this.mote = (ContikiMote) mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -39,13 +39,14 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.COOJARadioPacket;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.RadioPacket;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.contikimote.ContikiMote;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
|
||||
import org.contikios.cooja.interfaces.Position;
|
||||
import org.contikios.cooja.interfaces.Radio;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
import org.contikios.cooja.radiomediums.UDGM;
|
||||
|
||||
/**
|
||||
|
@ -89,7 +90,7 @@ import org.contikios.cooja.radiomediums.UDGM;
|
|||
public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledAfterActiveTicks {
|
||||
private ContikiMote mote;
|
||||
|
||||
private SectionMoteMemory myMoteMemory;
|
||||
private VarMemory myMoteMemory;
|
||||
|
||||
private static Logger logger = Logger.getLogger(ContikiRadio.class);
|
||||
|
||||
|
@ -132,7 +133,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA
|
|||
ContikiRadio.class, "RADIO_TRANSMISSION_RATE_kbps");
|
||||
|
||||
this.mote = (ContikiMote) mote;
|
||||
this.myMoteMemory = (SectionMoteMemory) mote.getMemory();
|
||||
this.myMoteMemory = new VarMemory(mote.getMemory());
|
||||
|
||||
radioOn = myMoteMemory.getByteValueOf("simRadioHWOn") == 1;
|
||||
}
|
||||
|
|
|
@ -39,9 +39,10 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.ClassDescription;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteInterface;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.contikimote.ContikiMote;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Vibration sensor mote interface.
|
||||
|
@ -67,7 +68,7 @@ import org.contikios.cooja.contikimote.ContikiMoteInterface;
|
|||
public class ContikiVib extends MoteInterface implements ContikiMoteInterface {
|
||||
|
||||
private ContikiMote mote;
|
||||
private SectionMoteMemory moteMem;
|
||||
private VarMemory moteMem;
|
||||
|
||||
/**
|
||||
* Creates an interface to the vibration sensor at mote.
|
||||
|
@ -79,7 +80,7 @@ public class ContikiVib extends MoteInterface implements ContikiMoteInterface {
|
|||
*/
|
||||
public ContikiVib(Mote mote) {
|
||||
this.mote = (ContikiMote) mote;
|
||||
this.moteMem = (SectionMoteMemory) mote.getMemory();
|
||||
this.moteMem = new VarMemory(mote.getMemory());
|
||||
}
|
||||
|
||||
public static String[] getCoreInterfaceDependencies() {
|
||||
|
|
|
@ -66,8 +66,11 @@ import javax.swing.JScrollPane;
|
|||
import org.contikios.cooja.CoreComm;
|
||||
import org.contikios.cooja.Cooja;
|
||||
import org.contikios.cooja.MoteType.MoteTypeCreationException;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteType;
|
||||
import org.contikios.cooja.contikimote.ContikiMoteType.SectionParser;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/* TODO Test common section */
|
||||
/* TODO Test readonly section */
|
||||
|
@ -141,7 +144,7 @@ public class ConfigurationWizard extends JDialog {
|
|||
private static File cLibraryFile;
|
||||
private static String javaLibraryName;
|
||||
private static CoreComm javaLibrary;
|
||||
private static HashMap<String, Integer> addresses;
|
||||
private static HashMap<String, Symbol> addresses;
|
||||
private static int relDataSectionAddr;
|
||||
private static int dataSectionSize;
|
||||
private static int relBssSectionAddr;
|
||||
|
@ -757,18 +760,28 @@ public class ConfigurationWizard extends JDialog {
|
|||
}
|
||||
|
||||
testOutput.addMessage("### Parsing map file data for addresses");
|
||||
addresses = new HashMap<String, Integer>();
|
||||
boolean parseOK = ContikiMoteType.parseMapFileData(mapData, addresses);
|
||||
if (!parseOK) {
|
||||
testOutput.addMessage("### Error: Failed parsing map file data", MessageList.ERROR);
|
||||
return false;
|
||||
}
|
||||
addresses = new HashMap<String, Symbol>();
|
||||
// boolean parseOK = ContikiMoteType.parseMapFileData(mapData, addresses);
|
||||
// if (!parseOK) {
|
||||
// testOutput.addMessage("### Error: Failed parsing map file data", MessageList.ERROR);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
testOutput.addMessage("### Validating section addresses");
|
||||
relDataSectionAddr = ContikiMoteType.parseMapDataSectionAddr(mapData);
|
||||
dataSectionSize = ContikiMoteType.parseMapDataSectionSize(mapData);
|
||||
relBssSectionAddr = ContikiMoteType.parseMapBssSectionAddr(mapData);
|
||||
bssSectionSize = ContikiMoteType.parseMapBssSectionSize(mapData);
|
||||
SectionParser dataSecParser = new ContikiMoteType.MapSectionParser(
|
||||
mapData,
|
||||
Cooja.getExternalToolsSetting("MAPFILE_DATA_START"),
|
||||
Cooja.getExternalToolsSetting("MAPFILE_DATA_SIZE"));
|
||||
SectionParser bssSecParser = new ContikiMoteType.MapSectionParser(
|
||||
mapData,
|
||||
Cooja.getExternalToolsSetting("MAPFILE_BSS_START"),
|
||||
Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE"));
|
||||
dataSecParser.parse(0);
|
||||
bssSecParser.parse(0);
|
||||
relDataSectionAddr = dataSecParser.getStartAddr();
|
||||
dataSectionSize = dataSecParser.getSize();
|
||||
relBssSectionAddr = bssSecParser.getStartAddr();
|
||||
bssSectionSize = bssSecParser.getSize();
|
||||
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
|
||||
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
|
||||
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
|
||||
|
@ -837,18 +850,31 @@ public class ConfigurationWizard extends JDialog {
|
|||
}
|
||||
|
||||
testOutput.addMessage("### Parsing command output for addresses");
|
||||
addresses = new HashMap<String, Integer>();
|
||||
boolean parseOK = ContikiMoteType.parseCommandData(commandData, addresses);
|
||||
if (!parseOK) {
|
||||
testOutput.addMessage("### Error: Failed parsing command output", MessageList.ERROR);
|
||||
return false;
|
||||
}
|
||||
addresses = new HashMap<String, Symbol>();
|
||||
// boolean parseOK = ContikiMoteType.parseCommandData(commandData, addresses);
|
||||
// if (!parseOK) {
|
||||
// testOutput.addMessage("### Error: Failed parsing command output", MessageList.ERROR);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
testOutput.addMessage("### Validating section addresses");
|
||||
relDataSectionAddr = ContikiMoteType.parseCommandDataSectionAddr(commandData);
|
||||
dataSectionSize = ContikiMoteType.parseCommandDataSectionSize(commandData);
|
||||
relBssSectionAddr = ContikiMoteType.parseCommandBssSectionAddr(commandData);
|
||||
bssSectionSize = ContikiMoteType.parseCommandBssSectionSize(commandData);
|
||||
SectionParser dataSecParser = new ContikiMoteType.CommandSectionParser(
|
||||
commandData,
|
||||
Cooja.getExternalToolsSetting("COMMAND_DATA_START"),
|
||||
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE"),
|
||||
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_DATA"));
|
||||
SectionParser bssSecParser = new ContikiMoteType.CommandSectionParser(
|
||||
commandData,
|
||||
Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
|
||||
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"),
|
||||
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_BSS"));
|
||||
|
||||
dataSecParser.parse(0);
|
||||
bssSecParser.parse(0);
|
||||
relDataSectionAddr = dataSecParser.getStartAddr();
|
||||
dataSectionSize = dataSecParser.getSize();
|
||||
relBssSectionAddr = bssSecParser.getStartAddr();
|
||||
bssSectionSize = bssSecParser.getSize();
|
||||
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
|
||||
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
|
||||
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
|
||||
|
@ -935,7 +961,7 @@ public class ConfigurationWizard extends JDialog {
|
|||
testOutput.addMessage("Could not find address of referenceVar", MessageList.ERROR);
|
||||
return false;
|
||||
}
|
||||
int relRefAddress = addresses.get("referenceVar");
|
||||
int relRefAddress = (int) addresses.get("referenceVar").addr;
|
||||
javaLibrary.setReferenceAddress(relRefAddress);
|
||||
|
||||
testOutput.addMessage("### Creating data and BSS memory sections");
|
||||
|
@ -943,15 +969,16 @@ public class ConfigurationWizard extends JDialog {
|
|||
byte[] initialBssSection = new byte[bssSectionSize];
|
||||
javaLibrary.getMemory(relDataSectionAddr, dataSectionSize, initialDataSection);
|
||||
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
|
||||
SectionMoteMemory memory = new SectionMoteMemory(addresses, 0);
|
||||
SectionMoteMemory memory = new SectionMoteMemory(addresses);
|
||||
VarMemory varMem = new VarMemory(memory);
|
||||
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
|
||||
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
|
||||
|
||||
int contikiDataCounter, contikiBSSCounter;
|
||||
|
||||
testOutput.addMessage("### Checking initial variable values: 1,0");
|
||||
contikiDataCounter = memory.getIntValueOf("var1");
|
||||
contikiBSSCounter = memory.getIntValueOf("uvar1");
|
||||
contikiDataCounter = varMem.getIntValueOf("var1");
|
||||
contikiBSSCounter = varMem.getIntValueOf("uvar1");
|
||||
int javaDataCounter = 1;
|
||||
int javaBSSCounter = 0;
|
||||
if (contikiDataCounter != javaDataCounter) {
|
||||
|
@ -975,8 +1002,8 @@ public class ConfigurationWizard extends JDialog {
|
|||
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
|
||||
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
|
||||
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
|
||||
contikiDataCounter = memory.getIntValueOf("var1");
|
||||
contikiBSSCounter = memory.getIntValueOf("uvar1");
|
||||
contikiDataCounter = varMem.getIntValueOf("var1");
|
||||
contikiBSSCounter = varMem.getIntValueOf("uvar1");
|
||||
if (contikiDataCounter != javaDataCounter) {
|
||||
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
|
||||
return false;
|
||||
|
@ -1004,8 +1031,8 @@ public class ConfigurationWizard extends JDialog {
|
|||
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
|
||||
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
|
||||
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
|
||||
contikiDataCounter = memory.getIntValueOf("var1");
|
||||
contikiBSSCounter = memory.getIntValueOf("uvar1");
|
||||
contikiDataCounter = varMem.getIntValueOf("var1");
|
||||
contikiBSSCounter = varMem.getIntValueOf("uvar1");
|
||||
if (contikiDataCounter != javaDataCounter) {
|
||||
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
|
||||
return false;
|
||||
|
@ -1029,8 +1056,8 @@ public class ConfigurationWizard extends JDialog {
|
|||
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
|
||||
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
|
||||
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
|
||||
contikiDataCounter = memory.getIntValueOf("var1");
|
||||
contikiBSSCounter = memory.getIntValueOf("uvar1");
|
||||
contikiDataCounter = varMem.getIntValueOf("var1");
|
||||
contikiBSSCounter = varMem.getIntValueOf("uvar1");
|
||||
if (contikiDataCounter != javaDataCounter) {
|
||||
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
|
||||
return false;
|
||||
|
@ -1049,8 +1076,8 @@ public class ConfigurationWizard extends JDialog {
|
|||
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
|
||||
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
|
||||
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
|
||||
contikiDataCounter = memory.getIntValueOf("var1");
|
||||
contikiBSSCounter = memory.getIntValueOf("uvar1");
|
||||
contikiDataCounter = varMem.getIntValueOf("var1");
|
||||
contikiBSSCounter = varMem.getIntValueOf("uvar1");
|
||||
if (contikiDataCounter != javaDataCounter) {
|
||||
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
|
||||
return false;
|
||||
|
|
|
@ -42,9 +42,9 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.ClassDescription;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteInterface;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.MoteMemory.MemoryEventType;
|
||||
import org.contikios.cooja.MoteMemory.MemoryMonitor;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Read-only interface to IPv4 or IPv6 address.
|
||||
|
@ -54,21 +54,22 @@ import org.contikios.cooja.MoteMemory.MemoryMonitor;
|
|||
@ClassDescription("IP Address")
|
||||
public class IPAddress extends MoteInterface {
|
||||
private static Logger logger = Logger.getLogger(IPAddress.class);
|
||||
private final MoteMemory moteMem;
|
||||
private final VarMemory moteMem;
|
||||
|
||||
private static final int IPv6_MAX_ADDRESSES = 4;
|
||||
private boolean ipv6IsGlobal = false;
|
||||
private int ipv6AddressIndex = -1;
|
||||
|
||||
private static final int MONITORED_SIZE = 150;
|
||||
private MemoryMonitor memMonitor;
|
||||
private SegmentMonitor memMonitor;
|
||||
|
||||
public IPAddress(final Mote mote) {
|
||||
moteMem = mote.getMemory();
|
||||
moteMem = new VarMemory(mote.getMemory());
|
||||
|
||||
memMonitor = new MemoryMonitor() {
|
||||
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) {
|
||||
if (type != MemoryEventType.WRITE) {
|
||||
memMonitor = new MemoryInterface.SegmentMonitor() {
|
||||
@Override
|
||||
public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
|
||||
if (type != SegmentMonitor.EventType.WRITE) {
|
||||
return;
|
||||
}
|
||||
setChanged();
|
||||
|
@ -76,11 +77,11 @@ public class IPAddress extends MoteInterface {
|
|||
}
|
||||
};
|
||||
if (isVersion4()) {
|
||||
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_hostaddr"), 4, memMonitor);
|
||||
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_hostaddr", memMonitor);
|
||||
} else if (isVersion6()) {
|
||||
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_netif_addr_list_offset"), 1, memMonitor);
|
||||
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_addr_size"), 1, memMonitor);
|
||||
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_if"), MONITORED_SIZE, memMonitor);
|
||||
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_netif_addr_list_offset", memMonitor);
|
||||
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_addr_size", memMonitor);
|
||||
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_if", memMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,11 +206,11 @@ public class IPAddress extends MoteInterface {
|
|||
super.removed();
|
||||
if (memMonitor != null) {
|
||||
if (isVersion4()) {
|
||||
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("rimeaddr_node_addr"), 4, memMonitor);
|
||||
moteMem.removeVarMonitor("rimeaddr_node_addr", memMonitor);
|
||||
} else if (isVersion6()) {
|
||||
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_netif_addr_list_offset"), 1, memMonitor);
|
||||
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_addr_size"), 1, memMonitor);
|
||||
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_if"), MONITORED_SIZE, memMonitor);
|
||||
moteMem.removeVarMonitor("uip_ds6_netif_addr_list_offset", memMonitor);
|
||||
moteMem.removeVarMonitor("uip_ds6_addr_size", memMonitor);
|
||||
moteMem.removeVarMonitor("uip_ds6_if", memMonitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,9 +43,9 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.ClassDescription;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteInterface;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.MoteMemory.MemoryEventType;
|
||||
import org.contikios.cooja.MoteMemory.MemoryMonitor;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Read-only interface to Rime address read from Contiki variable: linkaddr_node_addr.
|
||||
|
@ -57,18 +57,19 @@ import org.contikios.cooja.MoteMemory.MemoryMonitor;
|
|||
@ClassDescription("Rime address")
|
||||
public class RimeAddress extends MoteInterface {
|
||||
private static Logger logger = Logger.getLogger(RimeAddress.class);
|
||||
private MoteMemory moteMem;
|
||||
private VarMemory moteMem;
|
||||
|
||||
public static final int RIME_ADDR_LENGTH = 2;
|
||||
|
||||
private MemoryMonitor memMonitor = null;
|
||||
private SegmentMonitor memMonitor = null;
|
||||
|
||||
public RimeAddress(final Mote mote) {
|
||||
moteMem = mote.getMemory();
|
||||
moteMem = new VarMemory(mote.getMemory());
|
||||
if (hasRimeAddress()) {
|
||||
memMonitor = new MemoryMonitor() {
|
||||
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) {
|
||||
if (type != MemoryEventType.WRITE) {
|
||||
memMonitor = new SegmentMonitor() {
|
||||
@Override
|
||||
public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
|
||||
if (type != SegmentMonitor.EventType.WRITE) {
|
||||
return;
|
||||
}
|
||||
setChanged();
|
||||
|
@ -76,7 +77,7 @@ public class RimeAddress extends MoteInterface {
|
|||
}
|
||||
};
|
||||
/* TODO XXX Timeout? */
|
||||
moteMem.addMemoryMonitor(moteMem.getVariableAddress("linkaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor);
|
||||
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "linkaddr_node_addr", memMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +132,7 @@ public class RimeAddress extends MoteInterface {
|
|||
public void removed() {
|
||||
super.removed();
|
||||
if (memMonitor != null) {
|
||||
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("linkaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor);
|
||||
moteMem.removeVarMonitor("linkaddr_node_addr", memMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Enrico Joerns
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A memory that is backed by an array.
|
||||
*
|
||||
* @author Enrico Joerns
|
||||
*/
|
||||
public class ArrayMemory implements MemoryInterface {
|
||||
|
||||
private final byte memory[];
|
||||
private final long startAddress;
|
||||
private final MemoryLayout layout;
|
||||
private final boolean readonly;
|
||||
private final Map<String, Symbol> symbols;// XXX Allow to set symbols
|
||||
|
||||
public ArrayMemory(long address, int size, MemoryLayout layout, Map<String, Symbol> symbols) {
|
||||
this(address, layout, new byte[size], symbols);
|
||||
}
|
||||
|
||||
public ArrayMemory(long address, MemoryLayout layout, byte[] memory, Map<String, Symbol> symbols) {
|
||||
this(address, layout, memory, false, symbols);
|
||||
}
|
||||
|
||||
public ArrayMemory(long address, MemoryLayout layout, byte[] memory, boolean readonly, Map<String, Symbol> symbols) {
|
||||
this.startAddress = address;
|
||||
this.layout = layout;
|
||||
this.memory = memory;
|
||||
this.readonly = readonly;
|
||||
this.symbols = symbols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX Should addr be the relative or the absolute address of this section?
|
||||
* @param addr
|
||||
* @param size
|
||||
* @return
|
||||
* @throws org.contikios.cooja.mote.memory.MemoryInterface.MoteMemoryException
|
||||
*/
|
||||
@Override
|
||||
public byte[] getMemorySegment(long addr, int size) throws MoteMemoryException {
|
||||
byte[] ret = new byte[size];
|
||||
System.arraycopy(memory, (int) (addr - startAddress), ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMemorySegment(long addr, byte[] data) throws MoteMemoryException {
|
||||
if (readonly) {
|
||||
throw new MoteMemoryException("Invalid write access for readonly memory");
|
||||
}
|
||||
System.arraycopy(data, 0, memory, (int) (addr - startAddress), data.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearMemory() {
|
||||
Arrays.fill(memory, (byte) 0x00);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartAddr() {
|
||||
return startAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalSize() {
|
||||
return memory.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Symbol> getSymbolMap() {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryLayout getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addSegmentMonitor(SegmentMonitor.EventType flag, long address, int size, SegmentMonitor monitor) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor monitor) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
}
|
256
tools/cooja/java/org/contikios/cooja/mote/memory/Memory.java
Normal file
256
tools/cooja/java/org/contikios/cooja/mote/memory/Memory.java
Normal file
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig.
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
import org.contikios.cooja.mote.memory.MemoryLayout.DataType;
|
||||
|
||||
/**
|
||||
* Represents memory that can be accessed with address and size informations.
|
||||
*
|
||||
* @author Enrico Jorns
|
||||
*/
|
||||
public abstract class Memory {
|
||||
|
||||
private final MemoryInterface memIntf;
|
||||
|
||||
/**
|
||||
* Creates new memory for given MemoryLayout.
|
||||
*
|
||||
* @param intf
|
||||
*/
|
||||
public Memory(MemoryInterface intf) {
|
||||
memIntf = intf;
|
||||
}
|
||||
|
||||
// -- Get fixed size types
|
||||
/**
|
||||
* Read 8 bit integer from address.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return 8 bit value read from address
|
||||
*/
|
||||
public byte getInt8ValueOf(long addr) {
|
||||
return memIntf.getMemorySegment(addr, DataType.INT8.getSize())[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 16 bit integer from address.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return 16 bit value read from address
|
||||
*/
|
||||
public short getInt16ValueOf(long addr) {
|
||||
return MemoryBuffer.wrap(
|
||||
memIntf.getLayout(),
|
||||
memIntf.getMemorySegment(addr, DataType.INT16.getSize())).getInt16();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 32 bit integer from address.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return 32 bit value read from address
|
||||
*/
|
||||
public int getInt32ValueOf(long addr) {
|
||||
return MemoryBuffer.wrap(
|
||||
memIntf.getLayout(),
|
||||
memIntf.getMemorySegment(addr, DataType.INT32.getSize())).getInt32();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 64 bit integer from address.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return 64 bit value read from address
|
||||
*/
|
||||
public long getInt64ValueOf(long addr) {
|
||||
return MemoryBuffer.wrap(
|
||||
memIntf.getLayout(),
|
||||
memIntf.getMemorySegment(addr, DataType.INT64.getSize())).getInt64();
|
||||
}
|
||||
|
||||
// -- Get compiler-dependent types
|
||||
/**
|
||||
* Read byte from address.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return byte read from address
|
||||
*/
|
||||
public byte getByteValueOf(long addr) {
|
||||
return memIntf.getMemorySegment(addr, DataType.BYTE.getSize())[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read short from address.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return short read from address
|
||||
*/
|
||||
public short getShortValueOf(long addr) {
|
||||
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, 2)).getShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read integer from address.
|
||||
* <p>
|
||||
* Note: Size of integer depends on platform type.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return integer read from address
|
||||
*/
|
||||
public int getIntValueOf(long addr) {
|
||||
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, memIntf.getLayout().intSize)).getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read long from address.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return long read from address
|
||||
*/
|
||||
public long getLongValueOf(long addr) {
|
||||
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, 4)).getLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read pointer from address.
|
||||
* <p>
|
||||
* Note: Size of pointer depends on platform type.
|
||||
*
|
||||
* @param addr Address to read from
|
||||
* @return pointer read from address
|
||||
*/
|
||||
public long getAddrValueOf(long addr) {
|
||||
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, memIntf.getLayout().addrSize)).getAddr();
|
||||
}
|
||||
|
||||
// -- Set fixed size types
|
||||
/**
|
||||
* Write 8 bit integer to address.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value 8 bit value to write
|
||||
*/
|
||||
public void setInt8ValueOf(long addr, byte value) {
|
||||
memIntf.setMemorySegment(addr, new byte[]{value});
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 16 bit integer to address.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value 16 bit value to write
|
||||
*/
|
||||
public void setInt16ValueOf(long addr, short value) {
|
||||
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(
|
||||
memIntf.getLayout(),
|
||||
new byte[DataType.INT16.getSize()]).putShort(value).getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 32 bit integer to address.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value 32 bit value to write
|
||||
*/
|
||||
public void setInt32ValueOf(long addr, int value) {
|
||||
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(
|
||||
memIntf.getLayout(),
|
||||
new byte[DataType.INT32.getSize()]).putInt(value).getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 64 bit integer to address.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value 64 bit value to write
|
||||
*/
|
||||
public void setInt64ValueOf(long addr, long value) {
|
||||
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(
|
||||
memIntf.getLayout(),
|
||||
new byte[DataType.INT64.getSize()]).putLong(value).getBytes());
|
||||
}
|
||||
|
||||
// -- Set compiler-dependent types
|
||||
/**
|
||||
* Write byte to address.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value byte to write
|
||||
*/
|
||||
public void setByteValueOf(long addr, byte value) {
|
||||
memIntf.setMemorySegment(addr, new byte[]{value});
|
||||
}
|
||||
|
||||
/**
|
||||
* Write short to address.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value short to write
|
||||
*/
|
||||
public void setShortValueOf(long addr, short value) {
|
||||
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[2]).putShort(value).getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write integer to address.
|
||||
* <p>
|
||||
* Note: Size of integer depends on platform type.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value integer to write
|
||||
*/
|
||||
public void setIntValueOf(long addr, int value) {
|
||||
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[memIntf.getLayout().intSize]).putInt(value).getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write long to address.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value long to write
|
||||
*/
|
||||
public void setLongValueOf(long addr, long value) {
|
||||
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[4]).putLong(value).getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write pointer to address.
|
||||
* <p>
|
||||
* Note: Size of pointer depends on platform type.
|
||||
*
|
||||
* @param addr Address to write to
|
||||
* @param value pointer to write
|
||||
*/
|
||||
public void setAddrValueOf(long addr, long value) {
|
||||
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[memIntf.getLayout().addrSize]).putAddr(value).getBytes());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,481 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig
|
||||
* 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.
|
||||
*/
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.contikios.cooja.mote.memory.MemoryLayout.DataType;
|
||||
|
||||
/**
|
||||
* Basic routines for memory access with multi-arch support.
|
||||
*
|
||||
* Handles endianess, integer size and address size.
|
||||
*
|
||||
* Supports padding/aligning.
|
||||
*
|
||||
* @author Enrico Jorns
|
||||
*/
|
||||
public class MemoryBuffer {
|
||||
|
||||
private final MemoryLayout memLayout;
|
||||
private final ByteBuffer bbuf;
|
||||
private final DataType[] structure;
|
||||
private int structIndex;
|
||||
|
||||
private MemoryBuffer(MemoryLayout memLayout, ByteBuffer buffer, DataType[] structure) {
|
||||
this.memLayout = memLayout;
|
||||
this.bbuf = buffer;
|
||||
this.structure = structure;
|
||||
this.structIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a byte array into an unstructered MemoryBuffer with given MemoryLayout.
|
||||
*<p>
|
||||
* Note that modifications to the buffer are applied to the backed array and vice versa.
|
||||
*
|
||||
* @param layout MemoryLayout for memory to access array from
|
||||
* @param array Byte array that will back this buffer
|
||||
* @return the new MemroyBuffer
|
||||
*/
|
||||
public static MemoryBuffer wrap(MemoryLayout layout, byte[] array) {
|
||||
return wrap(layout, array, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a byte array into a structured MemoryBuffer with given MemoryLayout.
|
||||
*<p>
|
||||
* Note that modifications to the buffer are applied to the backed array and vice versa.
|
||||
*<p>
|
||||
* A structured MemoryBuffer can be used to simplify reading c struct data
|
||||
* from the memory as it provides support for data aligning.
|
||||
*<p>
|
||||
* The structure array elements should be set to exactly the same types and order
|
||||
* that the corresponding c struct has.
|
||||
*
|
||||
* @param layout MemoryLayout for memory to access array from
|
||||
* @param structure Array of data types representing the structure to read
|
||||
* @param array Byte array that will back this buffer
|
||||
* @return the new MemroyBuffer
|
||||
*/
|
||||
public static MemoryBuffer wrap(MemoryLayout layout, byte[] array, DataType[] structure) {
|
||||
ByteBuffer b = ByteBuffer.wrap(array);
|
||||
b.order(layout.order); // preset endianess
|
||||
return new MemoryBuffer(layout, b, structure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte array that backs this buffer
|
||||
*
|
||||
* @return byte array that backs this buffer
|
||||
*/
|
||||
public byte[] getBytes() {
|
||||
if (bbuf.hasArray()) {
|
||||
return bbuf.array();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the padding bytes to be added/skipped between current and next
|
||||
* element.
|
||||
*
|
||||
* @param type Current data type
|
||||
*/
|
||||
private void skipPaddingBytesFor(DataType type) {
|
||||
/* Check if we have a structure and not yet reached the last element */
|
||||
if (structure != null && structure[structIndex + 1] != null) {
|
||||
/* get size of next element in structure */
|
||||
int nextsize = structure[structIndex + 1].getSize();
|
||||
/* limit padding to word size */
|
||||
nextsize = nextsize > memLayout.WORD_SIZE ? memLayout.WORD_SIZE : nextsize;
|
||||
/* calc padding */
|
||||
int pad = nextsize - type.getSize();
|
||||
/* Skip padding bytes */
|
||||
if (pad > 0) {
|
||||
bbuf.position(bbuf.position() + pad);
|
||||
}
|
||||
}
|
||||
structIndex++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current element type.
|
||||
*
|
||||
* @return current element type or null if no struct is used
|
||||
*/
|
||||
public DataType getType() {
|
||||
if (structure == null) {
|
||||
return null;
|
||||
}
|
||||
return structure[structIndex];
|
||||
}
|
||||
|
||||
// --- fixed size types
|
||||
|
||||
/**
|
||||
* Reads 8 bit integer from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return 8 bit integer at the buffer's current position
|
||||
*/
|
||||
public byte getInt8() {
|
||||
byte value = bbuf.get();
|
||||
skipPaddingBytesFor(DataType.INT8);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads 16 bit integer from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return 16 bit integer at the buffer's current position
|
||||
*/
|
||||
public short getInt16() {
|
||||
short value = bbuf.getShort();
|
||||
skipPaddingBytesFor(DataType.INT16);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads 32 bit integer from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return 32 bit integer at the buffer's current position
|
||||
*/
|
||||
public int getInt32() {
|
||||
int value = bbuf.getInt();
|
||||
skipPaddingBytesFor(DataType.INT32);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads 64 bit integer from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return 64 bit integer at the buffer's current position
|
||||
*/
|
||||
public long getInt64() {
|
||||
long value = bbuf.getLong();
|
||||
skipPaddingBytesFor(DataType.INT64);
|
||||
return value;
|
||||
}
|
||||
|
||||
// --- platform-dependent types
|
||||
|
||||
/**
|
||||
* Reads byte from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return byte at the buffer's current position
|
||||
*/
|
||||
public byte getByte() {
|
||||
byte value = bbuf.get();
|
||||
skipPaddingBytesFor(DataType.BYTE);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads short from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return short at the buffer's current position
|
||||
*/
|
||||
public short getShort() {
|
||||
short value = bbuf.getShort();
|
||||
skipPaddingBytesFor(DataType.SHORT);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads integer from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return integer at the buffer's current position
|
||||
*/
|
||||
public int getInt() {
|
||||
int value;
|
||||
switch (memLayout.intSize) {
|
||||
case 2:
|
||||
value = bbuf.getShort();
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
value = bbuf.getInt();
|
||||
break;
|
||||
}
|
||||
skipPaddingBytesFor(DataType.INT);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads long from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return long at the buffer's current position
|
||||
*/
|
||||
public long getLong() {
|
||||
long value = bbuf.getLong();
|
||||
skipPaddingBytesFor(DataType.LONG);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads pointer from current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured reading is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @return pointer at the buffer's current position
|
||||
*/
|
||||
public long getAddr() {
|
||||
long value;
|
||||
switch (memLayout.addrSize) {
|
||||
case 2:
|
||||
value = bbuf.getShort();
|
||||
break;
|
||||
case 4:
|
||||
value = bbuf.getInt();
|
||||
break;
|
||||
case 8:
|
||||
value = bbuf.getLong();
|
||||
break;
|
||||
default:
|
||||
value = bbuf.getInt();
|
||||
break;
|
||||
}
|
||||
skipPaddingBytesFor(DataType.POINTER);
|
||||
return value;
|
||||
}
|
||||
|
||||
// --- fixed size types
|
||||
|
||||
/**
|
||||
* Writes 8 bit integer to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @param value 8 bit integer to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putInt8(byte value) {
|
||||
bbuf.put(value);
|
||||
skipPaddingBytesFor(DataType.INT8);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes 16 bit integer to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @param value 16 bit integer to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putInt16(short value) {
|
||||
bbuf.putShort(value);
|
||||
skipPaddingBytesFor(DataType.INT16);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes 32 bit integer to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @param value 32 bit integer to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putInt32(int value) {
|
||||
bbuf.putInt(value);
|
||||
skipPaddingBytesFor(DataType.INT32);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes 64 bit integer to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @param value 64 bit integer to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putInt64(long value) {
|
||||
bbuf.putLong(value);
|
||||
skipPaddingBytesFor(DataType.INT64);
|
||||
return this;
|
||||
}
|
||||
|
||||
// --- platform-dependent types
|
||||
|
||||
/**
|
||||
* Writes byte to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @param value byte to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putByte(byte value) {
|
||||
bbuf.put(value);
|
||||
skipPaddingBytesFor(DataType.BYTE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes short to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @param value short to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putShort(short value) {
|
||||
bbuf.putShort(value);
|
||||
skipPaddingBytesFor(DataType.SHORT);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes integer to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
* <p>
|
||||
* Note: Size of integer depends on platform type
|
||||
*
|
||||
* @param value integer to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putInt(int value) {
|
||||
switch (memLayout.intSize) {
|
||||
case 2:
|
||||
/**
|
||||
* @TODO: check for size?
|
||||
*/
|
||||
bbuf.putShort((short) value);
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
bbuf.putInt(value);
|
||||
break;
|
||||
}
|
||||
skipPaddingBytesFor(DataType.INT);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes long to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
*
|
||||
* @param value long to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putLong(long value) {
|
||||
bbuf.putLong(value);
|
||||
skipPaddingBytesFor(DataType.LONG);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes pointer to current buffer position,
|
||||
* and then increments position.
|
||||
* <p>
|
||||
* Note: If structured writing is enabled,
|
||||
* additional padding bytes may be skipped automatically.
|
||||
* <p>
|
||||
* Note: Size of pointer depends on platform type
|
||||
*
|
||||
* @param value pointer to write
|
||||
* @return A reference to this object
|
||||
*/
|
||||
public MemoryBuffer putAddr(long value) {
|
||||
/**
|
||||
* @TODO: check for size?
|
||||
*/
|
||||
switch (memLayout.addrSize) {
|
||||
case 2:
|
||||
bbuf.putShort((short) value);
|
||||
break;
|
||||
case 4:
|
||||
bbuf.putInt((int) value);
|
||||
break;
|
||||
case 8:
|
||||
bbuf.putLong(value);
|
||||
break;
|
||||
default:
|
||||
bbuf.putInt((int) value);
|
||||
break;
|
||||
}
|
||||
skipPaddingBytesFor(DataType.POINTER);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig
|
||||
* 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.
|
||||
*/
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A minimal interface to a motes memory.
|
||||
*
|
||||
* Allows reading and writing memory, obtaining symbol information
|
||||
* and provides some basic inforation about size, layout, etc.
|
||||
*
|
||||
* @author Enrico Jorns
|
||||
*/
|
||||
public interface MemoryInterface {
|
||||
|
||||
/**
|
||||
* Represents a symbol in memory (variable / function)
|
||||
*/
|
||||
public static class Symbol {
|
||||
|
||||
public final Type type;
|
||||
public final String name;
|
||||
public final String section;
|
||||
public final long addr;
|
||||
public final int size;
|
||||
|
||||
public enum Type {
|
||||
|
||||
VARIABLE,
|
||||
FUNCTION
|
||||
}
|
||||
|
||||
public Symbol(Type type, String name, String section, long addr, int size) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.section = section;
|
||||
this.addr = addr;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public Symbol(Type type, String name, long addr, int size) {
|
||||
this(type, name, null, addr, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("Symbol(").append(type == null ? "N/A" : type.toString())
|
||||
.append(") '").append(name)
|
||||
.append("' in '").append(section == null ? "N/A" : section)
|
||||
.append("' at 0x").append(addr == -1 ? "N/A" : Long.toHexString(addr))
|
||||
.append(" size ").append(size == -1 ? "N/A" : String.valueOf(size)).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class represents memory access exceptions.
|
||||
*/
|
||||
public class MoteMemoryException extends RuntimeException {
|
||||
|
||||
public MoteMemoryException(String message, Object... args) {
|
||||
super(String.format(message, args));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns entire mote memory
|
||||
* @return Memory byte array
|
||||
* @throws org.contikios.cooja.mote.memory.MemoryInterface.MoteMemoryException
|
||||
*/
|
||||
public byte[] getMemory() throws MoteMemoryException;
|
||||
|
||||
/**
|
||||
* Reads a segment from memory.
|
||||
*
|
||||
* @param addr Start address to read from
|
||||
* @param size Size to read [bytes]
|
||||
* @return Byte array
|
||||
*/
|
||||
public byte[] getMemorySegment(long addr, int size) throws MoteMemoryException;
|
||||
|
||||
/**
|
||||
* Sets a segment of memory.
|
||||
*
|
||||
* @param addr Start address to write to
|
||||
* @param data Size to write [bytes]
|
||||
*/
|
||||
void setMemorySegment(long addr, byte[] data) throws MoteMemoryException;
|
||||
|
||||
/**
|
||||
* Clears the memory.
|
||||
*/
|
||||
void clearMemory();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
long getStartAddr();
|
||||
|
||||
/**
|
||||
* Returns total size of memory.
|
||||
*
|
||||
* @return Size [bytes]
|
||||
*/
|
||||
int getTotalSize();// XXX getSize();
|
||||
|
||||
/**
|
||||
* Returns Map of all variables in memory.
|
||||
* Map must be of typ name / symbol.
|
||||
*
|
||||
* @return Variables
|
||||
*/
|
||||
Map<String, Symbol> getSymbolMap();
|
||||
|
||||
/**
|
||||
* Returns the MemoryLayout for this memory.
|
||||
*
|
||||
* @return Memory layout for this memory
|
||||
*/
|
||||
MemoryLayout getLayout();
|
||||
|
||||
/**
|
||||
* Monitor to listen for memory updates.
|
||||
*/
|
||||
interface SegmentMonitor {
|
||||
|
||||
public static enum EventType {
|
||||
|
||||
READ,
|
||||
WRITE,
|
||||
READWRITE
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked if the monitored segment changed
|
||||
*
|
||||
* @param memory Reference to the memory
|
||||
* @param type XXX ???
|
||||
* @param address Address in segment where modification occured
|
||||
*/
|
||||
void memoryChanged(MemoryInterface memory, EventType type, long address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a SegmentMonitor for the specified address region.
|
||||
*
|
||||
* @param flag Select memory operation(s) to listen for
|
||||
* (read, write, read/write)
|
||||
* @param address Start address of monitored data region
|
||||
* @param size Size of monitored data region
|
||||
* @param monitor SegmentMonitor to add
|
||||
* @return true if monitor could be added, false if not
|
||||
*/
|
||||
boolean addSegmentMonitor(SegmentMonitor.EventType flag, long address, int size, SegmentMonitor monitor);
|
||||
|
||||
/**
|
||||
* Removes SegmentMonitor assigned to the specified region.
|
||||
*
|
||||
* @param address Start address of Monitor data region
|
||||
* @param size Size of Monitor data region
|
||||
* @param monitor SegmentMonitor to remove
|
||||
* @return true if monitor was removed, false if not
|
||||
*/
|
||||
boolean removeSegmentMonitor(long address, int size, SegmentMonitor monitor);
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Holds memory layout informations such as endianess, wordsize, C int size.
|
||||
*
|
||||
* @author Enrico Jorns
|
||||
*/
|
||||
public class MemoryLayout {
|
||||
|
||||
/** 8 bit memory architecture */
|
||||
public static final int ARCH_8BIT = 1;
|
||||
/** 16 bit memory architecture */
|
||||
public static final int ARCH_16BIT = 2;
|
||||
/** 32 bit memory architecture */
|
||||
public static final int ARCH_32BIT = 4;
|
||||
/** 64 bit memory architecture */
|
||||
public static final int ARCH_64BIT = 8;
|
||||
|
||||
/**
|
||||
* Size of data types in bytes.
|
||||
*/
|
||||
public enum DataType {
|
||||
|
||||
BYTE(1),
|
||||
CHAR(1),
|
||||
SHORT(2),
|
||||
INT(4),
|
||||
LONG(8),
|
||||
LONGLONG(8),
|
||||
INT8(1),
|
||||
INT16(2),
|
||||
INT32(4),
|
||||
INT64(8),
|
||||
FLOAT(4),
|
||||
DOUBLE(8),
|
||||
POINTER(4);
|
||||
|
||||
private int size;
|
||||
|
||||
DataType(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return this.size;
|
||||
}
|
||||
}
|
||||
|
||||
public final ByteOrder order;
|
||||
public final int addrSize;
|
||||
public final int intSize;
|
||||
public final int WORD_SIZE;
|
||||
private boolean aligned = true;
|
||||
|
||||
/**
|
||||
* Creates new MemoryLayout instance.
|
||||
*
|
||||
* @param order either ByteOrder.BIG_ENDIAN, or ByteOrder.LITTLE_ENDIAN
|
||||
* @param wordsize should be one of ARCH_8BIT, ARCH_16BIT, ARCH_32BIT,
|
||||
* ARCH_64BIT
|
||||
* @param sizeofInt
|
||||
*/
|
||||
public MemoryLayout(ByteOrder order, int wordsize, int sizeofInt) {
|
||||
this(order, wordsize, sizeofInt, wordsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new MemoryLayout instance.
|
||||
*
|
||||
* @param order either ByteOrder.BIG_ENDIAN, or ByteOrder.LITTLE_ENDIAN
|
||||
* @param wordsize should be one of ARCH_8BIT, ARCH_16BIT, ARCH_32BIT,
|
||||
* ARCH_64BIT
|
||||
* @param sizeofPointer
|
||||
* @param sizeofInt
|
||||
*/
|
||||
public MemoryLayout(ByteOrder order, int wordsize, int sizeofInt, int sizeofPointer) {
|
||||
this.order = order;
|
||||
this.WORD_SIZE = wordsize;
|
||||
this.intSize = sizeofInt;
|
||||
this.addrSize = sizeofPointer;
|
||||
DataType.INT.setSize(this.intSize);
|
||||
DataType.POINTER.setSize(this.addrSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MemoryLayout for the running jvm.
|
||||
*
|
||||
* @return MemoryLayout for the running jvm.
|
||||
*/
|
||||
public static MemoryLayout getNative() {
|
||||
return new MemoryLayout(
|
||||
ByteOrder.nativeOrder(),
|
||||
Integer.parseInt(System.getProperty("sun.arch.data.model")) / 8,
|
||||
Integer.SIZE / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable data alignment.
|
||||
*
|
||||
* Determines whether data alignemnt is used for packing structs.
|
||||
* Default is enabled.
|
||||
*
|
||||
* @param aligned true to enable data alignment, false to disable
|
||||
*/
|
||||
public void setAligned(boolean aligned) {
|
||||
this.aligned = aligned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if data is aligned.
|
||||
*
|
||||
* @return if aligned
|
||||
*/
|
||||
public boolean isAligned() {
|
||||
return aligned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of padding bytes between two data types.
|
||||
*
|
||||
* @param currType
|
||||
* @param nextType
|
||||
* @return
|
||||
*/
|
||||
public int getPaddingBytesFor(DataType currType, DataType nextType) {
|
||||
/* No padding bytes for unaligned memory */
|
||||
if (!isAligned()) {
|
||||
return 0;
|
||||
}
|
||||
/* get size of next element in structure */
|
||||
int nextsize = nextType.getSize();
|
||||
/* limit padding to word size */
|
||||
nextsize = nextsize > WORD_SIZE ? WORD_SIZE : nextsize;
|
||||
System.out.println("Nextsize: " + nextsize);
|
||||
/* calc padding */
|
||||
int pad = nextsize - currType.getSize();
|
||||
return pad;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information string for this MemoryLayout.
|
||||
*
|
||||
* @return String that shows Endianess and word size.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
return sb.append("MemoryLayout: ")
|
||||
.append("Endianess: ").append(order)
|
||||
.append(", WORD_SIZE: ").append(WORD_SIZE)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig. All rights reserved.
|
||||
* Copyright (c) 2006, 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.
|
||||
*/
|
||||
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Represents a mote memory consisting of non-overlapping memory sections with
|
||||
* symbol addresses.
|
||||
* <p>
|
||||
* Every section must implement MemoyInterface.
|
||||
* <p>
|
||||
* Implements MemoryInterface by forwarding calls to available sections or returning
|
||||
* an error if no section is available.
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
* @author Enrico Jorns
|
||||
*/
|
||||
public class SectionMoteMemory implements MemoryInterface {
|
||||
private static Logger logger = Logger.getLogger(SectionMoteMemory.class);
|
||||
private static final boolean DEBUG = logger.isDebugEnabled();
|
||||
|
||||
private Map<String, MemoryInterface> sections = new HashMap<>();
|
||||
|
||||
private final Map<String, Symbol> symbols;
|
||||
private MemoryLayout memLayout;
|
||||
private long startAddr = Long.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* @param symbols Symbol addresses
|
||||
*/
|
||||
public SectionMoteMemory(Map<String, Symbol> symbols) {
|
||||
this.symbols = symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a section to this memory.
|
||||
*
|
||||
* A new section will be checked for address overlap with existing sections.
|
||||
*
|
||||
* @param name
|
||||
* @param section
|
||||
* @return true if adding succeeded, false otherwise
|
||||
*/
|
||||
public boolean addMemorySection(String name ,MemoryInterface section) {
|
||||
|
||||
if (section == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Cooja address space */
|
||||
for (MemoryInterface sec : sections.values()) {
|
||||
/* check for overlap with existing region */
|
||||
if ((section.getStartAddr() <= sec.getStartAddr() + sec.getTotalSize() - 1)
|
||||
&& (section.getStartAddr() + section.getTotalSize() - 1 >= sec.getStartAddr())) {
|
||||
logger.error(String.format(
|
||||
"Failed adding section '%s' of size %d @0x%x",
|
||||
name,
|
||||
section.getTotalSize(),
|
||||
section.getStartAddr()));
|
||||
return false;
|
||||
}
|
||||
/* Min start address is main start address */
|
||||
startAddr = sec.getStartAddr() < startAddr ? sec.getStartAddr() : startAddr;
|
||||
/* Layout is last layout. XXX Check layout consistency? */
|
||||
memLayout = section.getLayout();
|
||||
}
|
||||
|
||||
sections.put(name, section);
|
||||
if (section.getSymbolMap() != null) {
|
||||
for (String s : section.getSymbolMap().keySet()) {
|
||||
// XXX how to handle double names here?
|
||||
symbols.put(s, section.getSymbolMap().get(s));
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
logger.debug(String.format(
|
||||
"Added section '%s' of size %d @0x%x",
|
||||
name,
|
||||
section.getTotalSize(),
|
||||
section.getStartAddr()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of sections in this memory.
|
||||
*
|
||||
* @return Number of sections
|
||||
*/
|
||||
public int getNumberOfSections() {
|
||||
return sections.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns memory section of this memory.
|
||||
* @param name Name of section
|
||||
* @return memory section
|
||||
*/
|
||||
public MemoryInterface getSection(String name) {
|
||||
for (String memsec : sections.keySet()) {
|
||||
if (memsec.equals(name)) {
|
||||
return sections.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn("Section '" + name + "' not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all sections of this memory.
|
||||
* @return All memory sections
|
||||
*/
|
||||
public Map<String, MemoryInterface> getSections() {
|
||||
return sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if given address is part of this memory section.
|
||||
*
|
||||
* @param intf
|
||||
* @param addr
|
||||
* Address
|
||||
* @return True if given address is part of this memory section, false
|
||||
* otherwise
|
||||
*/
|
||||
public static boolean includesAddr(MemoryInterface intf, long addr) {
|
||||
return addr >= intf.getStartAddr() && addr < (intf.getStartAddr() + intf.getTotalSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the whole address range specified by address and size
|
||||
* lies inside this memory section.
|
||||
*
|
||||
* @param intf
|
||||
* @param addr Start address of segment to check
|
||||
* @param size Size of segment to check
|
||||
*
|
||||
* @return True if given address range lies inside address range of this
|
||||
* section
|
||||
*/
|
||||
public static boolean inSection(MemoryInterface intf, long addr, int size) {
|
||||
return addr >= intf.getStartAddr() && addr + size <= intf.getStartAddr() + intf.getTotalSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearMemory() {
|
||||
sections.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalSize() {
|
||||
int totalSize = 0;
|
||||
for (MemoryInterface section : sections.values()) {
|
||||
totalSize += section.getTotalSize();
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getMemory() throws MoteMemoryException {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns memory segment from section matching segment given by address and size
|
||||
* @param address start address of segment to get
|
||||
* @param size size of segmetn to get
|
||||
* @return Array containing data of segment
|
||||
* @throws MoteMemoryException if no single section containing the given address range was found
|
||||
*/
|
||||
@Override
|
||||
public byte[] getMemorySegment(long address, int size) throws MoteMemoryException {
|
||||
|
||||
for (MemoryInterface section : sections.values()) {
|
||||
if (includesAddr(section, address) && includesAddr(section, address + size - 1)) {
|
||||
return section.getMemorySegment(address, size);
|
||||
}
|
||||
}
|
||||
|
||||
throw new MoteMemoryException(
|
||||
"Getting memory segment [0x%x,0x%x] failed: No section available",
|
||||
address, address + size - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets memory segment of section matching segment given by address and size.
|
||||
* @param address start address of segment to set
|
||||
* @param data data to set
|
||||
* @throws MoteMemoryException if no single section containing the given address range was found
|
||||
* or memory is readonly.
|
||||
*/
|
||||
@Override
|
||||
public void setMemorySegment(long address, byte[] data) throws MoteMemoryException {
|
||||
|
||||
for (MemoryInterface section : sections.values()) {
|
||||
if (inSection(section, address, data.length)) {
|
||||
section.setMemorySegment(address, data);
|
||||
if (DEBUG) {
|
||||
logger.debug(String.format(
|
||||
"Wrote memory segment [0x%x,0x%x]",
|
||||
address, address + data.length - 1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new MoteMemoryException(
|
||||
"Writing memory segment [0x%x,0x%x] failed: No section available",
|
||||
address, address + data.length - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartAddr() {
|
||||
return startAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Symbol> getSymbolMap() {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryLayout getLayout() {
|
||||
return memLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addSegmentMonitor(SegmentMonitor.EventType flag, long address, int size, SegmentMonitor monitor) {
|
||||
PolledMemorySegments t = new PolledMemorySegments(monitor, address, size);
|
||||
polledMemories.add(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor monitor) {
|
||||
for (PolledMemorySegments mcm: polledMemories) {
|
||||
if (mcm.mm != monitor || mcm.address != address || mcm.size != size) {
|
||||
continue;
|
||||
}
|
||||
polledMemories.remove(mcm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Copies seciton memory to new (array backed) one
|
||||
* @return Cloned memory
|
||||
*/
|
||||
@Override
|
||||
public SectionMoteMemory clone() {
|
||||
|
||||
SectionMoteMemory clone = new SectionMoteMemory(symbols);
|
||||
|
||||
for (String secname : sections.keySet()) {
|
||||
// Copy section memory to new ArrayMemory
|
||||
MemoryInterface section = sections.get(secname);
|
||||
MemoryInterface cpmem = new ArrayMemory(section.getStartAddr(), section.getLayout(), section.getMemory().clone(), section.getSymbolMap());
|
||||
clone.addMemorySection(secname, cpmem);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
private ArrayList<PolledMemorySegments> polledMemories = new ArrayList<PolledMemorySegments>();
|
||||
public void pollForMemoryChanges() {
|
||||
for (PolledMemorySegments mem: polledMemories.toArray(new PolledMemorySegments[0])) {
|
||||
mem.notifyIfChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private class PolledMemorySegments {
|
||||
public final SegmentMonitor mm;
|
||||
public final long address;
|
||||
public final int size;
|
||||
private byte[] oldMem;
|
||||
|
||||
public PolledMemorySegments(SegmentMonitor mm, long address, int size) {
|
||||
this.mm = mm;
|
||||
this.address = address;
|
||||
this.size = size;
|
||||
|
||||
oldMem = getMemorySegment(address, size);
|
||||
}
|
||||
|
||||
private void notifyIfChanged() {
|
||||
byte[] newMem = getMemorySegment(address, size);
|
||||
if (Arrays.equals(oldMem, newMem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mm.memoryChanged(SectionMoteMemory.this, SegmentMonitor.EventType.WRITE, address);
|
||||
oldMem = newMem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Enrico Joerns
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
/**
|
||||
* Unknown variable name exception.
|
||||
*/
|
||||
public class UnknownVariableException extends RuntimeException {
|
||||
|
||||
public UnknownVariableException(String varName) {
|
||||
super("Unknown variable name: " + varName);
|
||||
}
|
||||
|
||||
}
|
387
tools/cooja/java/org/contikios/cooja/mote/memory/VarMemory.java
Normal file
387
tools/cooja/java/org/contikios/cooja/mote/memory/VarMemory.java
Normal file
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright (c) 2014, TU Braunschweig.
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
package org.contikios.cooja.mote.memory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor.EventType;
|
||||
|
||||
/**
|
||||
* Represents memory that can be accessed with names of variables.
|
||||
*
|
||||
* @author Enrico Jorns
|
||||
*/
|
||||
public class VarMemory extends Memory {
|
||||
|
||||
private MemoryInterface memIntf;
|
||||
|
||||
/**
|
||||
* Creates new VarMemory.
|
||||
*
|
||||
* @param intf
|
||||
*/
|
||||
public VarMemory(MemoryInterface intf) {
|
||||
super(intf);
|
||||
memIntf = intf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to change the MemoryInterface associated with this access class.
|
||||
*
|
||||
* @param intf Interface to associate with
|
||||
*/
|
||||
public void associateMemory(MemoryInterface intf) {
|
||||
memIntf = intf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and returns an array of all variables in this memory
|
||||
*
|
||||
* @return All variables located in this memory
|
||||
*/
|
||||
public Collection<Symbol> getVariables() {
|
||||
return memIntf.getSymbolMap().values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an array of all variable names in this memory.
|
||||
*
|
||||
* @return All variable names located in this memory
|
||||
*/
|
||||
public Set<String> getVariableNames() {
|
||||
return memIntf.getSymbolMap().keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given variable exists in memory.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return True if variable exists, false otherwise
|
||||
*/
|
||||
public boolean variableExists(String varName) {
|
||||
return memIntf.getSymbolMap().containsKey(varName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns address of variable with given name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return Variable address
|
||||
*/
|
||||
public Symbol getVariable(String varName) throws UnknownVariableException {
|
||||
Symbol sym = memIntf.getSymbolMap().get(varName);
|
||||
if (sym == null) {
|
||||
throw new UnknownVariableException(varName);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns address of variable with given name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return Address of variable
|
||||
* @throws UnknownVariableException If variable not found
|
||||
*/
|
||||
public long getVariableAddress(String varName) throws UnknownVariableException {
|
||||
return getVariable(varName).addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of variable with given name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return Size of variable, -1 if unknown size
|
||||
* @throws UnknownVariableException If variable not found
|
||||
*/
|
||||
public int getVariableSize(String varName) throws UnknownVariableException {
|
||||
return getVariable(varName).size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 8 bit integer from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return 8 bit integer value read from location assigned to variable name
|
||||
*/
|
||||
public byte getInt8ValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
return getInt8ValueOf(getVariable(varName).addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 16 bit integer from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return 16 bit integer value read from location assigned to variable name
|
||||
*/
|
||||
public short getInt16ValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
return getInt16ValueOf(getVariable(varName).addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 32 bit integer from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return 32 bit integer value read from location assigned to variable name
|
||||
*/
|
||||
public int getInt32ValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
return getInt32ValueOf(getVariable(varName).addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 64 bit integer from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return 64 bit integer value read from location assigned to variable name
|
||||
*/
|
||||
public long getInt64ValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
return getInt64ValueOf(getVariable(varName).addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read byte from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return byte value read from location assigned to variable name
|
||||
*/
|
||||
public byte getByteValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
return getByteValueOf(getVariable(varName).addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read short from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return short value read from location assigned to variable name
|
||||
*/
|
||||
public short getShortValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
short val = getShortValueOf(getVariable(varName).addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read integer from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return integer value read from location assigned to variable name
|
||||
*/
|
||||
public int getIntValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
int val = getIntValueOf(getVariable(varName).addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read long from location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return long value read from location assigned to variable name
|
||||
*/
|
||||
public long getLongValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
long val = getLongValueOf(getVariable(varName).addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read pointer from location associated with this variable name.
|
||||
*
|
||||
* The number of bytes actually read depends on the pointer size
|
||||
* defined in memory layout.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @return pointer value read from location assigned to variable name
|
||||
*/
|
||||
public long getAddrValueOf(String varName)
|
||||
throws UnknownVariableException {
|
||||
long val = getAddrValueOf(getVariable(varName).addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read byte array starting at location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param length Numbe of bytes to read
|
||||
* @return byte array read from location assigned to variable name
|
||||
*/
|
||||
public byte[] getByteArray(String varName, int length)
|
||||
throws UnknownVariableException {
|
||||
return memIntf.getMemorySegment(getVariable(varName).addr, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 8 bit integer value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value 8 bit integer value to write
|
||||
*/
|
||||
public void setInt8ValueOf(String varName, byte value)
|
||||
throws UnknownVariableException {
|
||||
setInt8ValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 16 bit integer value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value 16 bit integer value to write
|
||||
*/
|
||||
public void setInt16ValueOf(String varName, byte value)
|
||||
throws UnknownVariableException {
|
||||
setInt16ValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 32 bit integer value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value 32 bit integer value to write
|
||||
*/
|
||||
public void setInt32ValueOf(String varName, byte value)
|
||||
throws UnknownVariableException {
|
||||
setInt32ValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 64 bit integer value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value 64 bit integer value to write
|
||||
*/
|
||||
public void setInt64ValueOf(String varName, byte value)
|
||||
throws UnknownVariableException {
|
||||
setInt64ValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write byte value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value byte value to write
|
||||
*/
|
||||
public void setByteValueOf(String varName, byte value)
|
||||
throws UnknownVariableException {
|
||||
setByteValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write short value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value short value to write
|
||||
*/
|
||||
public void setShortValueOf(String varName, short value)
|
||||
throws UnknownVariableException {
|
||||
setShortValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write int value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value int value to write
|
||||
*/
|
||||
public void setIntValueOf(String varName, int value)
|
||||
throws UnknownVariableException {
|
||||
setIntValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write long value to location associated with this variable name.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value long value to write
|
||||
*/
|
||||
public void setLongValueOf(String varName, long value)
|
||||
throws UnknownVariableException {
|
||||
setLongValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write pointer value to location associated with this variable name.
|
||||
*
|
||||
* The number of bytes actually written depends on the pointer size
|
||||
* defined in memory layout.
|
||||
*
|
||||
* @param varName Variable name
|
||||
* @param value Value to write
|
||||
*/
|
||||
public void setAddrValueOf(String varName, long value)
|
||||
throws UnknownVariableException {
|
||||
setAddrValueOf(getVariable(varName).addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param varName
|
||||
* @param data
|
||||
*/
|
||||
public void setByteArray(String varName, byte[] data)
|
||||
throws UnknownVariableException {
|
||||
memIntf.setMemorySegment(getVariable(varName).addr, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a MemoryMonitor for the specified address region.
|
||||
*
|
||||
* @param flag Select memory operation(s) to listen for (read, write,
|
||||
* read/write)
|
||||
* @param varName
|
||||
* @param mm
|
||||
* @return
|
||||
*/
|
||||
public boolean addVarMonitor(EventType flag, final String varName, final SegmentMonitor mm) {
|
||||
return memIntf.addSegmentMonitor(
|
||||
flag,
|
||||
getVariable(varName).addr,
|
||||
getVariable(varName).size,
|
||||
mm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes MemoryMonitor assigned to the specified region.
|
||||
*
|
||||
* @param varName
|
||||
* @param mm MemoryMonitor to remove
|
||||
*/
|
||||
public void removeVarMonitor(String varName, SegmentMonitor mm) {
|
||||
memIntf.removeSegmentMonitor(getVariable(varName).addr, getVariable(varName).size, mm);
|
||||
}
|
||||
}
|
|
@ -33,21 +33,22 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteInterface;
|
||||
import org.contikios.cooja.MoteInterfaceHandler;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.MoteType;
|
||||
import org.contikios.cooja.RadioPacket;
|
||||
import org.contikios.cooja.SectionMoteMemory;
|
||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.interfaces.ApplicationRadio;
|
||||
import org.contikios.cooja.interfaces.ApplicationSerialPort;
|
||||
import org.contikios.cooja.interfaces.Radio;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
|
||||
import org.contikios.cooja.mote.memory.MemoryLayout;
|
||||
|
||||
/**
|
||||
* Abstract application mote.
|
||||
|
@ -67,6 +68,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
|
|||
|
||||
/* Observe our own radio for incoming radio packets */
|
||||
private Observer radioDataObserver = new Observer() {
|
||||
@Override
|
||||
public void update(Observable obs, Object obj) {
|
||||
ApplicationRadio radio = (ApplicationRadio) obs;
|
||||
if (radio.getLastEvent() == Radio.RadioEvent.RECEPTION_FINISHED) {
|
||||
|
@ -89,7 +91,8 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
|
|||
public AbstractApplicationMote(MoteType moteType, Simulation sim) {
|
||||
setSimulation(sim);
|
||||
this.moteType = moteType;
|
||||
this.memory = new SectionMoteMemory(new HashMap<String, Integer>(), 0);
|
||||
MemoryLayout.getNative();
|
||||
this.memory = new SectionMoteMemory(new HashMap<String, Symbol>());
|
||||
this.moteInterfaces = new MoteInterfaceHandler(this, moteType.getMoteInterfaceClasses());
|
||||
this.moteInterfaces.getRadio().addObserver(radioDataObserver);
|
||||
requestImmediateWakeup();
|
||||
|
@ -99,6 +102,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
|
|||
((ApplicationSerialPort)moteInterfaces.getLog()).triggerLog(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoteInterfaceHandler getInterfaces() {
|
||||
return moteInterfaces;
|
||||
}
|
||||
|
@ -107,14 +111,16 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
|
|||
moteInterfaces = moteInterfaceHandler;
|
||||
}
|
||||
|
||||
public MoteMemory getMemory() {
|
||||
@Override
|
||||
public MemoryInterface getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
public void setMemory(MoteMemory memory) {
|
||||
public void setMemory(SectionMoteMemory memory) {
|
||||
this.memory = (SectionMoteMemory) memory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoteType getType() {
|
||||
return moteType;
|
||||
}
|
||||
|
@ -123,6 +129,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
|
|||
moteType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Element> getConfigXML() {
|
||||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
@ -141,10 +148,11 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
|
|||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setConfigXML(Simulation simulation,
|
||||
Collection<Element> configXML, boolean visAvailable) {
|
||||
setSimulation(simulation);
|
||||
this.memory = new SectionMoteMemory(new HashMap<String, Integer>(), 0);
|
||||
this.memory = new SectionMoteMemory(new HashMap<String, Symbol>());
|
||||
moteInterfaces.getRadio().addObserver(radioDataObserver);
|
||||
|
||||
for (Element element : configXML) {
|
||||
|
@ -176,10 +184,12 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID() {
|
||||
return moteInterfaces.getMoteID().getMoteID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AppMote " + getID();
|
||||
}
|
||||
|
|
|
@ -89,8 +89,6 @@ import org.jdom.Element;
|
|||
import org.contikios.cooja.ClassDescription;
|
||||
import org.contikios.cooja.Cooja;
|
||||
import org.contikios.cooja.Mote;
|
||||
import org.contikios.cooja.MoteMemory;
|
||||
import org.contikios.cooja.MoteMemory.MemoryEventType;
|
||||
import org.contikios.cooja.Plugin;
|
||||
import org.contikios.cooja.PluginType;
|
||||
import org.contikios.cooja.SimEventCentral.MoteCountListener;
|
||||
|
@ -100,6 +98,10 @@ import org.contikios.cooja.VisPlugin;
|
|||
import org.contikios.cooja.dialogs.TableColumnAdjuster;
|
||||
import org.contikios.cooja.dialogs.UpdateAggregator;
|
||||
import org.contikios.cooja.interfaces.IPAddress;
|
||||
import org.contikios.cooja.mote.memory.MemoryBuffer;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
import org.contikios.cooja.motes.AbstractEmulatedMote;
|
||||
import org.contikios.cooja.util.ArrayQueue;
|
||||
import org.contikios.cooja.util.StringUtils;
|
||||
|
@ -163,6 +165,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private Parser parser = null;
|
||||
private Buffer buffer = null;
|
||||
@Override
|
||||
public void startPlugin() {
|
||||
super.startPlugin();
|
||||
if (parser == null) {
|
||||
|
@ -214,6 +217,7 @@ public class BufferListener extends VisPlugin {
|
|||
private ArrayList<SegmentMemoryMonitor> memoryMonitors = new ArrayList<SegmentMemoryMonitor>();
|
||||
|
||||
private TimeEvent hourTimeEvent = new TimeEvent(0) {
|
||||
@Override
|
||||
public void execute(long t) {
|
||||
hasHours = true;
|
||||
repaintTimeColumn();
|
||||
|
@ -224,11 +228,13 @@ public class BufferListener extends VisPlugin {
|
|||
private static final int UPDATE_INTERVAL = 250;
|
||||
private UpdateAggregator<BufferAccess> logUpdateAggregator = new UpdateAggregator<BufferAccess>(UPDATE_INTERVAL) {
|
||||
private Runnable scroll = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
logTable.scrollRectToVisible(
|
||||
new Rectangle(0, logTable.getHeight() - 2, 1, logTable.getHeight()));
|
||||
}
|
||||
};
|
||||
@Override
|
||||
protected void handle(List<BufferAccess> ls) {
|
||||
boolean isVisible = true;
|
||||
if (logTable.getRowCount() > 0) {
|
||||
|
@ -276,18 +282,22 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
model = new AbstractTableModel() {
|
||||
private static final long serialVersionUID = 3065150390849332924L;
|
||||
@Override
|
||||
public String getColumnName(int col) {
|
||||
if (col == COLUMN_TIME && formatTimeString) {
|
||||
return "Time";
|
||||
}
|
||||
return COLUMN_NAMES[col];
|
||||
}
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return logs.size();
|
||||
}
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return COLUMN_NAMES.length;
|
||||
}
|
||||
@Override
|
||||
public Object getValueAt(int row, int col) {
|
||||
BufferAccess log = logs.get(row);
|
||||
if (col == COLUMN_TIME) {
|
||||
|
@ -307,6 +317,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
logTable = new JTable(model) {
|
||||
private static final long serialVersionUID = -930616018336483196L;
|
||||
@Override
|
||||
public String getToolTipText(MouseEvent e) {
|
||||
java.awt.Point p = e.getPoint();
|
||||
int rowIndex = rowAtPoint(p);
|
||||
|
@ -356,6 +367,7 @@ public class BufferListener extends VisPlugin {
|
|||
new Color(220, 255, 220),
|
||||
new Color(255, 200, 255),
|
||||
};
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
Object value, boolean isSelected, boolean hasFocus, int row,
|
||||
int column) {
|
||||
|
@ -405,6 +417,7 @@ public class BufferListener extends VisPlugin {
|
|||
logTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
|
||||
logTable.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
||||
logTable.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
|
||||
showInAllAction.actionPerformed(null);
|
||||
|
@ -419,6 +432,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
/* Toggle time format */
|
||||
logTable.getTableHeader().addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
int colIndex = logTable.columnAtPoint(e.getPoint());
|
||||
int columnIndex = logTable.convertColumnIndexToModel(colIndex);
|
||||
|
@ -432,6 +446,7 @@ public class BufferListener extends VisPlugin {
|
|||
});
|
||||
logTable.addMouseListener(new MouseAdapter() {
|
||||
private Parser lastParser = null;
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.getButton() != MouseEvent.BUTTON2) {
|
||||
return;
|
||||
|
@ -444,6 +459,7 @@ public class BufferListener extends VisPlugin {
|
|||
setParser(ByteArrayParser.class);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
if (lastParser != null) {
|
||||
/* Switch back to previous parser */
|
||||
|
@ -451,6 +467,7 @@ public class BufferListener extends VisPlugin {
|
|||
lastParser = null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (lastParser != null) {
|
||||
/* Switch back to previous parser */
|
||||
|
@ -458,6 +475,7 @@ public class BufferListener extends VisPlugin {
|
|||
lastParser = null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
int colIndex = logTable.columnAtPoint(e.getPoint());
|
||||
int columnIndex = logTable.convertColumnIndexToModel(colIndex);
|
||||
|
@ -482,21 +500,27 @@ public class BufferListener extends VisPlugin {
|
|||
/* Popup menu */
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
bufferMenu.addMenuListener(new MenuListener() {
|
||||
@Override
|
||||
public void menuSelected(MenuEvent e) {
|
||||
updateBufferMenu();
|
||||
}
|
||||
@Override
|
||||
public void menuDeselected(MenuEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void menuCanceled(MenuEvent e) {
|
||||
}
|
||||
});
|
||||
popupMenu.add(bufferMenu);
|
||||
parserMenu.addMenuListener(new MenuListener() {
|
||||
@Override
|
||||
public void menuSelected(MenuEvent e) {
|
||||
updateParserMenu();
|
||||
}
|
||||
@Override
|
||||
public void menuDeselected(MenuEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void menuCanceled(MenuEvent e) {
|
||||
}
|
||||
});
|
||||
|
@ -521,6 +545,7 @@ public class BufferListener extends VisPlugin {
|
|||
colorCheckbox = new JCheckBoxMenuItem("Mote-specific coloring");
|
||||
popupMenu.add(colorCheckbox);
|
||||
colorCheckbox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
backgroundColors = colorCheckbox.isSelected();
|
||||
repaint();
|
||||
|
@ -529,6 +554,7 @@ public class BufferListener extends VisPlugin {
|
|||
inverseFilterCheckbox = new JCheckBoxMenuItem("Inverse filter");
|
||||
popupMenu.add(inverseFilterCheckbox);
|
||||
inverseFilterCheckbox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
inverseFilter = inverseFilterCheckbox.isSelected();
|
||||
if (inverseFilter) {
|
||||
|
@ -543,6 +569,7 @@ public class BufferListener extends VisPlugin {
|
|||
hideReadsCheckbox = new JCheckBoxMenuItem("Hide READs", hideReads);
|
||||
popupMenu.add(hideReadsCheckbox);
|
||||
hideReadsCheckbox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
hideReads = hideReadsCheckbox.isSelected();
|
||||
setFilter(getFilter());
|
||||
|
@ -553,6 +580,7 @@ public class BufferListener extends VisPlugin {
|
|||
withStackTraceCheckbox = new JCheckBoxMenuItem("Capture stack traces", withStackTrace);
|
||||
popupMenu.add(withStackTraceCheckbox);
|
||||
withStackTraceCheckbox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
withStackTrace = withStackTraceCheckbox.isSelected();
|
||||
setFilter(getFilter());
|
||||
|
@ -564,6 +592,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
/* Column width adjustment */
|
||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
/* Make sure this happens *after* adding history */
|
||||
adjuster.setDynamicAdjustment(true);
|
||||
|
@ -573,6 +602,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
logUpdateAggregator.start();
|
||||
simulation.getEventCentral().addMoteCountListener(logOutputListener = new MoteCountListener() {
|
||||
@Override
|
||||
public void moteWasAdded(Mote mote) {
|
||||
/* Update title */
|
||||
try {
|
||||
|
@ -581,6 +611,7 @@ public class BufferListener extends VisPlugin {
|
|||
logger.warn("Could not monitor buffer on: " + mote, e);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void moteWasRemoved(Mote mote) {
|
||||
/* Update title */
|
||||
stopObserving(mote);
|
||||
|
@ -596,12 +627,14 @@ public class BufferListener extends VisPlugin {
|
|||
filterPanel.add(filterLabel);
|
||||
filterPanel.add(filterTextField);
|
||||
filterTextField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String str = filterTextField.getText();
|
||||
setFilter(str);
|
||||
|
||||
/* Autoscroll */
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int s = logTable.getSelectedRow();
|
||||
if (s < 0) {
|
||||
|
@ -664,23 +697,24 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private void registerSegmentMonitor(int size, boolean notify) throws Exception {
|
||||
byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize);
|
||||
int segmentAddress = mote.getMemory().parseInt(pointerValue);
|
||||
int segmentAddress = MemoryBuffer.wrap(mote.getMemory().getLayout(), pointerValue).getInt();
|
||||
|
||||
segmentMonitor = new SegmentMemoryMonitor(bl, mote, segmentAddress, size);
|
||||
if (notify) {
|
||||
segmentMonitor.memoryChanged(mote.getMemory(), MemoryEventType.WRITE, -1);
|
||||
segmentMonitor.memoryChanged(mote.getMemory(), EventType.WRITE, -1);
|
||||
}
|
||||
lastSegmentAddress = segmentAddress;
|
||||
}
|
||||
|
||||
final public void memoryChanged(MoteMemory memory,
|
||||
org.contikios.cooja.MoteMemory.MemoryEventType type, int address) {
|
||||
if (type == MemoryEventType.READ) {
|
||||
@Override
|
||||
final public void memoryChanged(MemoryInterface memory,
|
||||
EventType type, long address) {
|
||||
if (type == EventType.READ) {
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize);
|
||||
int segmentAddress = mote.getMemory().parseInt(pointerValue);
|
||||
int segmentAddress = MemoryBuffer.wrap(mote.getMemory().getLayout(), pointerValue).getInt();
|
||||
if (segmentAddress == lastSegmentAddress) {
|
||||
return;
|
||||
}
|
||||
|
@ -694,17 +728,19 @@ public class BufferListener extends VisPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryMonitorType getType() {
|
||||
return MemoryMonitorType.POINTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
segmentMonitor.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static class SegmentMemoryMonitor implements org.contikios.cooja.MoteMemory.MemoryMonitor {
|
||||
static class SegmentMemoryMonitor implements SegmentMonitor {
|
||||
protected final BufferListener bl;
|
||||
protected final Mote mote;
|
||||
|
||||
|
@ -721,7 +757,7 @@ public class BufferListener extends VisPlugin {
|
|||
this.size = size;
|
||||
|
||||
if (address != 0) {
|
||||
if (!mote.getMemory().addMemoryMonitor(address, size, this)) {
|
||||
if (!mote.getMemory().addSegmentMonitor(SegmentMonitor.EventType.WRITE, address, size, this)) {
|
||||
throw new Exception("Could not register memory monitor on: " + mote);
|
||||
}
|
||||
}
|
||||
|
@ -742,17 +778,18 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
public void dispose() {
|
||||
if (address != 0) {
|
||||
mote.getMemory().removeMemoryMonitor(address, size, this);
|
||||
mote.getMemory().removeSegmentMonitor(address, size, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) {
|
||||
@Override
|
||||
public void memoryChanged(MemoryInterface memory, EventType type, long address) {
|
||||
byte[] newData = getAddress()==0?null:mote.getMemory().getMemorySegment(getAddress(), getSize());
|
||||
addBufferAccess(bl, mote, oldData, newData, type, this.address);
|
||||
oldData = newData;
|
||||
}
|
||||
|
||||
void addBufferAccess(BufferListener bl, Mote mote, byte[] oldData, byte[] newData, MemoryEventType type, int address) {
|
||||
void addBufferAccess(BufferListener bl, Mote mote, byte[] oldData, byte[] newData, EventType type, int address) {
|
||||
BufferAccess ba = new BufferAccess(
|
||||
mote,
|
||||
mote.getSimulation().getSimulationTime(),
|
||||
|
@ -793,6 +830,7 @@ public class BufferListener extends VisPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closePlugin() {
|
||||
if (hourTimeEvent != null) hourTimeEvent.remove();
|
||||
|
||||
|
@ -805,6 +843,7 @@ public class BufferListener extends VisPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Element> getConfigXML() {
|
||||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
@ -845,12 +884,14 @@ public class BufferListener extends VisPlugin {
|
|||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element : configXML) {
|
||||
String name = element.getName();
|
||||
if ("filter".equals(name)) {
|
||||
final String str = element.getText();
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setFilter(str);
|
||||
}
|
||||
|
@ -914,10 +955,11 @@ public class BufferListener extends VisPlugin {
|
|||
regexp = null;
|
||||
}
|
||||
RowFilter<Object, Object> wrapped = new RowFilter<Object, Object>() {
|
||||
@Override
|
||||
public boolean include(RowFilter.Entry<? extends Object, ? extends Object> entry) {
|
||||
if (hideReads) {
|
||||
int row = (Integer) entry.getIdentifier();
|
||||
if (logs.get(row).type == MemoryEventType.READ) {
|
||||
if (logs.get(row).type == SegmentMonitor.EventType.READ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -945,6 +987,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
public void trySelectTime(final long time) {
|
||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i=0; i < logs.size(); i++) {
|
||||
if (logs.get(i).time < time) {
|
||||
|
@ -972,13 +1015,13 @@ public class BufferListener extends VisPlugin {
|
|||
public final byte[] mem;
|
||||
private boolean[] accessedBitpattern = null;
|
||||
|
||||
public final MemoryEventType type;
|
||||
public final SegmentMonitor.EventType type;
|
||||
public final String sourceStr;
|
||||
public final String stackTrace;
|
||||
public final int address;
|
||||
|
||||
public BufferAccess(
|
||||
Mote mote, long time, int address, byte[] newData, byte[] oldData, MemoryEventType type, boolean withStackTrace) {
|
||||
Mote mote, long time, int address, byte[] newData, byte[] oldData, SegmentMonitor.EventType type, boolean withStackTrace) {
|
||||
this.mote = mote;
|
||||
this.time = time;
|
||||
this.mem = newData==null?NULL_DATA:newData;
|
||||
|
@ -1054,6 +1097,7 @@ public class BufferListener extends VisPlugin {
|
|||
private Action saveAction = new AbstractAction("Save to file") {
|
||||
private static final long serialVersionUID = -4140706275748686944L;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser fc = new JFileChooser();
|
||||
File suggest = new File(Cooja.getExternalToolsSetting("BUFFER_LISTENER_SAVEFILE", "BufferAccessLogger.txt"));
|
||||
|
@ -1116,6 +1160,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private Action bufferListenerAction = new AbstractAction("in Buffer Listener") {
|
||||
private static final long serialVersionUID = -6358463434933029699L;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int view = logTable.getSelectedRow();
|
||||
if (view < 0) {
|
||||
|
@ -1139,6 +1184,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private Action timeLineAction = new AbstractAction("in Timeline") {
|
||||
private static final long serialVersionUID = -6358463434933029699L;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int view = logTable.getSelectedRow();
|
||||
if (view < 0) {
|
||||
|
@ -1162,6 +1208,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private Action radioLoggerAction = new AbstractAction("in Radio Logger") {
|
||||
private static final long serialVersionUID = -3041714249257346688L;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int view = logTable.getSelectedRow();
|
||||
if (view < 0) {
|
||||
|
@ -1189,6 +1236,7 @@ public class BufferListener extends VisPlugin {
|
|||
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
timeLineAction.actionPerformed(null);
|
||||
radioLoggerAction.actionPerformed(null);
|
||||
|
@ -1197,6 +1245,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private Action clearAction = new AbstractAction("Clear") {
|
||||
private static final long serialVersionUID = -2115620313183440224L;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int size = logs.size();
|
||||
if (size > 0) {
|
||||
|
@ -1208,6 +1257,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private Action copyAction = new AbstractAction("Selected") {
|
||||
private static final long serialVersionUID = -8433490108577001803L;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
|
||||
|
@ -1240,6 +1290,7 @@ public class BufferListener extends VisPlugin {
|
|||
private Action copyAllAction = new AbstractAction("All") {
|
||||
private static final long serialVersionUID = -5038884975254178373L;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
|
||||
|
@ -1269,6 +1320,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private final ActionListener parserSelectedListener = new ActionListener() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Class<? extends Parser> bpClass =
|
||||
(Class<? extends Parser>)
|
||||
|
@ -1289,6 +1341,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
private final ActionListener bufferSelectedListener = new ActionListener() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Class<? extends Buffer> btClass =
|
||||
(Class<? extends Buffer>)
|
||||
|
@ -1421,6 +1474,7 @@ public class BufferListener extends VisPlugin {
|
|||
}
|
||||
public static abstract class GraphicalParser implements Parser {
|
||||
BufferAccess ba = null;
|
||||
@Override
|
||||
public Object parse(BufferAccess ba) {
|
||||
this.ba = ba;
|
||||
return ba;
|
||||
|
@ -1430,6 +1484,7 @@ public class BufferListener extends VisPlugin {
|
|||
}
|
||||
|
||||
public static abstract class StringParser implements Parser {
|
||||
@Override
|
||||
public Object parse(BufferAccess ba) {
|
||||
return parseString(ba);
|
||||
}
|
||||
|
@ -1459,13 +1514,17 @@ public class BufferListener extends VisPlugin {
|
|||
public void writeConfig(Element element);
|
||||
}
|
||||
public static abstract class AbstractBuffer implements Buffer {
|
||||
@Override
|
||||
public String getStatusString() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void writeConfig(Element element) {
|
||||
}
|
||||
@Override
|
||||
public void applyConfig(Element element) {
|
||||
}
|
||||
@Override
|
||||
public boolean configure(BufferListener bl) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1474,18 +1533,20 @@ public class BufferListener extends VisPlugin {
|
|||
public static abstract class PointerBuffer extends AbstractBuffer {
|
||||
public abstract int getPointerAddress(Mote mote);
|
||||
|
||||
@Override
|
||||
public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote)
|
||||
throws Exception {
|
||||
return new PointerMemoryMonitor(
|
||||
bl,
|
||||
mote,
|
||||
getPointerAddress(mote),
|
||||
mote.getMemory().getIntegerLength(),
|
||||
mote.getMemory().getLayout().intSize,
|
||||
getSize(mote)
|
||||
);
|
||||
}
|
||||
}
|
||||
public static abstract class SegmentBuffer extends AbstractBuffer {
|
||||
@Override
|
||||
public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote)
|
||||
throws Exception {
|
||||
return new SegmentMemoryMonitor(
|
||||
|
@ -1521,6 +1582,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("Byte array")
|
||||
public static class ByteArrayParser extends StringParser {
|
||||
@Override
|
||||
public String parseString(BufferAccess ba) {
|
||||
boolean[] diff = ba.getAccessedBitpattern();
|
||||
if (diff == null) {
|
||||
|
@ -1562,15 +1624,18 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("Integer array")
|
||||
public static class IntegerParser extends StringParser {
|
||||
private VarMemory varMem = new VarMemory(null);
|
||||
@Override
|
||||
public String parseString(BufferAccess ba) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
varMem.associateMemory(ba.mote.getMemory());
|
||||
|
||||
int intLen = ba.mote.getMemory().getIntegerLength();
|
||||
int intLen = ba.mote.getMemory().getLayout().intSize;
|
||||
sb.append("<html>");
|
||||
for (int i=0; i < ba.mem.length/intLen; i++) {
|
||||
byte[] mem = Arrays.copyOfRange(ba.mem, i*intLen,(i+1)*intLen);
|
||||
boolean[] diff = Arrays.copyOfRange(ba.getAccessedBitpattern(), i*intLen,(i+1)*intLen);
|
||||
int val = ba.mote.getMemory().parseInt(mem);
|
||||
int val = MemoryBuffer.wrap(ba.mote.getMemory().getLayout(), mem).getInt();
|
||||
|
||||
boolean red = false;
|
||||
for (boolean changed: diff) {
|
||||
|
@ -1592,6 +1657,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("Terminated string")
|
||||
public static class TerminatedStringParser extends StringParser {
|
||||
@Override
|
||||
public String parseString(BufferAccess ba) {
|
||||
/* TODO Diff? */
|
||||
int i;
|
||||
|
@ -1608,6 +1674,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("Printable characters")
|
||||
public static class PrintableCharactersParser extends StringParser {
|
||||
@Override
|
||||
public String parseString(BufferAccess ba) {
|
||||
/* TODO Diff? */
|
||||
return new String(ba.mem).replaceAll("[^\\p{Print}]", "");
|
||||
|
@ -1616,6 +1683,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("IPv6 address")
|
||||
public static class IPv6AddressParser extends StringParser {
|
||||
@Override
|
||||
public String parseString(BufferAccess ba) {
|
||||
/* TODO Diff? */
|
||||
if (ba.mem.length < 16) {
|
||||
|
@ -1634,6 +1702,7 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("IPv4 address")
|
||||
public static class IPv4AddressParser extends StringParser {
|
||||
@Override
|
||||
public String parseString(BufferAccess ba) {
|
||||
/* TODO Diff? */
|
||||
if (ba.mem.length < 4) {
|
||||
|
@ -1664,6 +1733,7 @@ public class BufferListener extends VisPlugin {
|
|||
parser.ba = ba;
|
||||
setPreferredSize(new Dimension(parser.getUnscaledWidth() + 2*XOFFSET, HEIGHT));
|
||||
}
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
g.translate(XOFFSET, 0);
|
||||
|
@ -1681,9 +1751,11 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("Graphical: Height")
|
||||
public static class GraphicalHeight4BitsParser extends GraphicalParser {
|
||||
@Override
|
||||
public int getUnscaledWidth() {
|
||||
return ba.mem.length*2;
|
||||
}
|
||||
@Override
|
||||
public void paintComponent(Graphics g, JComponent c) {
|
||||
g.setColor(Color.GRAY);
|
||||
boolean[] diff = ba.getAccessedBitpattern();
|
||||
|
@ -1707,9 +1779,11 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("Graphical: Grayscale")
|
||||
public static class GraphicalGrayscale4BitsParser extends GraphicalParser {
|
||||
@Override
|
||||
public int getUnscaledWidth() {
|
||||
return ba.mem.length*2;
|
||||
}
|
||||
@Override
|
||||
public void paintComponent(Graphics g, JComponent c) {
|
||||
boolean[] diff = ba.getAccessedBitpattern();
|
||||
for (int x=0; x < ba.mem.length; x++) {
|
||||
|
@ -1730,27 +1804,31 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("Variable: node_id")
|
||||
public static class NodeIDBuffer extends SegmentBuffer {
|
||||
@Override
|
||||
public int getAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists("node_id")) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey("node_id")) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getVariableAddress("node_id");
|
||||
return (int) mote.getMemory().getSymbolMap().get("node_id").addr;
|
||||
}
|
||||
@Override
|
||||
public int getSize(Mote mote) {
|
||||
return mote.getMemory().getIntegerLength();
|
||||
return mote.getMemory().getLayout().intSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ClassDescription("Queuebuf 0 RAM")
|
||||
public static class Queuebuf0Buffer extends SegmentBuffer {
|
||||
@Override
|
||||
public int getAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists("buframmem")) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey("buframmem")) {
|
||||
return -1;
|
||||
}
|
||||
int offset = 0;
|
||||
return mote.getMemory().getVariableAddress("buframmem") + offset;
|
||||
return (int) mote.getMemory().getSymbolMap().get("buframmem").addr + offset;
|
||||
}
|
||||
@Override
|
||||
public int getSize(Mote mote) {
|
||||
return 128;
|
||||
}
|
||||
|
@ -1758,12 +1836,14 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("packetbuf_aligned")
|
||||
public static class PacketbufBuffer extends SegmentBuffer {
|
||||
@Override
|
||||
public int getAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists("packetbuf_aligned")) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey("packetbuf_aligned")) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getVariableAddress("packetbuf_aligned");
|
||||
return (int) mote.getMemory().getSymbolMap().get("packetbuf_aligned").addr;
|
||||
}
|
||||
@Override
|
||||
public int getSize(Mote mote) {
|
||||
return 128;
|
||||
}
|
||||
|
@ -1771,18 +1851,23 @@ public class BufferListener extends VisPlugin {
|
|||
|
||||
@ClassDescription("*packetbufptr")
|
||||
public static class PacketbufPointerBuffer extends PointerBuffer {
|
||||
VarMemory varMem = new VarMemory(null);
|
||||
@Override
|
||||
public int getPointerAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists("packetbufptr")) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey("packetbufptr")) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getVariableAddress("packetbufptr");
|
||||
return (int) mote.getMemory().getSymbolMap().get("packetbufptr").addr;
|
||||
}
|
||||
@Override
|
||||
public int getAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists("packetbufptr")) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey("packetbufptr")) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getIntValueOf("packetbufptr");
|
||||
varMem.associateMemory(mote.getMemory());
|
||||
return varMem.getIntValueOf("packetbufptr");
|
||||
}
|
||||
@Override
|
||||
public int getSize(Mote mote) {
|
||||
return 128;
|
||||
}
|
||||
|
@ -1793,25 +1878,31 @@ public class BufferListener extends VisPlugin {
|
|||
public String variable;
|
||||
public int size;
|
||||
public int offset;
|
||||
VarMemory varMem = new VarMemory(null);
|
||||
@Override
|
||||
public int getPointerAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists(variable)) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getVariableAddress(variable);
|
||||
return (int) mote.getMemory().getSymbolMap().get(variable).addr;
|
||||
}
|
||||
@Override
|
||||
public int getAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists(variable)) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getIntValueOf(variable)+offset;
|
||||
varMem.associateMemory(mote.getMemory());
|
||||
return varMem.getIntValueOf(variable)+offset;
|
||||
}
|
||||
@Override
|
||||
public int getSize(Mote mote) {
|
||||
if (!mote.getMemory().variableExists(variable)) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
|
||||
return -1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusString() {
|
||||
if (offset > 0) {
|
||||
return "Pointer *" + variable + "[" + offset + "] (" + size + ")";
|
||||
|
@ -1820,16 +1911,19 @@ public class BufferListener extends VisPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeConfig(Element element) {
|
||||
element.setAttribute("variable", variable);
|
||||
element.setAttribute("size", "" + size);
|
||||
element.setAttribute("offset", "" + offset);
|
||||
}
|
||||
@Override
|
||||
public void applyConfig(Element element) {
|
||||
variable = element.getAttributeValue("variable");
|
||||
size = Integer.parseInt(element.getAttributeValue("size"));
|
||||
offset = Integer.parseInt(element.getAttributeValue("offset"));
|
||||
}
|
||||
@Override
|
||||
public boolean configure(BufferListener bl) {
|
||||
String suggestName = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id");
|
||||
String suggestSize = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2");
|
||||
|
@ -1880,19 +1974,22 @@ public class BufferListener extends VisPlugin {
|
|||
public String variable;
|
||||
public int size;
|
||||
public int offset;
|
||||
@Override
|
||||
public int getAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists(variable)) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getVariableAddress(variable)+offset;
|
||||
return (int) mote.getMemory().getSymbolMap().get(variable).addr+offset;
|
||||
}
|
||||
@Override
|
||||
public int getSize(Mote mote) {
|
||||
if (!mote.getMemory().variableExists(variable)) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
|
||||
return -1;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusString() {
|
||||
if (offset > 0) {
|
||||
return "Symbol &" + variable + "[" + offset + "] (" + size + ")";
|
||||
|
@ -1901,16 +1998,19 @@ public class BufferListener extends VisPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeConfig(Element element) {
|
||||
element.setAttribute("variable", variable);
|
||||
element.setAttribute("size", "" + size);
|
||||
element.setAttribute("offset", "" + offset);
|
||||
}
|
||||
@Override
|
||||
public void applyConfig(Element element) {
|
||||
variable = element.getAttributeValue("variable");
|
||||
size = Integer.parseInt(element.getAttributeValue("size"));
|
||||
offset = Integer.parseInt(element.getAttributeValue("offset"));
|
||||
}
|
||||
@Override
|
||||
public boolean configure(BufferListener bl) {
|
||||
String suggestName = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id");
|
||||
String suggestSize = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2");
|
||||
|
@ -1958,26 +2058,32 @@ public class BufferListener extends VisPlugin {
|
|||
@ClassDescription("Integer...")
|
||||
public static class CustomIntegerBuffer extends SegmentBuffer {
|
||||
public String variable;
|
||||
@Override
|
||||
public int getAddress(Mote mote) {
|
||||
if (!mote.getMemory().variableExists(variable)) {
|
||||
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
|
||||
return -1;
|
||||
}
|
||||
return mote.getMemory().getVariableAddress(variable);
|
||||
return (int) mote.getMemory().getSymbolMap().get(variable).addr;
|
||||
}
|
||||
@Override
|
||||
public int getSize(Mote mote) {
|
||||
return mote.getMemory().getIntegerLength();
|
||||
return mote.getMemory().getLayout().intSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusString() {
|
||||
return "Integer " + variable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeConfig(Element element) {
|
||||
element.setAttribute("variable", variable);
|
||||
}
|
||||
@Override
|
||||
public void applyConfig(Element element) {
|
||||
variable = element.getAttributeValue("variable");
|
||||
}
|
||||
@Override
|
||||
public boolean configure(BufferListener bl) {
|
||||
String suggestName = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id");
|
||||
BufferInput infoComponent =
|
||||
|
|
|
@ -44,8 +44,10 @@ import java.awt.event.KeyListener;
|
|||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
|
@ -64,7 +66,6 @@ import javax.swing.text.PlainDocument;
|
|||
|
||||
import org.jdom.Element;
|
||||
|
||||
import org.contikios.cooja.AddressMemory;
|
||||
import org.contikios.cooja.ClassDescription;
|
||||
import org.contikios.cooja.Cooja;
|
||||
import org.contikios.cooja.Mote;
|
||||
|
@ -72,7 +73,8 @@ import org.contikios.cooja.MotePlugin;
|
|||
import org.contikios.cooja.PluginType;
|
||||
import org.contikios.cooja.Simulation;
|
||||
import org.contikios.cooja.VisPlugin;
|
||||
import org.contikios.cooja.AddressMemory.UnknownVariableException;
|
||||
import org.contikios.cooja.mote.memory.UnknownVariableException;
|
||||
import org.contikios.cooja.mote.memory.VarMemory;
|
||||
|
||||
/**
|
||||
* Variable Watcher enables a user to watch mote variables during a simulation.
|
||||
|
@ -87,7 +89,7 @@ import org.contikios.cooja.AddressMemory.UnknownVariableException;
|
|||
public class VariableWatcher extends VisPlugin implements MotePlugin {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AddressMemory moteMemory;
|
||||
private VarMemory moteMemory;
|
||||
|
||||
private final static int LABEL_WIDTH = 170;
|
||||
private final static int LABEL_HEIGHT = 15;
|
||||
|
@ -124,7 +126,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
|
|||
public VariableWatcher(Mote moteToView, Simulation simulation, Cooja gui) {
|
||||
super("Variable Watcher (" + moteToView + ")", gui);
|
||||
this.mote = moteToView;
|
||||
moteMemory = (AddressMemory) moteToView.getMemory();
|
||||
moteMemory = new VarMemory(moteToView.getMemory());
|
||||
|
||||
JLabel label;
|
||||
integerFormat = NumberFormat.getIntegerInstance();
|
||||
|
@ -143,8 +145,8 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
|
|||
varName.setEditable(true);
|
||||
varName.setSelectedItem("[enter or pick name]");
|
||||
|
||||
String[] allPotentialVarNames = moteMemory.getVariableNames();
|
||||
Arrays.sort(allPotentialVarNames);
|
||||
List<String> allPotentialVarNames = new ArrayList<>(moteMemory.getVariableNames());
|
||||
Collections.sort(allPotentialVarNames);
|
||||
for (String aVarName: allPotentialVarNames) {
|
||||
varName.addItem(aVarName);
|
||||
}
|
||||
|
@ -172,7 +174,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
|
|||
|
||||
varType = new JComboBox();
|
||||
varType.addItem("Byte (1 byte)"); // BYTE_INDEX = 0
|
||||
varType.addItem("Integer (" + moteMemory.getIntegerLength() + " bytes)"); // INT_INDEX = 1
|
||||
varType.addItem("Integer (" + moteToView.getMemory().getLayout().intSize + " bytes)"); // INT_INDEX = 1
|
||||
varType.addItem("Byte array (x bytes)"); // ARRAY_INDEX = 2
|
||||
varType.addItem("Char array (x bytes)"); // CHAR_ARRAY_INDEX = 3
|
||||
|
||||
|
|
Loading…
Reference in a new issue