From: <fro...@us...> - 2008-04-01 08:18:34
|
Revision: 219 http://mspsim.svn.sourceforge.net/mspsim/?rev=219&view=rev Author: fros4943 Date: 2008-04-01 01:18:31 -0700 (Tue, 01 Apr 2008) Log Message: ----------- separated m24p80 from external files Added Paths: ----------- mspsim/se/sics/mspsim/chip/M25P80.java Added: mspsim/se/sics/mspsim/chip/M25P80.java =================================================================== --- mspsim/se/sics/mspsim/chip/M25P80.java (rev 0) +++ mspsim/se/sics/mspsim/chip/M25P80.java 2008-04-01 08:18:31 UTC (rev 219) @@ -0,0 +1,337 @@ +/** + * 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: M25P80.java 177 2008-03-11 15:32:12Z nifi $ + * + * ----------------------------------------------------------------- + * + * ExtFlash + * + * Author : Joakim Eriksson, Fredrik Osterlind + * Created : Sun Oct 21 22:00:00 2007 + * Updated : $Date: 2008-03-11 16:32:12 +0100 (ti, 11 mar 2008) $ + * $Revision: 177 $ + */ + +package se.sics.mspsim.chip; +import java.io.IOException; +import se.sics.mspsim.core.*; + +public abstract class M25P80 extends Chip implements USARTListener, PortListener { + + public static final boolean DEBUG = false; + + public static final int WRITE_STATUS = 0x01; + public static final int PAGE_PROGRAM = 0x02; + public static final int READ_DATA = 0x03; + public static final int WRITE_DISABLE = 0x04; + public static final int READ_STATUS = 0x05; + public static final int WRITE_ENABLE = 0x06; + public static final int READ_DATA_FAST = 0x0b; + public static final int READ_IDENT = 0x9f; + public static final int SECTOR_ERASE = 0xd8; + public static final int BULK_ERASE = 0xc7; + public static final int DEEP_POWER_DOWN = 0xb9; + public static final int WAKE_UP = 0xab; + + private int state = 0; + public static final int CHIP_SELECT = 0x10; + private boolean chipSelect; + + private int pos; + private int status = 0; + + private boolean writeEnable = false; + private boolean writing = false; + + private int[] identity = new int[] { + 0x20,0x20,0x14,0x10, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + private int readAddress; + private int loadedAddress = -1; + private int blockWriteAddress; + private byte[] readMemory = new byte[256]; + private byte[] buffer = new byte[256]; + + private TimeEvent writeEvent = new TimeEvent(0) { + public void execute(long t) { + writing = false; + }}; + + private MSP430Core cpu; + + public M25P80(MSP430Core cpu) { + this.cpu = cpu; + } + + public void dataReceived(USART source, int data) { + if (chipSelect) { + if (DEBUG) { + System.out.println("M25P80: byte received: " + data); + } + switch(state) { + case READ_IDENT: + source.byteReceived(identity[pos]); + pos++; + if (pos >= identity.length) { + pos = 0; + } + return; + case WRITE_STATUS: + status = data; + source.byteReceived(0); + return; + case READ_DATA: + if (pos < 3) { + readAddress = (readAddress << 8) + data; + source.byteReceived(0); + pos++; + if (DEBUG && pos == 3) { + System.out.println("M25P80: reading from " + Integer.toHexString(readAddress)); + } + } else { + source.byteReceived(readMemory(readAddress++)); + if (readAddress > 0xfffff) { + readAddress = 0; + } + } + return; + case SECTOR_ERASE: + if (pos < 3) { + readAddress = (readAddress << 8) + data; + source.byteReceived(0); + pos++; + if (pos == 3) { + // Clear buffer + sectorErase(readAddress); + } + } + return; + case PAGE_PROGRAM: + if (pos < 3) { + readAddress = (readAddress << 8) + data; + source.byteReceived(0); + pos++; + if (pos == 3) { + // Clear buffer + for (int i = 0; i < buffer.length; i++) { + buffer[i] = (byte) 0xff; + } + blockWriteAddress = readAddress & 0xfff00; + if (DEBUG) { + System.out.println("M25P80: programming at " + Integer.toHexString(readAddress)); + } + } + } else { + // Do the programming!!! + source.byteReceived(0); + writeBuffer((readAddress++) & 0xff, data); + } + return; + } + if (DEBUG) { + System.out.println("M25P80: new command: " + data); + } + switch (data) { + case WRITE_ENABLE: + if (DEBUG) { + System.out.println("M25P80: Write Enable"); + } + writeEnable = true; + break; + case WRITE_DISABLE: + if (DEBUG) { + System.out.println("M25P80: Write Disable"); + } + writeEnable = false; + break; + case READ_IDENT: + if (DEBUG) { + System.out.println("M25P80: Read ident."); + } + state = READ_IDENT; + pos = 0; + source.byteReceived(identity[pos++]); + return; + case READ_STATUS: + status = (status & (0xff - 1 - 2)) | (writeEnable ? 0x02 : 0x00) | + (writing ? 0x01 : 0x00); + source.byteReceived(status); + if (DEBUG) { + System.out.println("M25P80: Read status => " + status); + } + return; + case WRITE_STATUS: + if (DEBUG) { + System.out.println("M25P80: Write status"); + } + state = WRITE_STATUS; + break; + case READ_DATA: + if (DEBUG) { + System.out.println("M25P80: Read Data"); + } + state = READ_DATA; + pos = readAddress = 0; + break; + case PAGE_PROGRAM: + if (DEBUG) { + System.out.println("M25P80: Page Program"); + } + state = PAGE_PROGRAM; + pos = readAddress = 0; + break; + case SECTOR_ERASE: + if (DEBUG) { + System.out.println("M25P80: Sector Erase"); + } + state = SECTOR_ERASE; + pos = 0; + break; + case BULK_ERASE: + System.out.println("M25P80: Bulk Erase"); + break; + } + source.byteReceived(0); + } + } + + // Should return correct data! + private int readMemory(int address) { + if (DEBUG) { + System.out.println("M25P80: Reading memory address: " + Integer.toHexString(address)); + } + ensureLoaded(address); + return readMemory[address & 0xff]; + } + + private void writeBuffer(int address, int data) { + buffer[address] = (byte) data; + } + + private void ensureLoaded(int address) { + if (loadedAddress < 0 + || ((loadedAddress & 0xfff00) != (address & 0xfff00))) { + try { + if (DEBUG) { + System.out.println("M25P80: Loading memory: " + (address & 0xfff00)); + } + seek(address & 0xfff00); + readFully(readMemory); + for (int i = 0; i < readMemory.length; i++) { + readMemory[i] = (byte) (~readMemory[i] & 0xff); + } + } catch (IOException e) { + e.printStackTrace(); + } + loadedAddress = address & 0xfff00; + } + } + + public void portWrite(IOPort source, int data) { + // Chip select = active low... + if (chipSelect && (data & CHIP_SELECT) != 0) { + // Chip select will go "off" + switch(state) { + case PAGE_PROGRAM: + programPage(); + break; + } + } + chipSelect = (data & CHIP_SELECT) == 0; +// System.out.println("M25P80: write to Port4: " + +// Integer.toString(data, 16) +// + " CS:" + chipSelect); + state = 0; + } + + private void writeStatus(double time) { + writing = true; + cpu.scheduleTimeEventMillis(writeEvent, time); + } + + private void programPage() { + writeStatus(0.64); + ensureLoaded(blockWriteAddress); + for (int i = 0; i < readMemory.length; i++) { + readMemory[i] &= buffer[i]; + } + writeBack(blockWriteAddress, readMemory); + } + + private void sectorErase(int address) { + writeStatus(600); + int sectorAddress = address & 0xf0000; + loadedAddress = -1; + for (int i = 0; i < buffer.length; i++) { + buffer[i] = (byte)0xff; + } + // Erase a complete sector + blockWriteAddress = sectorAddress; + for (int i = 0; i < 0x100; i++) { + if (DEBUG) { + System.out.println("M25P80: erasing at " + Integer.toHexString(blockWriteAddress)); + } + writeBack(blockWriteAddress, buffer); + blockWriteAddress += 0x100; + } + } + + + private void writeBack(int address, byte[] data) { + try { + byte[] tmp = new byte[data.length]; + if (DEBUG) { + System.out.println("M25P80: 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) { + e.printStackTrace(); + } + } + + public int getModeMax() { + return 0; + } + + public String getName() { + return "M25P80: external flash"; + } + + public abstract void seek(long pos) throws IOException; + public abstract int readFully(byte[] b) throws IOException; + public abstract void write(byte[] b) throws IOException; + +} // ExtFlash This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |