Improved support for emulation of msp430f2xxx series

This commit is contained in:
Niclas Finne 2012-05-29 11:41:33 +02:00
parent b207699337
commit 0f1d0ff978
6 changed files with 105 additions and 73 deletions

View File

@ -49,7 +49,17 @@ import se.sics.mspsim.util.Utils;
public class MSP430f2617Config extends MSP430Config {
private static final String portConfig[] = {
"P1=0,IN 20,OUT 21,DIR 22,IFG 23,IES 24,IE 25,SEL 26,SEL2 41,REN 27",
"P2=0,IN 28,OUT 29,DIR 2A,IFG 2B,IES 2C,IE 2D,SEL 2E,SEL2 42,REN 2F",
"P3=0,IN 18,OUT 19,DIR 1A,SEL 1B,SEL2 43,REN 10",
"P4=0,IN 1C,OUT 1D,DIR 1E,SEL 1F,SEL2 44,REN 11",
"P5=0,IN 30,OUT 31,DIR 32,SEL 33,SEL2 45,REN 12",
"P6=0,IN 34,OUT 35,DIR 36,SEL 37,SEL2 46,REN 13",
"P7=0,IN 38,OUT 3A,DIR 3C,SEL 3E,SEL2 47,REN 14",
"P8=0,IN 39,OUT 3B,DIR 3D,SEL 3F,SEL2 48,REN 15"
};
public MSP430f2617Config() {
/* 32 vectors for the MSP430X series */
maxInterruptVector = 31;
@ -62,9 +72,9 @@ public class MSP430f2617Config extends MSP430Config {
/* 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 uB0 = new UARTConfig(22, 23, 3, 2, 1, 0x68, "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 uB1 = new UARTConfig(16, 17, 3, 2, 6, 0xD8, "USCI B1", false);
uartConfig = new UARTConfig[] {uA0, uB0, uA1, uB1};
/* configure memory */
@ -103,13 +113,12 @@ public class MSP430f2617Config extends MSP430Config {
// Add port 1,2 with interrupt capability!
// IOPorts will add themselves to the CPU
ioUnits.add(new IOPort(cpu, 1, 4, cpu.memory, 0x20));
ioUnits.add(new IOPort(cpu, 2, 1, cpu.memory, 0x28));
IOPort last = null;
ioUnits.add(last = IOPort.parseIOPort(cpu, 18, portConfig[0], last));
ioUnits.add(last = IOPort.parseIOPort(cpu, 19, portConfig[1], last));
// Add port 3,4 & 5,6
for (int i = 0, n = 2; i < n; i++) {
ioUnits.add(new IOPort(cpu, (3 + i), 0, cpu.memory, 0x18 + i * 4));
ioUnits.add(new IOPort(cpu, (5 + i), 0, cpu.memory, 0x30 + i * 4));
for (int i = 2; i < portConfig.length; i++) {
ioUnits.add(last = IOPort.parseIOPort(cpu, 0, portConfig[i], last));
}
ADC12 adc12 = new ADC12(cpu);

View File

@ -36,6 +36,7 @@
package se.sics.mspsim.config;
import java.util.ArrayList;
import se.sics.mspsim.core.ClockSystem;
import se.sics.mspsim.core.GenericUSCI;
import se.sics.mspsim.core.IOPort;
import se.sics.mspsim.core.IOUnit;
@ -43,6 +44,7 @@ import se.sics.mspsim.core.MSP430Config;
import se.sics.mspsim.core.MSP430Core;
import se.sics.mspsim.core.Multiplier32;
import se.sics.mspsim.core.Timer;
import se.sics.mspsim.core.UnifiedClockSystem;
import se.sics.mspsim.util.Utils;
public class MSP430f5437Config extends MSP430Config {
@ -113,12 +115,12 @@ public class MSP430f5437Config extends MSP430Config {
// System.out.println("Adding IOUnit USCI: " + usci.getName());
ioUnits.add(usci);
}
ioUnits.add(IOPort.parseIOPort(cpu, 47, portConfig[0]));
ioUnits.add(IOPort.parseIOPort(cpu, 42, portConfig[1]));
IOPort last = null;
ioUnits.add(last = IOPort.parseIOPort(cpu, 47, portConfig[0], last));
ioUnits.add(last = IOPort.parseIOPort(cpu, 42, portConfig[1], last));
for (int i = 2; i < portConfig.length; i++) {
ioUnits.add(IOPort.parseIOPort(cpu, 0, portConfig[i]));
ioUnits.add(last = IOPort.parseIOPort(cpu, 0, portConfig[i], last));
}
return portConfig.length + uartConfig.length;
@ -129,4 +131,9 @@ public class MSP430f5437Config extends MSP430Config {
return Utils.hex20(addr);
}
@Override
public ClockSystem createClockSystem(MSP430Core cpu, int[] memory, Timer[] timers) {
return new UnifiedClockSystem(cpu, memory, 0, timers);
}
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2007, Swedish Institute of Computer Science.
* Copyright (c) 2007-2012, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -36,47 +36,14 @@
*/
package se.sics.mspsim.core;
import java.util.Arrays;
import se.sics.mspsim.util.Utils;
public class IOPort extends IOUnit {
public enum PinState { LOW, HI };
private final int port;
private final int interrupt;
// External pin state!
private PinState pinState[] = new PinState[8];
/* NOTE: The offset needs to be configurable since the new IOPorts on
* the 5xxx series are located at other addresses.
* Maybe create another IOPort that just convert IOAddress to this 'old' mode?
* - will be slightly slower on IOWrite/read but very easy to implement.
*
*
*
*
*
*
*/
enum PortReg {IN, OUT, DIR, SEL, IFG, IES, IE, REN, DS, IV_L, IV_H};
public static final int IN = 0;
public static final int OUT = 1;
public static final int DIR = 2;
public static final int SEL = 4; /* what about SEL2? */
public static final int IFG = 5;
public static final int IES = 6;
public static final int IE = 7;
public static final int REN = 8;
public static final int DS = 9;
public static final int IV_L = 10;
public static final int IV_H = 11;
private static final String[] names = {
"IN", "OUT", "DIR", "SEL", "IFG", "IES", "IE", "REN", "DS" };
public enum PortReg {IN, OUT, DIR, SEL, SEL2, IFG, IES, IE, REN, DS, IV_L, IV_H};
/* portmaps for 1611 */
private static final PortReg[] PORTMAP_INTERRUPT =
@ -84,10 +51,15 @@ public class IOPort extends IOUnit {
private static final PortReg[] PORTMAP_NO_INTERRUPT =
{PortReg.IN, PortReg.OUT, PortReg.DIR, PortReg.SEL};
private final int port;
private final int interrupt;
// External pin state!
private final PinState pinState[] = new PinState[8];
private final PortReg[] portMap;
private PortListener portListener = null;
// represents the direction register
/* Registers for Digital I/O */
@ -95,11 +67,12 @@ public class IOPort extends IOUnit {
private int out;
private int dir;
private int sel;
private int sel2;
private int ie;
private int ifg;
private int ies; /* edge select */
private int ren;
// private int ds;
private int ds;
private int iv; /* low / high */
@ -136,7 +109,7 @@ public class IOPort extends IOUnit {
}
}
public static IOPort parseIOPort(MSP430Core cpu, int interrupt, String specification) {
public static IOPort parseIOPort(MSP430Core cpu, int interrupt, String specification, IOPort last) {
/* Specification = Px=Offset,REG Off, ... */
String[] specs = specification.split(",");
int port = specs[0].charAt(1) - '0';
@ -148,10 +121,17 @@ public class IOPort extends IOUnit {
String[] preg = specs[i].split(" ");
PortReg pr = PortReg.valueOf(preg[0]);
int offs = Integer.parseInt(preg[1], 16);
if (offs >= portMap.length) {
portMap = Arrays.copyOf(portMap, offs + 1);
}
portMap[offs] = pr;
}
return new IOPort(cpu, port, interrupt, cpu.memory, offset, portMap);
IOPort newPort = new IOPort(cpu, port, interrupt, cpu.memory, offset, portMap);
if (last != null && offset == last.offset && offset > 0) {
// This port is a pair with previous port to allow 16 bits writes
last.ioPair = newPort;
}
return newPort;
}
public int getPort() {
@ -202,7 +182,37 @@ public class IOPort extends IOUnit {
}
//System.out.println("*** Setting IV to: " + iv + " ifg: " + ifg);
}
public int getRegister(PortReg register) {
switch(register) {
case DIR:
return dir;
case IE:
return ie;
case IES:
return ies;
case IFG:
return ifg;
case IN:
return in;
case IV_H:
return (iv >> 8) & 0xff;
case IV_L:
return iv & 0xff;
case OUT:
return out;
case REN:
return ren;
case DS:
return ds;
case SEL:
return sel;
case SEL2:
return sel2;
}
return 0;
}
/* only byte access!!! */
int read_port(PortReg function, long cycles) {
switch(function) {
@ -222,6 +232,10 @@ public class IOPort extends IOUnit {
return ies;
case SEL:
return sel;
case SEL2:
return sel2;
case DS:
return ds;
case IV_L:
return iv & 0xff;
case IV_H:
@ -282,7 +296,13 @@ public class IOPort extends IOUnit {
case SEL:
sel = data;
break;
case SEL2:
sel2 = data;
break;
/* Can IV be written ? */
case DS:
ds = data;
break;
case IV_L:
iv = (iv & 0xff00) | data;
break;
@ -381,9 +401,7 @@ public class IOPort extends IOUnit {
public void reset(int type) {
int oldValue = out | (~dir) & 0xff;
for (int i = 0, n = 8; i < n; i++) {
pinState[i] = PinState.LOW;
}
Arrays.fill(pinState, PinState.LOW);
in = 0;
dir = 0;
ren = 0;
@ -401,12 +419,13 @@ public class IOPort extends IOUnit {
public String info() {
StringBuilder sb = new StringBuilder();
/* TODO: USE PORTMAP FOR THIS!!! */
String[] regs = names;
sb.append('$').append(Utils.hex16(offset)).append(':');
for (int i = 0, n = regs.length; i < n; i++) {
sb.append(' ').append(regs[i]).append(":$")
.append(Utils.hex8(0));
sb.append(" $").append(Utils.hex(offset, 2)).append(':');
for (int i = 0, n = portMap.length; i < n; i++) {
PortReg reg = portMap[i];
if (reg != null) {
sb.append(' ').append(reg).append("($").append(Utils.hex(i, 2)).append("):$")
.append(Utils.hex(0, 2));
}
}
return sb.toString();
}

View File

@ -143,5 +143,8 @@ public abstract class MSP430Config {
maxMemIO = size;
}
public ClockSystem createClockSystem(MSP430Core cpu, int[] memory, Timer[] timers) {
return new BasicClockModule(cpu, memory, 0, timers);
}
}

View File

@ -239,13 +239,7 @@ public class MSP430Core extends Chip implements MSP430Constants {
timers[i] = t;
}
// XXX this should be handled by the config, but we do it here to
// avoid changing too much of the mspsim architecture for now
if (MSP430XArch) {
bcs = new UnifiedClockSystem(this, memory, 0, timers);
} else {
bcs = new BasicClockModule(this, memory, 0, timers);
}
bcs = config.createClockSystem(this, memory, timers);
ioSegment.setIORange(bcs.getAddressRangeMin(), bcs.getAddressRangeMax() - bcs.getAddressRangeMin() + 1, bcs);
// SFR and Basic clock system.

View File

@ -168,12 +168,12 @@ public class Multiplier32 extends IOUnit {
public void write(int address, int data, boolean word, long cycles) {
address = address - offset;
if (DEBUG) {
log("write to: " + Utils.hex(address, 4) + " data = " + data + " word = " + word);
log("write to: $" + Utils.hex(address, 4) + " data=" + data + " word=" + word);
}
switch(address) {
case MPY:
op1 = mpy = data;
if (DEBUG) log("Write to MPY: " + data);
op1 = mpy = data;
signed = false;
accumulating = false;
break;