added improved support for Z1/2xxx platform

This commit is contained in:
Joakim Eriksson 2011-04-08 22:21:36 +02:00
parent d7a36abbfb
commit 6ab1eadb97
22 changed files with 682 additions and 81 deletions

2
.gitignore vendored Executable file
View File

@ -0,0 +1,2 @@
*.class
.DS_Store

View File

@ -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) {

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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<IOUnit> 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;
}
}

View File

@ -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<IOUnit> 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;
}
}

View File

@ -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<IOUnit> ioUnits);
}

View File

@ -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<IOUnit> 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<IOUnit>();
// 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);
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

500
se/sics/mspsim/core/USCI.java Executable file
View File

@ -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 <code>USART</code> 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);
}
}
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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');

View File

@ -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);