From 6ab1eadb97515b3d589061cbb8bfff988aaeed8a Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Fri, 8 Apr 2011 22:21:36 +0200 Subject: [PATCH] added improved support for Z1/2xxx platform --- .gitignore | 2 + se/sics/mspsim/chip/AT45DB.java | 2 +- se/sics/mspsim/chip/CC2420.java | 9 +- se/sics/mspsim/chip/M25P80.java | 2 +- se/sics/mspsim/chip/TR1001.java | 3 +- se/sics/mspsim/config/MSP430f1611Config.java | 9 +- se/sics/mspsim/config/MSP430f2617Config.java | 42 +- se/sics/mspsim/core/MSP430Config.java | 31 +- se/sics/mspsim/core/MSP430Core.java | 86 +-- se/sics/mspsim/core/SFR.java | 12 +- se/sics/mspsim/core/USART.java | 2 +- se/sics/mspsim/core/USARTListener.java | 2 +- se/sics/mspsim/core/USARTSource.java | 11 + se/sics/mspsim/core/USCI.java | 500 ++++++++++++++++++ .../mspsim/platform/jcreate/JCreateNode.java | 3 +- .../platform/sentillausb/SentillaUSBNode.java | 3 +- se/sics/mspsim/platform/sky/CC2420Node.java | 3 +- se/sics/mspsim/platform/sky/SkyNode.java | 3 +- se/sics/mspsim/platform/sky/TelosNode.java | 3 +- se/sics/mspsim/platform/z1/Z1Node.java | 22 +- se/sics/mspsim/ui/SerialMon.java | 11 +- se/sics/mspsim/util/Test.java | 2 +- 22 files changed, 682 insertions(+), 81 deletions(-) create mode 100755 .gitignore create mode 100755 se/sics/mspsim/core/USARTSource.java create mode 100755 se/sics/mspsim/core/USCI.java diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..73a6866 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.class +.DS_Store diff --git a/se/sics/mspsim/chip/AT45DB.java b/se/sics/mspsim/chip/AT45DB.java index 5c8c355..5d07695 100644 --- a/se/sics/mspsim/chip/AT45DB.java +++ b/se/sics/mspsim/chip/AT45DB.java @@ -141,7 +141,7 @@ public abstract class AT45DB extends Chip implements USARTListener { status &= ~STATUS_RDY; } - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { int buf_num = 1; if (chipSelect) { diff --git a/se/sics/mspsim/chip/CC2420.java b/se/sics/mspsim/chip/CC2420.java index b8ea453..3c53d65 100644 --- a/se/sics/mspsim/chip/CC2420.java +++ b/se/sics/mspsim/chip/CC2420.java @@ -715,7 +715,7 @@ public class CC2420 extends Chip implements USARTListener, RFListener, RFSource configurationChanged(address, oldValue, data); } - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { int oldStatus = status; if (DEBUG) { log("byte received: " + Utils.hex8(data) + @@ -880,6 +880,10 @@ public class CC2420 extends Chip implements USARTListener, RFListener, RFSource break; } source.byteReceived(oldStatus); + } else { + /* No VREG but chip select */ + if (chipSelect) source.byteReceived(0); + System.out.println("**** Warning - writing to CC2420 when VREG is off!!!"); } } @@ -1268,7 +1272,8 @@ public class CC2420 extends Chip implements USARTListener, RFListener, RFSource if(newOn) { // 0.6ms maximum vreg startup from datasheet pg 13 - cpu.scheduleTimeEventMillis(vregEvent, 0.1); + // but Z1 platform does not work with 0.1 so trying with lower... + cpu.scheduleTimeEventMillis(vregEvent, 0.05); if (DEBUG) log("Scheduling vregEvent at: cyc = " + cpu.cycles + " target: " + vregEvent.getTime() + " current: " + cpu.getTime()); } else { diff --git a/se/sics/mspsim/chip/M25P80.java b/se/sics/mspsim/chip/M25P80.java index b9e98fc..0a36e8d 100644 --- a/se/sics/mspsim/chip/M25P80.java +++ b/se/sics/mspsim/chip/M25P80.java @@ -109,7 +109,7 @@ public abstract class M25P80 extends Chip implements USARTListener, PortListener public void stateChanged(int state) { } - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { if (chipSelect) { if (DEBUG) { log("byte received: " + data); diff --git a/se/sics/mspsim/chip/TR1001.java b/se/sics/mspsim/chip/TR1001.java index e115a39..93c25be 100644 --- a/se/sics/mspsim/chip/TR1001.java +++ b/se/sics/mspsim/chip/TR1001.java @@ -43,6 +43,7 @@ import se.sics.mspsim.core.Chip; import se.sics.mspsim.core.MSP430Core; import se.sics.mspsim.core.USART; import se.sics.mspsim.core.USARTListener; +import se.sics.mspsim.core.USARTSource; /** * @@ -66,7 +67,7 @@ public class TR1001 extends Chip implements RFListener, RFSource { setMode(MODE_TXRX_OFF); usart.setUSARTListener(new USARTListener() { - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { RFListener listener = rfListener; if (getMode() != MODE_TXRX_ON) { // Radio is turned off during transmission diff --git a/se/sics/mspsim/config/MSP430f1611Config.java b/se/sics/mspsim/config/MSP430f1611Config.java index 4ae748c..b1e5dce 100755 --- a/se/sics/mspsim/config/MSP430f1611Config.java +++ b/se/sics/mspsim/config/MSP430f1611Config.java @@ -35,6 +35,7 @@ package se.sics.mspsim.config; +import java.util.ArrayList; import se.sics.mspsim.core.DMA; import se.sics.mspsim.core.IOUnit; import se.sics.mspsim.core.InterruptMultiplexer; @@ -56,7 +57,7 @@ public class MSP430f1611Config extends MSP430Config { } - public int setup(MSP430Core cpu, IOUnit[] ioUnits, int ioPos) { + public int setup(MSP430Core cpu, ArrayList ioUnits) { System.out.println("*** Setting up f1611 IO!"); USART usart0 = new USART(cpu, 0, cpu.memory, 0x70); @@ -71,8 +72,8 @@ public class MSP430f1611Config extends MSP430Config { } // Usarts - ioUnits[ioPos] = usart0; - ioUnits[ioPos + 1] = usart1; + ioUnits.add(usart0); + ioUnits.add(usart1); DMA dma = new DMA("dma", cpu.memory, 0, cpu); for (int i = 0, n = 24; i < n; i++) { @@ -91,7 +92,7 @@ public class MSP430f1611Config extends MSP430Config { dma.setDMATrigger(DMA.UTXIFG1, usart1, 1); dma.setInterruptMultiplexer(new InterruptMultiplexer(cpu, 0)); - ioUnits[ioPos + 2] = dma; + ioUnits.add(dma); return 3; } } diff --git a/se/sics/mspsim/config/MSP430f2617Config.java b/se/sics/mspsim/config/MSP430f2617Config.java index f727d36..14aa51b 100755 --- a/se/sics/mspsim/config/MSP430f2617Config.java +++ b/se/sics/mspsim/config/MSP430f2617Config.java @@ -35,10 +35,12 @@ package se.sics.mspsim.config; +import java.util.ArrayList; import se.sics.mspsim.core.IOUnit; import se.sics.mspsim.core.MSP430Config; import se.sics.mspsim.core.MSP430Core; import se.sics.mspsim.core.Timer; +import se.sics.mspsim.core.USCI; public class MSP430f2617Config extends MSP430Config { @@ -52,10 +54,46 @@ public class MSP430f2617Config extends MSP430Config { TimerConfig timerA = new TimerConfig(25, 24, 3, 0x160, Timer.TIMER_Ax149, "TimerA"); TimerConfig timerB = new TimerConfig(29, 28, 7, 0x180, Timer.TIMER_Bx149, "TimerB"); timerConfig = new TimerConfig[] {timerA, timerB}; + + /* TX Vec, RX Vec, TX Bit, RX Bit, SFR-reg, Offset, Name, A?*/ + UARTConfig uA0 = new UARTConfig(22, 23, 1, 0, 1, 0x60, "USCI A0", true); + UARTConfig uB0 = new UARTConfig(22, 23, 3, 2, 1, 0x60, "USCI B0", false); + UARTConfig uA1 = new UARTConfig(16, 17, 1, 0, 6, 0xD0, "USCI A1", true); + UARTConfig uB1 = new UARTConfig(16, 17, 3, 2, 6, 0xD0, "USCI B1", false); + uartConfig = new UARTConfig[] {uA0, uB0, uA1, uB1}; } - public int setup(MSP430Core cpu, IOUnit[] ioUnits, int ioPos) { - return 0; + public int setup(MSP430Core cpu, ArrayList ioUnits) { + USCI usciA0 = new USCI(cpu, 0, cpu.memory, this); + USCI usciB0 = new USCI(cpu, 1, cpu.memory, this); + USCI usciA1 = new USCI(cpu, 2, cpu.memory, this); + USCI usciB1 = new USCI(cpu, 3, cpu.memory, this); + + for (int i = 0, n = 8; i < n; i++) { + cpu.memOut[0x60 + i] = usciA0; + cpu.memIn[0x60 + i] = usciA0; + cpu.memOut[0x68 + i] = usciB0; + cpu.memIn[0x68 + i] = usciB0; + + cpu.memOut[0xd0 + i] = usciA1; + cpu.memIn[0xd0 + i] = usciA1; + cpu.memOut[0xd8 + i] = usciB1; + cpu.memIn[0xd8 + i] = usciB1; + } + + ioUnits.add(usciA0); + ioUnits.add(usciB0); + ioUnits.add(usciA1); + ioUnits.add(usciB1); + + /* usciA1 handles interrupts for both usciA1 and B1 */ + cpu.memOut[6] = usciA1; + cpu.memIn[6] = usciA1; + cpu.memOut[7] = usciA1; + cpu.memIn[7] = usciA1; + + /* 4 usci units */ + return 4; } } \ No newline at end of file diff --git a/se/sics/mspsim/core/MSP430Config.java b/se/sics/mspsim/core/MSP430Config.java index b9107e8..b92d30e 100644 --- a/se/sics/mspsim/core/MSP430Config.java +++ b/se/sics/mspsim/core/MSP430Config.java @@ -1,5 +1,7 @@ package se.sics.mspsim.core; +import java.util.ArrayList; + public abstract class MSP430Config { public class TimerConfig { @@ -21,13 +23,40 @@ public abstract class MSP430Config { } } + public class UARTConfig { + int txVector; + int rxVector; + int offset; + String name; + int txBit; + int rxBit; + int sfrAddr; + boolean usciA; + + public UARTConfig(int txVector, int rxVector, int txBit, int rxBit, int sftAddr, int offset, + String name, boolean usciA) { + this.txVector = txVector; + this.rxVector = rxVector; + this.txBit = txBit; + this.rxBit = rxBit; + this.offset = offset; + this.name = name; + this.usciA = usciA; + this.sfrAddr = sftAddr; + } + } + + public UARTConfig[] uartConfig; + /* default for the 149/1611 */ public TimerConfig[] timerConfig = { new TimerConfig(6, 5, 3, 0x160, Timer.TIMER_Ax149, "TimerA"), new TimerConfig(13, 12, 7, 0x180, Timer.TIMER_Bx149, "TimerB") }; + + public int maxMemIO = 0x200; public int maxInterruptVector = 15; public boolean MSP430XArch = false; - public abstract int setup(MSP430Core cpu, IOUnit[] ioUnits, int ioPos); + public abstract int setup(MSP430Core cpu, ArrayList ioUnits); } diff --git a/se/sics/mspsim/core/MSP430Core.java b/se/sics/mspsim/core/MSP430Core.java index da16329..d476b69 100644 --- a/se/sics/mspsim/core/MSP430Core.java +++ b/se/sics/mspsim/core/MSP430Core.java @@ -61,7 +61,7 @@ public class MSP430Core extends Chip implements MSP430Constants { // Try it out with 64 k memory public static final int MAX_MEM = 64*1024; - public static final int MAX_MEM_IO = 0x200; + public final int MAX_MEM_IO; public static final int PORTS = 6; // 16 registers of which some are "special" - PC, SP, etc. @@ -86,11 +86,11 @@ public class MSP430Core extends Chip implements MSP430Constants { // Most HW needs only notify write and clocking, others need also read... // For notify write... - public IOUnit[] memOut = new IOUnit[MAX_MEM_IO]; + public IOUnit[] memOut; // For notify read... -> which will happen before actual read! - public IOUnit[] memIn = new IOUnit[MAX_MEM_IO]; + public IOUnit[] memIn; - private IOUnit[] ioUnits; + private ArrayList ioUnits; private SFR sfr; private Watchdog watchdog; @@ -142,6 +142,9 @@ public class MSP430Core extends Chip implements MSP430Constants { public MSP430Core(int type, ComponentRegistry registry, MSP430Config config) { super("MSP430", "MSP430 Core", null); MAX_INTERRUPT = config.maxInterruptVector; + MAX_MEM_IO = config.maxMemIO; + memOut = new IOUnit[MAX_MEM_IO]; + memIn = new IOUnit[MAX_MEM_IO]; this.registry = registry; this.config = config; // The CPU need to register itself as chip @@ -149,10 +152,9 @@ public class MSP430Core extends Chip implements MSP430Constants { // Ignore type for now... setModeNames(MODE_NAMES); - int passIO = 0; // IOUnits should likely be placed in a hashtable? // Maybe for debugging purposes... - ioUnits = new IOUnit[PORTS + 9]; + ioUnits = new ArrayList(); // first step towards making core configurable Timer ta = new Timer(this, memory, config.timerConfig[0]); @@ -201,44 +203,45 @@ public class MSP430Core extends Chip implements MSP430Constants { // Add port 1,2 with interrupt capability! - ioUnits[0] = new IOPort(this, 1, 4, memory, 0x20); - ioUnits[1] = new IOPort(this, 2, 1, memory, 0x28); + ioUnits.add(new IOPort(this, 1, 4, memory, 0x20)); + ioUnits.add(new IOPort(this, 2, 1, memory, 0x28)); for (int i = 0, n = 8; i < n; i++) { - memOut[0x20 + i] = ioUnits[0]; - memOut[0x28 + i] = ioUnits[1]; + memOut[0x20 + i] = ioUnits.get(0); + memOut[0x28 + i] = ioUnits.get(1); } // Add port 3,4 & 5,6 for (int i = 0, n = 2; i < n; i++) { - ioUnits[i + 2] = new IOPort(this, (3 + i), 0, memory, 0x18 + i * 4); - memOut[0x18 + i * 4] = ioUnits[i + 2]; - memOut[0x19 + i * 4] = ioUnits[i + 2]; - memOut[0x1a + i * 4] = ioUnits[i + 2]; - memOut[0x1b + i * 4] = ioUnits[i + 2]; + ioUnits.add(new IOPort(this, (3 + i), 0, memory, 0x18 + i * 4)); + memOut[0x18 + i * 4] = ioUnits.get(i + 2); + memOut[0x19 + i * 4] = ioUnits.get(i + 2); + memOut[0x1a + i * 4] = ioUnits.get(i + 2); + memOut[0x1b + i * 4] = ioUnits.get(i + 2); + } - ioUnits[i + 4] = new IOPort(this, (5 + i), 0, memory, 0x30 + i * 4); + for (int i = 0, n = 2; i < n; i++) { + ioUnits.add(new IOPort(this, (5 + i), 0, memory, 0x30 + i * 4)); - memOut[0x30 + i * 4] = ioUnits[i + 4]; - memOut[0x31 + i * 4] = ioUnits[i + 4]; - memOut[0x32 + i * 4] = ioUnits[i + 4]; - memOut[0x33 + i * 4] = ioUnits[i + 4]; + memOut[0x30 + i * 4] = ioUnits.get(i + 4); + memOut[0x31 + i * 4] = ioUnits.get(i + 4); + memOut[0x32 + i * 4] = ioUnits.get(i + 4); + memOut[0x33 + i * 4] = ioUnits.get(i + 4); } - passIO = 6; // SFR and Basic clock system. - ioUnits[passIO++] = sfr; - ioUnits[passIO++] = bcs; + ioUnits.add(sfr); + ioUnits.add(bcs); - passIO += config.setup(this, ioUnits, passIO); + config.setup(this, ioUnits); // Add the timers - ioUnits[passIO++] = ta; - ioUnits[passIO++] = tb; + ioUnits.add(ta); + ioUnits.add(tb); ADC12 adc12 = new ADC12(this); - ioUnits[passIO++] = adc12; + ioUnits.add(adc12); - ioUnits[passIO++] = watchdog; + ioUnits.add(watchdog); for (int i = 0, n = 16; i < n; i++) { memOut[0x80 + i] = adc12; @@ -252,9 +255,8 @@ public class MSP430Core extends Chip implements MSP430Constants { memOut[0x1A0 + i] = adc12; memIn[0x1A0 + i] = adc12; } - - - if (DEBUG) System.out.println("Number of passive: " + passIO); + + if (DEBUG) System.out.println("Number of passive: " + ioUnits.size()); } public Profiler getProfiler() { @@ -278,7 +280,7 @@ public class MSP430Core extends Chip implements MSP430Constants { /* returns port 1 ... 6 */ public IOPort getIOPort(int portID) { if (portID > 0 && portID < 7) { - return (IOPort) ioUnits[portID - 1]; + return (IOPort) ioUnits.get(portID - 1); } return null; } @@ -311,12 +313,12 @@ public class MSP430Core extends Chip implements MSP430Constants { } public Loggable[] getLoggables() { - Loggable[] ls = new Loggable[ioUnits.length + chips.size()]; - for (int i = 0; i < ioUnits.length; i++) { - ls[i] = ioUnits[i]; + Loggable[] ls = new Loggable[ioUnits.size() + chips.size()]; + for (int i = 0; i < ioUnits.size(); i++) { + ls[i] = ioUnits.get(i); } for (int i = 0; i < chips.size(); i++) { - ls[i + ioUnits.length] = chips.get(i); + ls[i + ioUnits.size()] = chips.get(i); } return ls; } @@ -580,17 +582,19 @@ public class MSP430Core extends Chip implements MSP430Constants { // Should also return active units... public IOUnit getIOUnit(String name) { - for (int i = 0, n = ioUnits.length; i < n; i++) { - if (name.equalsIgnoreCase(ioUnits[i].getID()) || name.equalsIgnoreCase(ioUnits[i].getName())) { - return ioUnits[i]; + for (int i = 0, n = ioUnits.size(); i < n; i++) { + IOUnit ioUnit = ioUnits.get(i); + if (ioUnit != null && name.equalsIgnoreCase(ioUnit.getID()) || + name.equalsIgnoreCase(ioUnit.getName())) { + return ioUnit; } } return null; } private void resetIOUnits() { - for (int i = 0, n = ioUnits.length; i < n; i++) { - ioUnits[i].reset(RESET_POR); + for (int i = 0, n = ioUnits.size(); i < n; i++) { + ioUnits.get(i).reset(RESET_POR); } } diff --git a/se/sics/mspsim/core/SFR.java b/se/sics/mspsim/core/SFR.java index 6feb197..2a88702 100644 --- a/se/sics/mspsim/core/SFR.java +++ b/se/sics/mspsim/core/SFR.java @@ -65,11 +65,12 @@ public class SFR extends IOUnit { private int[] memory; private MSP430Core cpu; - private SFRModule[] sfrModule = new SFRModule[16]; - private int[] irqVector = new int[16]; - private boolean[] irqTriggered = new boolean[16]; - private boolean[] autoclear = new boolean[16]; - private int[] irqTriggeredPos = new int[16]; + /* 64 = max number of interrupts */ + private SFRModule[] sfrModule = new SFRModule[64]; + private int[] irqVector = new int[64]; + private boolean[] irqTriggered = new boolean[64]; + private boolean[] autoclear = new boolean[64]; + private int[] irqTriggeredPos = new int[64]; public SFR(MSP430Core cpu, int[] memory) { super("SFR", "Special Function Register", memory, 0); @@ -223,6 +224,7 @@ public class SFR extends IOUnit { int change = value ^ after; if (index == 0) ifg1 = after; else ifg2 = after; + updateIRQ(index, change); } diff --git a/se/sics/mspsim/core/USART.java b/se/sics/mspsim/core/USART.java index 4a70a4f..9b6238a 100644 --- a/se/sics/mspsim/core/USART.java +++ b/se/sics/mspsim/core/USART.java @@ -41,7 +41,7 @@ package se.sics.mspsim.core; -public class USART extends IOUnit implements SFRModule, DMATrigger { +public class USART extends IOUnit implements SFRModule, DMATrigger, USARTSource { // USART 0/1 register offset (0x70 / 0x78) public static final int UCTL = 0; diff --git a/se/sics/mspsim/core/USARTListener.java b/se/sics/mspsim/core/USARTListener.java index e22d306..a8e16cb 100644 --- a/se/sics/mspsim/core/USARTListener.java +++ b/se/sics/mspsim/core/USARTListener.java @@ -43,5 +43,5 @@ package se.sics.mspsim.core; public interface USARTListener { public static int RXFLAG_CLEARED = 1; - public void dataReceived(USART source, int data); + public void dataReceived(USARTSource source, int data); } diff --git a/se/sics/mspsim/core/USARTSource.java b/se/sics/mspsim/core/USARTSource.java new file mode 100755 index 0000000..a84e8f8 --- /dev/null +++ b/se/sics/mspsim/core/USARTSource.java @@ -0,0 +1,11 @@ +package se.sics.mspsim.core; + +public interface USARTSource { + + public void setUSARTListener(USARTListener listener); + + /* for input into this UART */ + public boolean isReceiveFlagCleared(); + public void byteReceived(int b); + +} diff --git a/se/sics/mspsim/core/USCI.java b/se/sics/mspsim/core/USCI.java new file mode 100755 index 0000000..36be095 --- /dev/null +++ b/se/sics/mspsim/core/USCI.java @@ -0,0 +1,500 @@ +/** + * 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$ + * + * ----------------------------------------------------------------- + * + * USART + * + * Author : Joakim Eriksson + * Created : Sun Oct 21 22:00:00 2007 + * Updated : $Date$ + * $Revision$ + */ + +package se.sics.mspsim.core; + + +public class USCI extends IOUnit implements SFRModule, DMATrigger, USARTSource { + + // USART 0/1 register offset (0x60 / 0xD0) + public static final int UAxCTL0 = 0; + public static final int UAxCTL1 = 1; + public static final int UAxBR0 = 2; + public static final int UAxBR1 = 3; + public static final int UAxMCTL = 4; + public static final int UAxSTAT = 5; + public static final int UAxRXBUF = 6; + public static final int UAxTXBUF = 7; + + // SPI related registers + public static final int UBxCTL0 = 8; + public static final int UBxCTL1 = 9; + public static final int UBxBR0 = 0xa; + public static final int UBxBR1 = 0xb; + public static final int UBxSTAT = 0xd; + public static final int UBxRXBUF = 0xe; + public static final int UBxTXBUF = 0xf; + + // IrDA related (negative offset ??) + public static final int UABCTL = -3; /* very odd... */ + public static final int UIRTCTL = -2; + public static final int UIRRCTL = -1; + + // Interrupt flags... + public static final int UTXIFG0 = 0x80; + public static final int URXIFG0 = 0x40; + + public static final int UTXIFG1 = 0x20; + public static final int URXIFG1 = 0x10; + + // USART SRF mod enable registers (absolute + 1) + public static final int ME1 = 4; + public static final int IE1 = 0; + public static final int IFG1 = 2; + + private final int uartID; + + // Flags. + public static final int UTCTL_TXEMPTY = 0x01; + public static final int UTCTL_URXSE = 0x08; + public static final int USCI_BUSY = 0x01; + + private USARTListener listener; + + private int utxifg; + private int urxifg; + private int rxVector; + + private int clockSource = 0; + private int baudRate = 0; + private int tickPerByte = 1000; + private long nextTXReady = -1; + private int nextTXByte = -1; + private int txShiftReg = -1; + private boolean transmitting = false; + + private MSP430Core cpu; + private SFR sfr; + private int sfrAddress; + + /* ifg and ie if not in sfr... - assume IE in sfraddr and IFG in addr + 1*/ + private int ifgAddress = 0; + private int ieAddress = 0; + + private int uctl0; + private int uctl1; + private int umctl; + private int ubr0; + private int ubr1; + private int urxbuf; + private int utxbuf; + private int ustat; + private int txbit; + + private boolean txEnabled = false; + private boolean rxEnabled = false; + private boolean spiMode = false; + + /* DMA controller that needs to be called at certain times */ + private DMA dma; + private int dmaIndex; + + private boolean usciA = true; /* if this is an USCI A or B */ + + private TimeEvent txTrigger = new TimeEvent(0) { + public void execute(long t) { + // Ready to transmit new byte! + handleTransmit(t); + } + }; + + /** + * Creates a new USART instance. + * + */ + public USCI(MSP430Core cpu, int uartID, int[] memory, MSP430Config config) { + super(config.uartConfig[uartID].name, config.uartConfig[uartID].name, memory, config.uartConfig[uartID].offset); + System.out.println("NAME: " + config.uartConfig[uartID].name); + this.cpu = cpu; + this.uartID = uartID; + MSP430Config.UARTConfig uartConfig = config.uartConfig[uartID]; + + // Initialize - transmit = ok... + // and set which interrupts are used + if (uartConfig.sfrAddr < 2) { + sfr = cpu.getSFR(); + sfrAddress = uartConfig.sfrAddr; + sfr.registerSFDModule(uartConfig.sfrAddr, uartConfig.rxBit, this, uartConfig.rxVector); + sfr.registerSFDModule(uartConfig.sfrAddr, uartConfig.txBit, this, uartConfig.txVector); + } else { + ieAddress = uartConfig.sfrAddr; + ifgAddress = uartConfig.sfrAddr + 1; + } + utxifg = 1 << uartConfig.txBit; + urxifg = 1 << uartConfig.rxBit; + txbit = uartConfig.txBit; + rxVector = uartConfig.rxVector; + usciA = uartConfig.usciA; + reset(0); + } + + public void setDMA(DMA dma) { + this.dma = dma; + } + + + public void reset(int type) { + nextTXReady = cpu.cycles + 100; + txShiftReg = nextTXByte = -1; + transmitting = false; + clrBitIFG(urxifg); + setBitIFG(utxifg); /* empty at start! */ + ustat &= ~USCI_BUSY; + txEnabled = true; //false; + rxEnabled = true; //false; + } + + public void enableChanged(int reg, int bit, boolean enabled) { + if (DEBUG) log("enableChanged: " + reg + " bit: " + bit + + " enabled = " + enabled + " txBit: " + txbit); + if (bit == txbit) { + txEnabled = enabled; + } else { + rxEnabled = enabled; + } + } + + private void setBitIFG(int bits) { + if ((bits) > 0) { + System.out.println(getName() + " Set utxifg = " + utxifg + + " sfrA: " + sfrAddress + " bits: " + bits); + } + if (sfr != null) { + sfr.setBitIFG(sfrAddress, bits); + System.out.println("SFR =>" + sfr.getIFG(sfrAddress)); + } else { + memory[ifgAddress] |= bits; + } + if (dma != null) { + /* set bit first, then trigger DMA transfer - this should + * be made via a 1 cycle or so delayed action */ + if ((bits & urxifg) > 0) dma.trigger(this, 0); + if ((bits & utxifg) > 0) dma.trigger(this, 1); + } + } + + private void clrBitIFG(int bits) { +// if ((bits & utxifg) > 0) { +// System.out.println(getName() + " Clear utxifg"); +// } + if (sfr != null) { + sfr.clrBitIFG(sfrAddress, bits); + } else { + memory[ifgAddress] &= ~bits; + } + } + + private int getIFG() { + if (sfr != null) + return sfr.getIFG(sfrAddress); + return memory[ifgAddress]; + } + + private boolean isIEBitsSet(int bits) { + if (sfr != null) + return sfr.isIEBitsSet(sfrAddress, bits); + return (memory[ieAddress] & bits) > 0; + } + + /* reuse USART listener API for USCI */ + public void setUSARTListener(USARTListener listener) { + this.listener = listener; + } + + // Only 8 bits / read! + public void write(int address, int data, boolean word, long cycles) { + if (address == ieAddress || address == ifgAddress) { + memory[address] = data; + } + address = address - offset; + + // Indicate ready to write!!! - this should not be done here... +// System.out.println(">>>> Write to " + getName() + " at " + +// address + " = " + data); + switch (address) { + case UAxCTL0: + case UBxCTL0: + uctl0 = data; + spiMode = (data & 0x01) > 0; + if (DEBUG) log(" write to UAxCTL0 " + data); + break; + case UAxCTL1: + case UBxCTL1: + /* emulate the reset */ + if ((uctl1 & 1) == 1 && (data & 1) == 0) + reset(0); + uctl1 = data; + if (DEBUG) log(" write to UAxCTL1 " + data); + + if (((data >> 6) & 3) == 1) { + clockSource = MSP430Constants.CLK_ACLK; + if (DEBUG) { + log(" Selected ACLK as source"); + } + } else { + clockSource = MSP430Constants.CLK_SMCLK; + if (DEBUG) { + log(" Selected SMCLK as source"); + } + } + updateBaudRate(); + break; + case UAxMCTL: + umctl = data; + if (DEBUG) log(" write to UMCTL " + data); + break; + case UAxBR0: + case UBxBR0: + ubr0 = data; + updateBaudRate(); + break; + case UAxBR1: + case UBxBR1: + ubr1 = data; + updateBaudRate(); + break; + case UAxSTAT: + case UBxSTAT: + //ustat = data; + break; + case UAxTXBUF: + case UBxTXBUF: + if (DEBUG) log(": USART_UTXBUF:" + (char) data + " = " + data + "\n"); + if (txEnabled || (spiMode && rxEnabled)) { + // Interruptflag not set! + clrBitIFG(utxifg); + /* the TX is no longer empty ! */ + ustat |= USCI_BUSY; + /* should the interrupt be flagged off here ? - or only the flags */ + if (DEBUG) log(" flagging off transmit interrupt"); + // cpu.flagInterrupt(transmitInterrupt, this, false); + + // Schedule on cycles here + // TODO: adding 3 extra cycles here seems to give + // slightly better timing in some test... + + nextTXByte = data; + if (!transmitting) { + /* how long time will the copy from the TX_BUF to the shift reg take? */ + /* assume 3 cycles? */ + nextTXReady = cycles + 1; //tickPerByte + 3; + cpu.scheduleCycleEvent(txTrigger, nextTXReady); + } + } else { + log("Ignoring UTXBUF data since TX not active..."); + } + utxbuf = data; + break; + } + } + + public int read(int address, boolean word, long cycles) { + if (address == ieAddress || address == ifgAddress) { + return memory[address]; + } + address = address - offset; +// System.out.println(">>>>> Read from " + getName() + " at " + +// address); + + switch (address) { + case UAxCTL0: + case UBxCTL0: + if (DEBUG) log(" read from UCTL"); + return uctl0; + case UAxCTL1: + case UBxCTL1: + if (DEBUG) log(" read from UTCTL: " + uctl1); + return uctl1; + case UAxMCTL: + return umctl; + case UAxBR0: + case UBxBR0: + return ubr0; + case UAxBR1: + case UBxBR1: + return ubr1; + case UAxTXBUF: + case UBxTXBUF: + return utxbuf; + case UAxSTAT: + case UBxSTAT: +// System.out.println(getName() + " Reading STAT: " + ustat); + return ustat; + case UAxRXBUF: + case UBxRXBUF: + int tmp = urxbuf; + // When byte is read - the interruptflag is cleared! + // and error status should also be cleared later... + // is this cleared also on the MSP430x2xx series??? + if (MSP430Constants.DEBUGGING_LEVEL > 0) { + log(" clearing rx interrupt flag " + cpu.getPC() + " byte: " + tmp); + } + clrBitIFG(urxifg); + /* This should be changed to a state rather than an "event" */ + /* Force callback since this is not used as a state */ + stateChanged(USARTListener.RXFLAG_CLEARED, true); + return tmp; + } + return 0; + } + + private void updateBaudRate() { + int div = ubr0 + (ubr1 << 8); + if (div == 0) { + div = 1; + } + if (clockSource == MSP430Constants.CLK_ACLK) { + if (DEBUG) { + log(" Baud rate is (bps): " + cpu.aclkFrq / div + " div = " + div); + } + baudRate = cpu.aclkFrq / div; + } else { + if (DEBUG) { + log(" Baud rate is (bps): " + cpu.smclkFrq / div + " div = " + div); + } + baudRate = cpu.smclkFrq / div; + } + if (baudRate == 0) baudRate = 1; + // Is this correct??? Is it the DCO or smclkFRQ we should have here??? + tickPerByte = (8 * cpu.smclkFrq) / baudRate; + if (DEBUG) { + log(" Ticks per byte: " + tickPerByte); + } + } + + // We should add "Interrupt serviced..." to indicate that its latest + // Interrupt was serviced... + public void interruptServiced(int vector) { + /* NOTE: this is handled by SFR : clear IFG bit if interrupt is serviced */ +// System.out.println(getName() + " SFR irq " + vector + " " + txShiftReg + " " + getIFG()); + } + + private void handleTransmit(long cycles) { + if (cpu.getMode() >= MSP430Core.MODE_LPM3) { + System.out.println(getName() + " Warning: USART transmission during LPM!!! " + nextTXByte); + } + + if (transmitting) { + /* in this case we have shifted out the last character */ + if (listener != null && txShiftReg != -1) { + listener.dataReceived(this, txShiftReg); + } + /* nothing more to transmit after this - stop transmission */ + if (nextTXByte == -1) { + /* ~BUSY - nothing more to send - and last data already in RX */ + ustat &= ~USCI_BUSY; + transmitting = false; + txShiftReg = -1; + } + } + + /* any more chars to transmit? */ + if (nextTXByte != -1) { + txShiftReg = nextTXByte; + nextTXByte = -1; + /* txbuf always empty after this */ + setBitIFG(utxifg); + transmitting = true; + nextTXReady = cycles + tickPerByte + 1; + cpu.scheduleCycleEvent(txTrigger, nextTXReady); + } + + if (DEBUG) { + if (isIEBitsSet(utxifg)) { + log(" flagging on transmit interrupt"); + } + log(" Ready to transmit next at: " + cycles); + } + } + + + public boolean isReceiveFlagCleared() { + return (getIFG() & urxifg) == 0; + } + + // A byte have been received! + // This needs to be complemented with a method for checking if the USART + // is ready for next byte (readyForReceive) that respects the current speed + public void byteReceived(int b) { + System.out.println(getName() + " byte received: " + b + " enabled:" + rxEnabled); + if (!rxEnabled) return; + + if (DEBUG || true) { + log(" byteReceived: " + b + " " + (char) b); + } + urxbuf = b & 0xff; + // Indicate interrupt also! + setBitIFG(urxifg); + + // Check if the IE flag is enabled! - same as the IFlag to indicate! + if (isIEBitsSet(urxifg)) { + if (DEBUG) { + log(" flagging receive interrupt "); + } + } + } + + public String info() { + return "UTXIE: " + isIEBitsSet(utxifg) + " URXIE:" + isIEBitsSet(urxifg) + "\n" + + "UTXIFG: " + ((getIFG() & utxifg) > 0) + " URXIFG:" + ((getIFG() & urxifg) > 0); + } + + public boolean getDMATriggerState(int index) { + if (index == 0) { + return (getIFG() & urxifg) > 0; + } else { + return (getIFG() & utxifg) > 0; + } + } + + public void clearDMATrigger(int index) { + System.out.println("UART clearing DMA " + index); + if (index == 0) { + /* clear RX - might be different in different modes... */ + System.out.println("UART clearing read bit!"); + clrBitIFG(urxifg); + stateChanged(USARTListener.RXFLAG_CLEARED, true); + } else { + /* clear TX - might be different in different modes... */ + clrBitIFG(utxifg); + } + } +} \ No newline at end of file diff --git a/se/sics/mspsim/platform/jcreate/JCreateNode.java b/se/sics/mspsim/platform/jcreate/JCreateNode.java index a470636..9297a2d 100644 --- a/se/sics/mspsim/platform/jcreate/JCreateNode.java +++ b/se/sics/mspsim/platform/jcreate/JCreateNode.java @@ -51,6 +51,7 @@ 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; @@ -97,7 +98,7 @@ public class JCreateNode extends CC2420Node { // USART Listener @Override - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { radio.dataReceived(source, data); flash.dataReceived(source, data); /* if nothing selected, just write back a random byte to this device */ diff --git a/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java b/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java index e2e81ce..3a47929 100644 --- a/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java +++ b/se/sics/mspsim/platform/sentillausb/SentillaUSBNode.java @@ -47,6 +47,7 @@ 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; @@ -91,7 +92,7 @@ public class SentillaUSBNode extends CC2420Node { // USART Listener @Override - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { radio.dataReceived(source, data); flash.dataReceived(source, data); /* if nothing selected, just write back a random byte to this device */ diff --git a/se/sics/mspsim/platform/sky/CC2420Node.java b/se/sics/mspsim/platform/sky/CC2420Node.java index adca94b..b989a71 100644 --- a/se/sics/mspsim/platform/sky/CC2420Node.java +++ b/se/sics/mspsim/platform/sky/CC2420Node.java @@ -10,6 +10,7 @@ import se.sics.mspsim.core.MSP430Config; import se.sics.mspsim.core.PortListener; import se.sics.mspsim.core.USART; import se.sics.mspsim.core.USARTListener; +import se.sics.mspsim.core.USARTSource; import se.sics.mspsim.extutil.jfreechart.DataChart; import se.sics.mspsim.extutil.jfreechart.DataSourceSampler; import se.sics.mspsim.platform.GenericNode; @@ -200,7 +201,7 @@ public abstract class CC2420Node extends GenericNode implements PortListener, US protected abstract void flashWrite(IOPort source, int data); - public abstract void dataReceived(USART source, int data); + public abstract void dataReceived(USARTSource source, int data); public void stateChanged(int state) { // Ignore UART state changes by default diff --git a/se/sics/mspsim/platform/sky/SkyNode.java b/se/sics/mspsim/platform/sky/SkyNode.java index 77f5a02..3e88f87 100644 --- a/se/sics/mspsim/platform/sky/SkyNode.java +++ b/se/sics/mspsim/platform/sky/SkyNode.java @@ -45,6 +45,7 @@ import se.sics.mspsim.chip.FileM25P80; 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.util.ArgumentManager; /** @@ -74,7 +75,7 @@ public class SkyNode extends MoteIVNode { } // USART Listener - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { radio.dataReceived(source, data); flash.dataReceived(source, data); /* if nothing selected, just write back a random byte to these devs */ diff --git a/se/sics/mspsim/platform/sky/TelosNode.java b/se/sics/mspsim/platform/sky/TelosNode.java index c388701..a8362df 100644 --- a/se/sics/mspsim/platform/sky/TelosNode.java +++ b/se/sics/mspsim/platform/sky/TelosNode.java @@ -45,6 +45,7 @@ import se.sics.mspsim.chip.AT45DB; import se.sics.mspsim.chip.FileAT45DB; import se.sics.mspsim.core.IOPort; import se.sics.mspsim.core.USART; +import se.sics.mspsim.core.USARTSource; import se.sics.mspsim.util.ArgumentManager; /** @@ -84,7 +85,7 @@ public class TelosNode extends MoteIVNode { } // USART Listener - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { radio.dataReceived(source, data); flash.dataReceived(source, data); } diff --git a/se/sics/mspsim/platform/z1/Z1Node.java b/se/sics/mspsim/platform/z1/Z1Node.java index 9ffe36d..7ebe9c6 100644 --- a/se/sics/mspsim/platform/z1/Z1Node.java +++ b/se/sics/mspsim/platform/z1/Z1Node.java @@ -11,6 +11,8 @@ import se.sics.mspsim.core.IOUnit; import se.sics.mspsim.core.PortListener; import se.sics.mspsim.core.USART; import se.sics.mspsim.core.USARTListener; +import se.sics.mspsim.core.USARTSource; +import se.sics.mspsim.core.USCI; import se.sics.mspsim.platform.GenericNode; import se.sics.mspsim.ui.SerialMon; import se.sics.mspsim.util.ArgumentManager; @@ -59,7 +61,8 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { registry.registerComponent("xmem", flash); } - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { + USCI s = (USCI) source; radio.dataReceived(source, data); flash.dataReceived(source, data); /* if nothing selected, just write back a random byte to these devs */ @@ -69,17 +72,16 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { } public void portWrite(IOPort source, int data) { - System.out.println("Write to port: " + source + " => " + data); if (source == port5) { System.out.println("LEDS GREEN = " + ((data & LEDS_CONF_GREEN) > 0)); System.out.println("LEDS RED = " + ((data & LEDS_CONF_RED) > 0)); System.out.println("LEDS YELLOW = " + ((data & LEDS_CONF_YELLOW) > 0)); } if (source == port3) { + // Chip select = active low... radio.setChipSelect((data & CC2420_CHIP_SELECT) == 0); } if (source == port4) { - // Chip select = active low... radio.setVRegOn((data & CC2420_VREG) != 0); //radio.portWrite(source, data); flash.portWrite(source, data); @@ -112,18 +114,17 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { port5.setPortListener(this); } - IOUnit usart0 = cpu.getIOUnit("USART0"); - if (usart0 instanceof USART) { + IOUnit usart0 = cpu.getIOUnit("USCI B0"); + if (usart0 instanceof USCI) { radio = new CC2420(cpu); radio.setCCAPort(port1, CC2420_CCA); radio.setFIFOPPort(port1, CC2420_FIFOP); radio.setFIFOPort(port1, CC2420_FIFO); - ((USART) usart0).setUSARTListener(this); + ((USARTSource) usart0).setUSARTListener(this); if (port4 != null) { radio.setSFDPort(port4, CC2420_SFD); } - } } @@ -151,9 +152,9 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { setupGUI(); // Add some windows for listening to serial output - IOUnit usart = cpu.getIOUnit("USART1"); - if (usart instanceof USART) { - SerialMon serial = new SerialMon((USART)usart, "USART1 Port Output"); + IOUnit usart = cpu.getIOUnit("USCI A0"); + if (usart instanceof USARTSource) { + SerialMon serial = new SerialMon((USARTSource)usart, "USART1 Port Output"); registry.registerComponent("serialgui", serial); } } @@ -175,4 +176,5 @@ public class Z1Node extends GenericNode implements PortListener, USARTListener { config.handleArguments(args); node.setupArgs(config); } + } diff --git a/se/sics/mspsim/ui/SerialMon.java b/se/sics/mspsim/ui/SerialMon.java index cd675ff..eba9e24 100644 --- a/se/sics/mspsim/ui/SerialMon.java +++ b/se/sics/mspsim/ui/SerialMon.java @@ -54,9 +54,10 @@ import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; +import se.sics.mspsim.core.IOUnit; import se.sics.mspsim.core.StateChangeListener; -import se.sics.mspsim.core.USART; import se.sics.mspsim.core.USARTListener; +import se.sics.mspsim.core.USARTSource; import se.sics.mspsim.util.ComponentRegistry; import se.sics.mspsim.util.ServiceComponent; @@ -67,7 +68,7 @@ public class SerialMon implements USARTListener, StateChangeListener, ServiceCom private String name; private ServiceComponent.Status status = Status.STOPPED; - private final USART usart; + private final USARTSource usart; private final String title; private JFrame window; @@ -86,7 +87,7 @@ public class SerialMon implements USARTListener, StateChangeListener, ServiceCom private int lines = 1; private boolean isUpdatePending = false; - public SerialMon(USART usart, String title) { + public SerialMon(USARTSource usart, String title) { this.usart = usart; this.title = title; } @@ -199,7 +200,7 @@ public class SerialMon implements USARTListener, StateChangeListener, ServiceCom if (window == null) { initGUI(); usart.setUSARTListener(this); - usart.addStateChangeListener(this); + ((IOUnit) usart).addStateChangeListener(this); } window.setVisible(true); status = Status.STARTED; @@ -212,7 +213,7 @@ public class SerialMon implements USARTListener, StateChangeListener, ServiceCom } } - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { if (data == '\n') { if (lines >= MAX_LINES) { int index = text.indexOf('\n'); diff --git a/se/sics/mspsim/util/Test.java b/se/sics/mspsim/util/Test.java index e005703..eeaffb5 100644 --- a/se/sics/mspsim/util/Test.java +++ b/se/sics/mspsim/util/Test.java @@ -61,7 +61,7 @@ public class Test implements USARTListener { } } - public void dataReceived(USART source, int data) { + public void dataReceived(USARTSource source, int data) { if (data == '\n') { String line = lineBuffer.toString(); lineBuffer.setLength(0);