From 3ddcfefe04621e69da7deb619111ed98d1793368 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Wed, 30 May 2012 22:40:54 +0200 Subject: [PATCH] Added ExternalFlash base class for emulation of external flash chips. Replaced FileAT45DB and FileM25P80 with storage abstraction for storing data in memory or on file --- se/sics/mspsim/chip/AT45DB.java | 22 +- se/sics/mspsim/chip/ExternalFlash.java | 68 ++++++ se/sics/mspsim/chip/FileAT45DB.java | 146 ----------- se/sics/mspsim/chip/FileM25P80.java | 180 -------------- se/sics/mspsim/chip/FileStorage.java | 229 ++++++++++++++++++ se/sics/mspsim/chip/M25P16.java | 51 ++++ se/sics/mspsim/chip/M25P80.java | 29 +-- se/sics/mspsim/chip/MemoryStorage.java | 116 +++++++++ se/sics/mspsim/chip/Storage.java | 56 +++++ .../mspsim/platform/jcreate/JCreateNode.java | 10 +- .../platform/sentillausb/SentillaUSBNode.java | 9 +- se/sics/mspsim/platform/sky/CC2420Node.java | 1 - se/sics/mspsim/platform/sky/SkyNode.java | 7 +- se/sics/mspsim/platform/sky/TelosNode.java | 7 +- se/sics/mspsim/platform/z1/Z1Node.java | 17 +- 15 files changed, 572 insertions(+), 376 deletions(-) create mode 100644 se/sics/mspsim/chip/ExternalFlash.java delete mode 100644 se/sics/mspsim/chip/FileAT45DB.java delete mode 100644 se/sics/mspsim/chip/FileM25P80.java create mode 100644 se/sics/mspsim/chip/FileStorage.java create mode 100644 se/sics/mspsim/chip/M25P16.java create mode 100644 se/sics/mspsim/chip/MemoryStorage.java create mode 100644 se/sics/mspsim/chip/Storage.java diff --git a/se/sics/mspsim/chip/AT45DB.java b/se/sics/mspsim/chip/AT45DB.java index 5d07695..3f7135e 100644 --- a/se/sics/mspsim/chip/AT45DB.java +++ b/se/sics/mspsim/chip/AT45DB.java @@ -43,7 +43,7 @@ package se.sics.mspsim.chip; import java.io.IOException; import se.sics.mspsim.core.*; -public abstract class AT45DB extends Chip implements USARTListener { +public class AT45DB extends ExternalFlash implements USARTListener { public static final int PAGE_SIZE = 264; public static final int NUM_PAGES = 2048; @@ -337,11 +337,10 @@ public abstract class AT45DB extends Chip implements USARTListener { private void bufferToPage(int buf) { try { - seek(pageAddress * PAGE_SIZE); if(buf == 1) - write(buffer1); + getStorage().write(pageAddress * PAGE_SIZE, buffer1); else - write(buffer2); + getStorage().write(pageAddress * PAGE_SIZE, buffer2); } catch (IOException e) { e.printStackTrace(); } @@ -349,11 +348,10 @@ public abstract class AT45DB extends Chip implements USARTListener { private void pageToBuffer(int buf) { try { - seek(pageAddress * PAGE_SIZE); if(buf == 1) - read(buffer1); + getStorage().read(pageAddress * PAGE_SIZE, buffer1); else - read(buffer2); + getStorage().read(pageAddress * PAGE_SIZE, buffer2); } catch (IOException e) { e.printStackTrace(); } @@ -363,13 +361,9 @@ public abstract class AT45DB extends Chip implements USARTListener { return 0; } - public abstract void seek(long pos) throws IOException; - public abstract int read(byte[] b) throws IOException; - public abstract void write(byte[] b) throws IOException; - - /* not yet any meaningful support for getting configuration */ - public int getConfiguration(int param) { + @Override + public int getSize() { return 0; } - + } // AT45DB diff --git a/se/sics/mspsim/chip/ExternalFlash.java b/se/sics/mspsim/chip/ExternalFlash.java new file mode 100644 index 0000000..319ec59 --- /dev/null +++ b/se/sics/mspsim/chip/ExternalFlash.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2012, 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. + * + * This file is part of MSPSim. + * + */ +package se.sics.mspsim.chip; + +import se.sics.mspsim.core.Chip; +import se.sics.mspsim.core.MSP430Core; + +public abstract class ExternalFlash extends Chip { + + private Storage storage; + + protected ExternalFlash(String id, MSP430Core cpu) { + super(id, cpu); + } + + protected ExternalFlash(String id, String name, MSP430Core cpu) { + super(id, name, cpu); + } + + public Storage getStorage() { + if (storage ==null) { + // No storage set. Create a memory storage + storage = new MemoryStorage(); + storage.setMaxSize(getSize()); + } + return storage; + } + + public void setStorage(Storage storage) { + this.storage = storage; + } + + @Override + public int getConfiguration(int param) { + return 0; + } + + public abstract int getSize(); + +} diff --git a/se/sics/mspsim/chip/FileAT45DB.java b/se/sics/mspsim/chip/FileAT45DB.java deleted file mode 100644 index cc123ba..0000000 --- a/se/sics/mspsim/chip/FileAT45DB.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of MSPSim. - * - * $Id: $ - * - * ----------------------------------------------------------------- - * - * FileAT45DB - File based implementation of external flash. - * - * Author : Joakim Eriksson, Fredrik Osterlind - * Created : Sun Oct 21 22:00:00 2007 - * Updated : $Date: 2008-05-12 18:10:17 +0000 (Mon, 12 May 2008) $ - * $Revision: 280 $ - */ - -package se.sics.mspsim.chip; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import se.sics.mspsim.core.MSP430Core; - -public class FileAT45DB extends AT45DB { - - // PAGE_SIZE and NUM_PAGES defined in AT45DB - private static final int FLASH_SIZE = PAGE_SIZE * NUM_PAGES; - - private RandomAccessFile file; - private FileChannel fileChannel; - private FileLock fileLock; - - public FileAT45DB(MSP430Core cpu, String filename) { - super(cpu); - if (filename == null) { - filename = "flash.bin"; - } - - // Open flash file for R/W - if (!openFile(filename)) { - // Failed to open/lock the specified file. Add a counter and try with next filename. - Matcher m = Pattern.compile("(.+?)(\\d*)(\\.[^.]+)").matcher(filename); - if (m.matches()) { - String baseName = m.group(1); - String c = m.group(2); - String extName = m.group(3); - int count = 1; - if (c != null && c.length() > 0) { - count = Integer.parseInt(c) + 1; - } - for (int i = 0; !openFile(baseName + count + extName) && i < 100; i++, count++); - } - } - if (fileLock == null) { - // Failed to open flash file - throw new IllegalStateException("failed to open flash file '" + filename + '\''); - } - // Set size of flash - try { - file.setLength(FLASH_SIZE); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private boolean openFile(String filename) { - // Open flash file for R/W - try { - file = new RandomAccessFile(filename, "rw"); - fileChannel = file.getChannel(); - fileLock = fileChannel.tryLock(); - if (fileLock != null) { - // The file is now locked for use - if (DEBUG) log("using flash file '" + filename + '\''); - return true; - } else { - fileChannel.close(); - return false; - } - } catch (IOException e) { - e.printStackTrace(); - closeFile(); - return false; - } - } - - private void closeFile() { - try { - if (fileLock != null) { - fileLock.release(); - fileLock = null; - } - if (fileChannel != null) { - fileChannel.close(); - fileChannel = null; - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void seek(long pos) throws IOException { - file.seek(pos); - } - - public int read(byte[] b) throws IOException { - return file.read(b); - } - - public void write(byte[] b) throws IOException { - file.write(b); - } - - public void stateChanged(int state) { - // TODO Auto-generated method stub - - } - -} // FileAT45DB diff --git a/se/sics/mspsim/chip/FileM25P80.java b/se/sics/mspsim/chip/FileM25P80.java deleted file mode 100644 index 8be8c86..0000000 --- a/se/sics/mspsim/chip/FileM25P80.java +++ /dev/null @@ -1,180 +0,0 @@ -/** - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of MSPSim. - * - * $Id$ - * - * ----------------------------------------------------------------- - * - * FileM25P80 - File based implementation of external flash. - * - * Author : Joakim Eriksson, Fredrik Osterlind - * Created : Sun Oct 21 22:00:00 2007 - * Updated : $Date$ - * $Revision$ - */ - -package se.sics.mspsim.chip; -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import se.sics.mspsim.core.MSP430Core; - -public class FileM25P80 extends M25P80 { - - private String filename; - private RandomAccessFile file; - private FileChannel fileChannel; - private FileLock fileLock; - private long pos = 0; - - public FileM25P80(MSP430Core cpu, String filename) { - super(cpu); - if (filename == null) { - filename = "flash.bin"; - } - this.filename = filename; - } - - private boolean ensureOpen(boolean write) { - if (fileChannel != null) { - return true; - } - if (!write) { - File fp = new File(filename); - if (!fp.exists()) { - // File does not exist and only trying to read. Delay file creation until first write - return false; - } - } - - // Open flash file for R/W - if (!openFile(filename)) { - // Failed to open/lock the specified file. Add a counter and try with next filename. - Matcher m = Pattern.compile("(.+?)(\\d*)(\\.[^.]+)").matcher(filename); - if (m.matches()) { - String baseName = m.group(1); - String c = m.group(2); - String extName = m.group(3); - int count = 1; - if (c != null && c.length() > 0) { - count = Integer.parseInt(c) + 1; - } - for (int i = 0; !openFile(baseName + count + extName) && i < 100; i++, count++); - } - } - if (fileLock == null) { - // Failed to open flash file - if (write) { - logw("failed to open flash file '" + filename + '\''); - } - return false; - } - // Set size of flash - try { - file.setLength(MEMORY_SIZE); - if (pos > 0) { - file.seek(pos); - } - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - - private boolean openFile(String filename) { - // Open flash file for R/W - try { - file = new RandomAccessFile(filename, "rw"); - fileChannel = file.getChannel(); - fileLock = fileChannel.tryLock(); - if (fileLock != null) { - // The file is now locked for use - if (DEBUG) log("using flash file '" + filename + '\''); - return true; - } - fileChannel.close(); - return false; - } catch (IOException e) { - e.printStackTrace(); - closeFile(); - return false; - } - } - - private void closeFile() { - try { - file = null; - if (fileLock != null) { - fileLock.release(); - fileLock = null; - } - if (fileChannel != null) { - fileChannel.close(); - fileChannel = null; - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void seek(long pos) throws IOException { - if (file != null) { - file.seek(pos); - } - this.pos = pos; - } - - public int readFully(byte[] b) throws IOException { - if (file != null || ensureOpen(false)) { - pos += b.length; - return file.read(b); - } - Arrays.fill(b, (byte) 0); - pos += b.length; - return b.length; - } - - public void write(byte[] b) throws IOException { - if (file != null || ensureOpen(true)) { - file.write(b); - } - pos += b.length; - } - - public void stateChanged(int state) { - // TODO Auto-generated method stub - } - -} // FileM25P80 diff --git a/se/sics/mspsim/chip/FileStorage.java b/se/sics/mspsim/chip/FileStorage.java new file mode 100644 index 0000000..1bd5796 --- /dev/null +++ b/se/sics/mspsim/chip/FileStorage.java @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2012, 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. + * + * This file is part of MSPSim. + * + */ +package se.sics.mspsim.chip; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Niclas Finne + */ +public class FileStorage implements Storage { + + private String filename; + private String currentFilename; + private RandomAccessFile file; + private FileChannel fileChannel; + private FileLock fileLock; + private long maxSize = 0; + + public FileStorage() { + this("flash.bin"); + } + + public FileStorage(String filename) { + this.filename = filename; + } + + private boolean ensureOpen(boolean write) throws IOException { + if (fileChannel != null) { + return true; + } + if (!write) { + File fp = new File(filename); + if (!fp.exists()) { + // File does not exist and only trying to read. Delay file creation until first write + return false; + } + } + + // Open flash file for R/W + if (!openFile(filename)) { + // Failed to open/lock the specified file. Add a counter and try with next filename. + Matcher m = Pattern.compile("(.+?)(\\d*)(\\.[^.]+)").matcher(filename); + if (m.matches()) { + String baseName = m.group(1); + String c = m.group(2); + String extName = m.group(3); + int count = 1; + if (c != null && c.length() > 0) { + count = Integer.parseInt(c) + 1; + } + for (int i = 0; !openFile(baseName + count + extName) && i < 100; i++, count++); + } + } + if (fileLock == null) { + // Failed to open flash file + if (write) { + throw new IOException("failed to open storage file '" + filename + '\''); + } + return false; + } + return true; + } + + private boolean openFile(String filename) { + // Open flash file for R/W + try { + currentFilename = filename; + file = new RandomAccessFile(filename, "rw"); + fileChannel = file.getChannel(); + fileLock = fileChannel.tryLock(); + if (fileLock != null) { + // The file is now locked for use +// if (DEBUG) log("using flash file '" + filename + '\''); + return true; + } + fileChannel.close(); + return false; + } catch (IOException e) { + e.printStackTrace(); + close(); + return false; + } + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + close(); + } + + public File getCurrentFile() { + if (file != null) { + return new File(currentFilename); + } + return null; + } + + @Override + public int read(long pos, byte[] b) throws IOException { + return read(pos, b, 0, b.length); + } + + @Override + public int read(long pos, byte[] b, int offset, int len) throws IOException { + if (maxSize > 0 && pos + len > maxSize) { + throw new IOException("outside storage"); + } + if (file != null || ensureOpen(false)) { + file.seek(pos); + return file.read(b, offset, len); + } + Arrays.fill(b, (byte) 0); + return len; + } + + @Override + public void write(long pos, byte[] b) throws IOException { + write(pos, b, 0, b.length); + } + + public void write(long pos, byte[] b, int offset, int len) throws IOException { + if (maxSize > 0 && pos + len > maxSize) { + throw new IOException("outside storage"); + } + if (file != null || ensureOpen(true)) { + file.seek(pos); + file.write(b, offset, len); + } + } + + @Override + public long getMaxSize() { + return maxSize; + } + + @Override + public void setMaxSize(long size) { + this.maxSize = size; + if (size > 0 && file != null) { + try { + if (file.length() > size) { + file.setLength(size); + } + } catch (IOException e) { + // Ignore + } + } + } + + @Override + public void close() { + try { + file = null; + if (fileLock != null) { + fileLock.release(); + fileLock = null; + } + if (fileChannel != null) { + fileChannel.close(); + fileChannel = null; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public String info() { + File fp = getCurrentFile(); + StringBuilder sb = new StringBuilder(); + sb.append("FileStorage("); + if (file != null) { + try { + long len = file.length(); + sb.append(len); + } catch (Exception e) { + // Ignore + sb.append('0'); + } + } + if (maxSize > 0) { + sb.append('/').append(maxSize); + } + sb.append(" bytes): "); + if (fp != null) { + sb.append(fp.getAbsolutePath()); + } else { + sb.append(filename); + } + return sb.toString(); + } +} diff --git a/se/sics/mspsim/chip/M25P16.java b/se/sics/mspsim/chip/M25P16.java new file mode 100644 index 0000000..d678641 --- /dev/null +++ b/se/sics/mspsim/chip/M25P16.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2012, 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. + * + * This file is part of MSPSim. + * + */ +package se.sics.mspsim.chip; + +import se.sics.mspsim.core.MSP430Core; + +/** + * @author Niclas Finne + */ +public class M25P16 extends M25P80 { + + public static final int MEMORY_SIZE = 2 * 1024 * 1024; + + public M25P16(MSP430Core cpu) { + super("M25P16", cpu); + } + + @Override + public int getSize() { + return MEMORY_SIZE; + } + +} diff --git a/se/sics/mspsim/chip/M25P80.java b/se/sics/mspsim/chip/M25P80.java index 0f9cb76..191d6c2 100644 --- a/se/sics/mspsim/chip/M25P80.java +++ b/se/sics/mspsim/chip/M25P80.java @@ -44,7 +44,7 @@ import java.io.IOException; import se.sics.mspsim.core.*; import se.sics.mspsim.util.Utils; -public abstract class M25P80 extends Chip implements USARTListener, PortListener, Memory { +public class M25P80 extends ExternalFlash implements USARTListener, PortListener, Memory { public static final int WRITE_STATUS = 0x01; public static final int PAGE_PROGRAM = 0x02; @@ -93,6 +93,10 @@ public abstract class M25P80 extends Chip implements USARTListener, PortListener writing = false; }}; + protected M25P80(String id, MSP430Core cpu) { + super(id, "External Flash", cpu); + } + public M25P80(MSP430Core cpu) { super("M25P80", "External Flash", cpu); } @@ -271,6 +275,7 @@ public abstract class M25P80 extends Chip implements USARTListener, PortListener } } + @Override public int getSize() { return MEMORY_SIZE; } @@ -304,8 +309,7 @@ public abstract class M25P80 extends Chip implements USARTListener, PortListener } private void loadMemory(int address, byte[] readMemory) throws IOException { - seek(address & 0xfff00); - readFully(readMemory); + getStorage().read(address & 0xfff00, readMemory); for (int i = 0; i < readMemory.length; i++) { readMemory[i] = (byte) (~readMemory[i] & 0xff); } @@ -372,32 +376,25 @@ public abstract class M25P80 extends Chip implements USARTListener, PortListener if (DEBUG) { log("Writing data to disk at $" + Integer.toHexString(address)); } - seek(address & 0xfff00); for (int i = 0; i < data.length; i++) { tmp[i] = (byte) (~data[i] & 0xff); } - write(tmp); - } catch (IOException e) { + getStorage().write(address & 0xfff00, tmp); + } catch (IOException e) { e.printStackTrace(); } } + @Override public int getModeMax() { return 0; } - public abstract void seek(long pos) throws IOException; - public abstract int readFully(byte[] b) throws IOException; - public abstract void write(byte[] b) throws IOException; - - /* by default - there is not configuration to return for m25p80 */ - public int getConfiguration(int param) { - return 0; - } - + @Override public String info() { return " Status: " + getStatus() + " Write Enabled: " + writeEnable - + " Write in Progress: " + writing + '\n' + " Chip Select: " + chipSelect; + + " Write in Progress: " + writing + " Chip Select: " + chipSelect + + "\n " + getStorage().info(); } } // M25P80 diff --git a/se/sics/mspsim/chip/MemoryStorage.java b/se/sics/mspsim/chip/MemoryStorage.java new file mode 100644 index 0000000..752dd36 --- /dev/null +++ b/se/sics/mspsim/chip/MemoryStorage.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2012, 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. + * + * This file is part of MSPSim. + * + */ +package se.sics.mspsim.chip; + +import java.io.IOException; +import java.util.Arrays; + +/** + * @author Niclas Finne + */ +public class MemoryStorage implements Storage { + + private byte[] data; + private int maxSize; + + private void ensureCapacity(int size) throws IOException { + if (data == null) { + data = new byte[size]; + } else if (data.length < size) { + data = Arrays.copyOf(data, size); + } + } + + @Override + public int read(long pos, byte[] b) throws IOException { + return read(pos, b, 0, b.length); + } + + @Override + public int read(long storagePos, byte[] buffer, int offset, int len) throws IOException { + if (maxSize > 0 && storagePos + len > maxSize) { + throw new IOException("outside storage"); + } + if (data == null) { + Arrays.fill(buffer, offset, offset + len, (byte)0); + } else { + int pos = (int) storagePos; + if (pos + len > data.length) { + System.arraycopy(data, pos, buffer, offset, data.length - pos); + Arrays.fill(buffer, offset + data.length - pos, offset + len, (byte) 0); + } else { + System.arraycopy(data, pos, buffer, offset, len); + } + } + return len; + } + + @Override + public void write(long storagePos, byte[] buffer) throws IOException { + write(storagePos, buffer, 0, buffer.length); + } + + @Override + public void write(long storagePos, byte[] buffer, int offset, int len) throws IOException { + int pos = (int) storagePos; + if (maxSize > 0 && pos + len > maxSize) { + throw new IOException("outside storage"); + } + ensureCapacity(pos + len); + System.arraycopy(buffer, offset, data, pos, len); + } + + @Override + public long getMaxSize() { + return maxSize; + } + + @Override + public void setMaxSize(long size) { + this.maxSize = (int) size; + if (maxSize > 0 && data != null && data.length > maxSize) { + data = Arrays.copyOf(data, maxSize); + } + } + + @Override + public void close() { + // Nothing to close + } + + @Override + public String info() { + if (maxSize > 0) { + return "MemoryStorage(" + data.length + "/" + maxSize + " bytes)"; + } + return "MemoryStorage(" + data.length + " bytes allocated)"; + } +} diff --git a/se/sics/mspsim/chip/Storage.java b/se/sics/mspsim/chip/Storage.java new file mode 100644 index 0000000..1b684e7 --- /dev/null +++ b/se/sics/mspsim/chip/Storage.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2012, 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. + * + * This file is part of MSPSim. + * + */ +package se.sics.mspsim.chip; + +import java.io.IOException; + +/** + * @author Niclas Finne + */ +public interface Storage { + + public int read(long pos, byte[] buffer) throws IOException; + + public int read(long pos, byte[] buffer, int offset, int len) throws IOException; + + public void write(long pos, byte[] buffer) throws IOException; + + public void write(long pos, byte[] buffer, int offset, int len) throws IOException; + + public long getMaxSize(); + + public void setMaxSize(long size); + + public void close(); + + public String info(); + +} diff --git a/se/sics/mspsim/platform/jcreate/JCreateNode.java b/se/sics/mspsim/platform/jcreate/JCreateNode.java index b3031bb..754e18f 100644 --- a/se/sics/mspsim/platform/jcreate/JCreateNode.java +++ b/se/sics/mspsim/platform/jcreate/JCreateNode.java @@ -41,16 +41,13 @@ package se.sics.mspsim.platform.jcreate; import java.io.IOException; - -import se.sics.mspsim.chip.FileM25P80; +import se.sics.mspsim.chip.FileStorage; import se.sics.mspsim.chip.Leds; import se.sics.mspsim.chip.M25P80; import se.sics.mspsim.chip.MMA7260QT; import se.sics.mspsim.core.ADC12; import se.sics.mspsim.core.ADCInput; import se.sics.mspsim.core.IOPort; -import se.sics.mspsim.core.IOUnit; -import se.sics.mspsim.core.USART; import se.sics.mspsim.core.USARTSource; import se.sics.mspsim.platform.sky.CC2420Node; import se.sics.mspsim.util.ArgumentManager; @@ -134,8 +131,11 @@ public class JCreateNode extends CC2420Node { } }); + if (getFlash() == null) { + setFlash(new M25P80(cpu)); + } if (flashFile != null) { - setFlash(new FileM25P80(cpu, flashFile)); + getFlash().setStorage(new FileStorage(flashFile)); } } diff --git a/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java b/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java index 3a47929..b9c3324 100644 --- a/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java +++ b/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java @@ -41,12 +41,10 @@ package se.sics.mspsim.platform.sentillausb; import java.io.IOException; - -import se.sics.mspsim.chip.FileM25P80; +import se.sics.mspsim.chip.FileStorage; import se.sics.mspsim.chip.Leds; import se.sics.mspsim.chip.M25P80; import se.sics.mspsim.core.IOPort; -import se.sics.mspsim.core.USART; import se.sics.mspsim.core.USARTSource; import se.sics.mspsim.platform.sky.CC2420Node; import se.sics.mspsim.util.ArgumentManager; @@ -110,8 +108,11 @@ public class SentillaUSBNode extends CC2420Node { public void setupNodePorts() { super.setupNodePorts(); leds = new Leds(cpu, LEDS); + if (getFlash() == null) { + setFlash(new M25P80(cpu)); + } if (flashFile != null) { - setFlash(new FileM25P80(cpu, flashFile)); + getFlash().setStorage(new FileStorage(flashFile)); } } diff --git a/se/sics/mspsim/platform/sky/CC2420Node.java b/se/sics/mspsim/platform/sky/CC2420Node.java index 7914997..7d46e16 100644 --- a/se/sics/mspsim/platform/sky/CC2420Node.java +++ b/se/sics/mspsim/platform/sky/CC2420Node.java @@ -4,7 +4,6 @@ import se.sics.mspsim.chip.DS2411; import se.sics.mspsim.chip.PacketListener; import se.sics.mspsim.config.MSP430f1611Config; import se.sics.mspsim.core.IOPort; -import se.sics.mspsim.core.IOUnit; import se.sics.mspsim.core.MSP430; import se.sics.mspsim.core.PortListener; import se.sics.mspsim.core.USART; diff --git a/se/sics/mspsim/platform/sky/SkyNode.java b/se/sics/mspsim/platform/sky/SkyNode.java index 6ef74ce..998e3f5 100644 --- a/se/sics/mspsim/platform/sky/SkyNode.java +++ b/se/sics/mspsim/platform/sky/SkyNode.java @@ -41,7 +41,7 @@ package se.sics.mspsim.platform.sky; import java.io.IOException; -import se.sics.mspsim.chip.FileM25P80; +import se.sics.mspsim.chip.FileStorage; import se.sics.mspsim.chip.M25P80; import se.sics.mspsim.core.IOPort; import se.sics.mspsim.core.USARTSource; @@ -88,8 +88,11 @@ public class SkyNode extends MoteIVNode { public void setupNodePorts() { super.setupNodePorts(); + if (getFlash() == null) { + setFlash(new M25P80(cpu)); + } if (flashFile != null) { - setFlash(new FileM25P80(cpu, flashFile)); + getFlash().setStorage(new FileStorage(flashFile)); } } diff --git a/se/sics/mspsim/platform/sky/TelosNode.java b/se/sics/mspsim/platform/sky/TelosNode.java index 212a09f..1d02286 100644 --- a/se/sics/mspsim/platform/sky/TelosNode.java +++ b/se/sics/mspsim/platform/sky/TelosNode.java @@ -42,7 +42,7 @@ package se.sics.mspsim.platform.sky; import java.io.IOException; import se.sics.mspsim.chip.AT45DB; -import se.sics.mspsim.chip.FileAT45DB; +import se.sics.mspsim.chip.FileStorage; import se.sics.mspsim.core.IOPort; import se.sics.mspsim.core.USARTSource; import se.sics.mspsim.util.ArgumentManager; @@ -90,8 +90,11 @@ public class TelosNode extends MoteIVNode { public void setupNodePorts() { super.setupNodePorts(); + if (getFlash() == null) { + setFlash(new AT45DB(cpu)); + } if (flashFile != null) { - flash = new FileAT45DB(cpu, flashFile); + getFlash().setStorage(new FileStorage(flashFile)); } } diff --git a/se/sics/mspsim/platform/z1/Z1Node.java b/se/sics/mspsim/platform/z1/Z1Node.java index 3931010..8c938ea 100644 --- a/se/sics/mspsim/platform/z1/Z1Node.java +++ b/se/sics/mspsim/platform/z1/Z1Node.java @@ -3,7 +3,7 @@ package se.sics.mspsim.platform.z1; import java.io.IOException; import se.sics.mspsim.chip.Button; import se.sics.mspsim.chip.CC2420; -import se.sics.mspsim.chip.FileM25P80; +import se.sics.mspsim.chip.FileStorage; import se.sics.mspsim.chip.Leds; import se.sics.mspsim.chip.M25P80; import se.sics.mspsim.config.MSP430f2617Config; @@ -89,6 +89,9 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { } public M25P80 getFlash() { + // TODO Replace with M25P16. + // The Z1 platform has a M25P16 chip with 2MB compared to the M25P80 + // with 1MB but the chips are compatible. return flash; } @@ -142,10 +145,6 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { } private void setupNodePorts() { - if (flashFile != null) { - setFlash(new FileM25P80(cpu, flashFile)); - } - port1 = cpu.getIOUnit(IOPort.class, "P1"); // port1.addPortListener(this); port2 = cpu.getIOUnit(IOPort.class, "P2"); @@ -174,6 +173,12 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { leds = new Leds(cpu, LEDS); button = new Button("Button", cpu, port2, BUTTON_PIN, true); + if (getFlash() == null) { + setFlash(new M25P80(cpu)); + } + if (flashFile != null) { + getFlash().setStorage(new FileStorage(flashFile)); + } } public void setupNode() { @@ -190,7 +195,7 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { fileName = fileName + ".flash"; } } - if (DEBUG) System.out.println("Using flash file: " + (fileName == null ? "no file" : fileName)); + if (DEBUG) log("Using flash file: " + (fileName == null ? "no file" : fileName)); this.flashFile = fileName;