📄 contikimotetype.java
字号:
/* * 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. * * $Id: ContikiMoteType.java,v 1.10 2007/04/02 12:45:19 fros4943 Exp $ */package se.sics.cooja.contikimote;import java.awt.BorderLayout;import java.awt.Dimension;import java.io.*;import java.security.*;import java.util.*;import java.util.regex.*;import javax.swing.*;import org.apache.log4j.Logger;import org.jdom.Element;import se.sics.cooja.*;/** * The Contiki mote type holds the native library used to communicate with an * underlying Contiki system. All communication with that system should always * pass through this mote type. * <p> * This type also contains information about which processes, sensors and core * interfaces a mote of this type has, as well as where the Contiki OS, COOJA * core files and optional mote type specific project directories are located. * <p> * All core communication with the Contiki mote should be via this class. When a * mote type is created it allocates a CoreComm to be used with this type, and * loads a map file. The map file is used to map variable names to addresses. * <p> * When a new mote type is created an initialization function is run on the * Contiki system in order to create the initial memory. When a new mote is * created the createInitialMemory() method should be called to get this initial * memory for the mote. * * @author Fredrik Osterlind */@ClassDescription("Contiki Mote Type")public class ContikiMoteType implements MoteType { private static Logger logger = Logger.getLogger(ContikiMoteType.class); /** * Map file suffix */ final static public String mapSuffix = ".map"; /** * Library file suffix */ final static public String librarySuffix = ".library"; /** * Make dependency file suffix */ final static public String dependSuffix = ".a"; /** * Temporary output directory */ final static public File tempOutputDirectory = new File("obj_cooja"); // Regular expressions for parsing the map file final static private String bssSectionAddrRegExp = "^.bss[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$"; final static private String bssSectionSizeRegExp = "^.bss[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$"; final static private String dataSectionAddrRegExp = "^.data[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$"; final static private String dataSectionSizeRegExp = "^.data[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$"; final static private String varAddressRegExpPrefix = "^[ \t]*0x([0-9A-Fa-f]*)[ \t]*"; final static private String varAddressRegExpSuffix = "[ \t]*$"; final static private String varNameRegExp = "^[ \t]*(0x[0-9A-Fa-f]*)[ \t]*([^ ]*)[ \t]*$"; final static private String varSizeRegExpPrefix = "^"; final static private String varSizeRegExpSuffix = "[ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$"; // Regular expressions for parsing nm response final static private String nmRegExp = "^([0-9A-Fa-f][0-9A-Fa-f]*)[ \t][^Tt][ \t]([^ ._][^ ]*)"; // Mote type specific data private String identifier = null; private String description = null; private String contikiBaseDir = null; private String contikiCoreDir = null; private Vector<File> projectDirs = null; private Vector<File> compilationFiles = null; private Vector<String> processes = null; private Vector<String> sensors = null; private Vector<String> coreInterfaces = null; private Vector<Class<? extends MoteInterface>> moteInterfaces = null; private boolean hasSystemSymbols = false; // Simulation holding this mote type private Simulation mySimulation = null; // Type specific class configuration private ProjectConfig myConfig = null; // Core communication variables private String libraryClassName = null; private int offsetRelToAbs = 0; private CoreComm myCoreComm = null; // Variable name to address mappings private Properties varAddresses = new Properties(); // Initial memory for all motes of this type private SectionMoteMemory initialMemory = null; /** * Creates a new uninitialized Contiki mote type. This mote type needs to load * a library file and parse a map file before it can be used. */ public ContikiMoteType() { } /** * Creates a new Contiki mote type. This type uses two external files: a map * file for parsing relative addresses of Contiki variables (identifier + * ".map") and a library file with an actual compiled Contiki system * (identifier + ".library") * * @param identifier * Unique identifier for this mote type */ public ContikiMoteType(String identifier) throws MoteTypeCreationException { doInit(identifier); } public Mote generateMote(Simulation simulation) { return new ContikiMote(this, simulation); } public boolean configureAndInit(JFrame parentFrame, Simulation simulation, boolean visAvailable) throws MoteTypeCreationException { if (visAvailable) { return ContikiMoteTypeDialog.showDialog(parentFrame, simulation, this); } else { // Create temp output directory if not already exists if (!ContikiMoteType.tempOutputDirectory.exists()) ContikiMoteType.tempOutputDirectory.mkdir(); if (!ContikiMoteType.tempOutputDirectory.exists()) { throw new MoteTypeCreationException("Could not create output directory: " + ContikiMoteType.tempOutputDirectory); } // Delete output files File libFile = new File(ContikiMoteType.tempOutputDirectory, identifier + ContikiMoteType.librarySuffix); File mapFile = new File(ContikiMoteType.tempOutputDirectory, identifier + ContikiMoteType.mapSuffix); File depFile = new File(ContikiMoteType.tempOutputDirectory, identifier + ContikiMoteType.dependSuffix); if (libFile.exists()) libFile.delete(); if (depFile.exists()) depFile.delete(); if (mapFile.exists()) mapFile.delete(); if (libFile.exists()) { throw new MoteTypeCreationException("Could not delete output file: " + libFile); } if (depFile.exists()) { throw new MoteTypeCreationException("Could not delete output file: " + depFile); } if (mapFile.exists()) { throw new MoteTypeCreationException("Could not delete output file: " + mapFile); } // Generate Contiki main source file try { ContikiMoteTypeDialog.generateSourceFile(identifier, sensors, coreInterfaces, processes); } catch (Exception e) { throw new MoteTypeCreationException("Error during main source file generation: " + e.getMessage()); } // Compile library boolean compilationSucceded = ContikiMoteTypeDialog.compileLibrary( identifier, new File(contikiBaseDir), compilationFiles, hasSystemSymbols, null, null); if (!libFile.exists() || !depFile.exists() || !mapFile.exists()) compilationSucceded = false; if (!compilationSucceded) { throw new MoteTypeCreationException("Error during compilation"); } // Load compiled library doInit(identifier); return true; } } /** * This is an mote type initialization method and should normally never be * called by any other part than the mote type constructor. It is called from * the constructor with an identifier argument. but not from the standard * constructor. This method may be called from the simulator when loading * configuration files, and the libraries must be recompiled. * * This method allocates a core communicator, loads the Contiki library file, * loads and parses the map file, creates a variable name to address mapping * of the Contiki system and finally creates the Contiki mote initial memory. * * @param identifier * Mote type identifier */ protected void doInit(String identifier) throws MoteTypeCreationException { this.identifier = identifier; if (myCoreComm != null) { throw new MoteTypeCreationException("Core communicator already used: " + myCoreComm.getClass().getName()); } File libFile = new File(ContikiMoteType.tempOutputDirectory, identifier + librarySuffix); File mapFile = new File(ContikiMoteType.tempOutputDirectory, identifier + mapSuffix); // Check that library file exists if (!libFile.exists()) { throw new MoteTypeCreationException("Library file could not be found: " + libFile); } // Check that map file exists if (!mapFile.exists()) { throw new MoteTypeCreationException("Map file could not be found: " + mapFile); } // Allocate core communicator class libraryClassName = CoreComm.getAvailableClassName(); myCoreComm = CoreComm.createCoreComm(libraryClassName, libFile); // Try load map file Vector<String> mapFileData = loadMapFile(mapFile); // Try load nm data Vector<String> nmData = loadNmData(libFile); // Create variable names to addresses mappings varAddresses.clear(); if (mapFileData == null || !parseMapFileData(mapFileData, varAddresses)) { logger.fatal("Map file parsing failed"); } logger.info("Testing experimental nm response parsing for finding variable addresses"); if (nmData == null || !parseNmData(nmData, varAddresses)) { logger.fatal("Nm response parsing failed"); } if (varAddresses.size() == 0) { throw new MoteTypeCreationException("Variable name to addresses mappings could not be created"); } // Get offset between relative and absolute addresses offsetRelToAbs = getReferenceAbsAddr() - getRelVarAddr(mapFileData, "referenceVar"); // Parse addresses of data and BSS memory sections int relDataSectionAddr = loadRelDataSectionAddr(mapFileData); int dataSectionSize = loadDataSectionSize(mapFileData); int relBssSectionAddr = loadRelBssSectionAddr(mapFileData); int bssSectionSize = loadBssSectionSize(mapFileData); if (relDataSectionAddr <= 0 || dataSectionSize <= 0 || relBssSectionAddr <= 0 || bssSectionSize <= 0) { throw new MoteTypeCreationException("Could not parse section addresses correctly"); } // Create initial memory byte[] initialDataSection = new byte[dataSectionSize]; getCoreMemory(relDataSectionAddr + offsetRelToAbs, dataSectionSize, initialDataSection); byte[] initialBssSection = new byte[bssSectionSize]; getCoreMemory( relBssSectionAddr + offsetRelToAbs, bssSectionSize, initialBssSection); initialMemory = new SectionMoteMemory(varAddresses); initialMemory.setMemorySegment(relDataSectionAddr, initialDataSection); initialMemory.setMemorySegment(relBssSectionAddr, initialBssSection); } /** * Ticks the currently loaded mote. This should not be used directly, but * rather via ContikiMote.tick(). */ public void tick() { myCoreComm.tick(); } /** * Creates and returns a copy of this mote type's initial memory (just after * the init function has been run). When a new mote is created it should get * it's memory from here. * * @return Initial memory of a mote type */ public SectionMoteMemory createInitialMemory() { return initialMemory.clone(); } /** * Copy given memory to the Contiki system. This should not be used directly, * but instead via ContikiMote.setMemory(). * * @param mem * New memory */ public void setCoreMemory(SectionMoteMemory mem) { for (int i = 0; i < mem.getNumberOfSections(); i++) { setCoreMemory(mem.getStartAddrOfSection(i) + offsetRelToAbs, mem .getSizeOfSection(i), mem.getDataOfSection(i)); } } /** * Parses specified map file data for variable name to addresses mappings. The * mappings are added to the given properties object. * * @param mapFileData * Contents of entire map file * @param varAddresses * Properties that should contain the name to addresses mappings. */ private boolean parseMapFileData(Vector<String> mapFileData, Properties varAddresses) { Vector<String> varNames = getMapFileVarNames(mapFileData); if (varNames == null || varNames.size() == 0) return false; for (String varName : varNames) { int varAddress = getMapFileVarAddress(mapFileData, varName); if (varAddress > 0) { varAddresses.put(varName, new Integer(varAddress)); } else logger.warn("Parsed Contiki variable '" + varName + "' but could not find address"); } return true; } /** * Parses specified nm data for variable name to addresses mappings. The * mappings are added to the given properties object. * * @param nmData * Response from nm command on object file * @param varAddresses * Properties that should contain the name to addresses mappings. */ public static boolean parseNmData(Vector<String> nmData, Properties varAddresses) { int nrNew = 0, nrOld = 0, nrMismatch = 0; Pattern pattern = Pattern.compile(nmRegExp); for (String nmLine: nmData) { Matcher matcher = pattern.matcher(nmLine); if (matcher.find()) { //logger.debug("Parsing line: " + nmLine); String varName = matcher.group(2); int varAddress = Integer.parseInt(matcher.group(1), 16); if (!varAddresses.containsKey(varName)) { nrNew++; varAddresses.put(varName, new Integer(varAddress)); } else { int oldAddress = (Integer) varAddresses.get(varName); if (oldAddress != varAddress) { logger.warn("Warning, nm response not matching previous entry of: " + varName); nrMismatch++; } nrOld++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -