mirror of https://github.com/contiki-ng/mspsim
Rewrote scheduling of timer system to be eventbased instead of "tick" based.
git-svn-id: https://mspsim.svn.sourceforge.net/svnroot/mspsim/mspsim@195 23d1a52b-0c3c-0410-b72d-8f29ab48fe35
This commit is contained in:
parent
bc89b1c17e
commit
848cf2bf87
|
|
@ -45,6 +45,7 @@ public class EventQueue {
|
|||
|
||||
private TimeEvent first;
|
||||
public long nextTime;
|
||||
public int eventCount = 0;
|
||||
|
||||
public EventQueue() {
|
||||
}
|
||||
|
|
@ -58,6 +59,7 @@ public class EventQueue {
|
|||
if (event.scheduled) {
|
||||
removeEvent(event);
|
||||
}
|
||||
eventCount++;
|
||||
if (first == null) {
|
||||
first = event;
|
||||
} else {
|
||||
|
|
@ -116,6 +118,7 @@ public class EventQueue {
|
|||
// System.out.println("Removed =>");
|
||||
// print();
|
||||
event.scheduled = false;
|
||||
eventCount--;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,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 INTERNAL_IO_SIZE = 5;
|
||||
public static final int INTERNAL_IO_SIZE = 3;
|
||||
public static final int PORTS = 6;
|
||||
|
||||
public static final int MODE_ACTIVE = 0;
|
||||
|
|
@ -131,12 +131,14 @@ public class MSP430Core extends Chip implements MSP430Constants {
|
|||
// Ignore type for now...
|
||||
|
||||
// Internal Active IOUnits
|
||||
int passIO = 0;
|
||||
int actIO = 0;
|
||||
ioUnits = new IOUnit[INTERNAL_IO_SIZE + 10];
|
||||
ioCycles = new long[INTERNAL_IO_SIZE + 10];
|
||||
|
||||
// Passive IOUnits (no tick) - do we need to remember them???
|
||||
// Maybe for debugging purposes...
|
||||
passiveIOUnits = new IOUnit[PORTS];
|
||||
passiveIOUnits = new IOUnit[PORTS + 2];
|
||||
|
||||
Timer ta = new Timer(this, Timer.TIMER_Ax149, memory, 0x160);
|
||||
Timer tb = new Timer(this, Timer.TIMER_Bx149, memory, 0x180);
|
||||
|
|
@ -168,15 +170,15 @@ public class MSP430Core extends Chip implements MSP430Constants {
|
|||
memIn[i] = mp;
|
||||
}
|
||||
|
||||
ioUnits[0] = ta;
|
||||
ioUnits[1] = tb;
|
||||
ioUnits[2] = bcs;
|
||||
// ioUnits[0] = ta;
|
||||
// ioUnits[1] = tb;
|
||||
ioUnits[actIO++] = bcs;
|
||||
|
||||
USART usart0 = new USART(this, memory, 0x70);
|
||||
USART usart1 = new USART(this, memory, 0x78);
|
||||
|
||||
ioUnits[3] = usart0;
|
||||
ioUnits[4] = usart1;
|
||||
ioUnits[actIO++] = usart0;
|
||||
ioUnits[actIO++] = usart1;
|
||||
|
||||
for (int i = 0, n = 8; i < n; i++) {
|
||||
memOut[0x70 + i] = usart0;
|
||||
|
|
@ -187,7 +189,7 @@ public class MSP430Core extends Chip implements MSP430Constants {
|
|||
}
|
||||
|
||||
ADC12 adc12 = new ADC12(this);
|
||||
ioUnits[5] = adc12;
|
||||
ioUnits[actIO++] = adc12;
|
||||
|
||||
for (int i = 0, n = 16; i < n; i++) {
|
||||
memOut[0x80 + i] = adc12;
|
||||
|
|
@ -228,6 +230,11 @@ public class MSP430Core extends Chip implements MSP430Constants {
|
|||
memOut[0x32 + i * 4] = passiveIOUnits[i + 4];
|
||||
memOut[0x33 + i * 4] = passiveIOUnits[i + 4];
|
||||
}
|
||||
passIO = 6;
|
||||
|
||||
// Add the timers
|
||||
passiveIOUnits[passIO++] = ta;
|
||||
passiveIOUnits[passIO++] = tb;
|
||||
|
||||
initIOUnit();
|
||||
}
|
||||
|
|
@ -378,30 +385,30 @@ public class MSP430Core extends Chip implements MSP430Constants {
|
|||
|
||||
private void executeEvents() {
|
||||
if (cycles >= nextVTimeEventCycles) {
|
||||
if (vTimeEventQueue.nextTime == 0) {
|
||||
nextVTimeEventCycles = cycles + 1000;
|
||||
if (vTimeEventQueue.eventCount == 0) {
|
||||
nextVTimeEventCycles = cycles + 10000;
|
||||
} else {
|
||||
TimeEvent te = vTimeEventQueue.popFirst();
|
||||
long now = getTime();
|
||||
te.execute(now);
|
||||
if (vTimeEventQueue.nextTime > 0) {
|
||||
if (vTimeEventQueue.eventCount > 0) {
|
||||
nextVTimeEventCycles = convertVTime(vTimeEventQueue.nextTime);
|
||||
} else {
|
||||
nextVTimeEventCycles = cycles + 1000;
|
||||
nextVTimeEventCycles = cycles + 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cycles >= nextCycleEventCycles) {
|
||||
if (cycleEventQueue.nextTime == 0) {
|
||||
nextCycleEventCycles = cycles + 1000;
|
||||
if (cycleEventQueue.eventCount == 0) {
|
||||
nextCycleEventCycles = cycles + 10000;
|
||||
} else {
|
||||
TimeEvent te = cycleEventQueue.popFirst();
|
||||
te.execute(cycles);
|
||||
if (cycleEventQueue.nextTime > 0) {
|
||||
nextEventCycles = cycleEventQueue.nextTime;
|
||||
if (cycleEventQueue.eventCount > 0) {
|
||||
nextCycleEventCycles = cycleEventQueue.nextTime;
|
||||
} else {
|
||||
nextCycleEventCycles = cycles + 1000;
|
||||
nextCycleEventCycles = cycles + 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -417,7 +424,7 @@ public class MSP430Core extends Chip implements MSP430Constants {
|
|||
* @param time
|
||||
*/
|
||||
public void scheduleCycleEvent(TimeEvent event, long cycles) {
|
||||
long currentNext = vTimeEventQueue.nextTime;
|
||||
long currentNext = cycleEventQueue.nextTime;
|
||||
cycleEventQueue.addEvent(event, cycles);
|
||||
if (currentNext != cycleEventQueue.nextTime) {
|
||||
nextCycleEventCycles = cycleEventQueue.nextTime;
|
||||
|
|
@ -425,7 +432,6 @@ public class MSP430Core extends Chip implements MSP430Constants {
|
|||
nextEventCycles = nextCycleEventCycles;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,13 @@ public class Timer extends IOUnit {
|
|||
private boolean interruptEnable = false;
|
||||
private boolean interruptPending = false;
|
||||
|
||||
|
||||
private TimeEvent timerTrigger = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
// System.out.println(getName() + " executing update timers at " + t);
|
||||
updateTimers(t);
|
||||
}
|
||||
};
|
||||
|
||||
private MSP430Core core;
|
||||
|
||||
private int lastTIV;
|
||||
|
|
@ -389,6 +395,7 @@ public class Timer extends IOUnit {
|
|||
}
|
||||
|
||||
updateCaptures(-1, cycles);
|
||||
|
||||
break;
|
||||
case TCCTL0:
|
||||
case TCCTL1:
|
||||
|
|
@ -448,8 +455,10 @@ public class Timer extends IOUnit {
|
|||
if (DEBUG) {
|
||||
System.out.println(getName() + " Cycles: " + cycles + " expCap[" + index + "]: " + expCaptureTime[index] + " ctr:" + counter +
|
||||
" data: " + data + " ~" +
|
||||
(100 * (cyclesMultiplicator * diff * 1L) / 2500000) / 100.0 + " sec");
|
||||
(100 * (cyclesMultiplicator * diff * 1L) / 2500000) / 100.0 + " sec" +
|
||||
"at cycles: " + expCaptureTime[index]);
|
||||
}
|
||||
calculateNextEventTime(cycles);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -459,10 +468,8 @@ public class Timer extends IOUnit {
|
|||
}
|
||||
|
||||
private void updateCaptures(int index, long cycles) {
|
||||
int low = 0;
|
||||
int hi = noCompare;
|
||||
if (index != -1) {
|
||||
low = index;
|
||||
hi = index + 1;
|
||||
}
|
||||
|
||||
|
|
@ -476,12 +483,12 @@ public class Timer extends IOUnit {
|
|||
} else if (clockSource == SRC_ACLK) {
|
||||
frqClk = core.aclkFrq / inputDivider;
|
||||
}
|
||||
|
||||
|
||||
// Handle the captures...
|
||||
if (captureOn[i]) {
|
||||
if (inputSrc[i] == SRC_ACLK) {
|
||||
divisor = core.aclkFrq;
|
||||
}
|
||||
if (inputSrc[i] == SRC_ACLK) {
|
||||
divisor = core.aclkFrq;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println(getName() + " expCapInterval[" + i + "] frq = " +
|
||||
|
|
@ -506,6 +513,7 @@ public class Timer extends IOUnit {
|
|||
}
|
||||
}
|
||||
}
|
||||
calculateNextEventTime(cycles);
|
||||
}
|
||||
|
||||
private int updateCounter(long cycles) {
|
||||
|
|
@ -539,10 +547,15 @@ public class Timer extends IOUnit {
|
|||
return counter;
|
||||
}
|
||||
|
||||
// Simplest possible - just a call each 1000 cycles (which is wrong...)
|
||||
// Simplest possible - just a call each 1000 cycles (which is wrong...)
|
||||
public long ioTick(long cycles) {
|
||||
System.out.println(getName() + " UNEXPECTED CALL TO IOTICK ****");
|
||||
return 100000 + cycles;
|
||||
}
|
||||
|
||||
if (cycles > nextTimerTrigger) {
|
||||
private void updateTimers(long cycles) {
|
||||
|
||||
if (cycles >= nextTimerTrigger) {
|
||||
interruptPending = true;
|
||||
// This should be updated whenever clockspeed changes...
|
||||
nextTimerTrigger = (long) (nextTimerTrigger + 0x10000 * cyclesMultiplicator);
|
||||
|
|
@ -551,57 +564,83 @@ public class Timer extends IOUnit {
|
|||
// This will not work very good...
|
||||
// But the timer does not need to be updated this often...
|
||||
// Do we need to update the counter here???
|
||||
// System.out.println("Checking capture register [ioTick]: " + cycles);
|
||||
// System.out.println("Checking capture register [ioTick]: " + cycles);
|
||||
for (int i = 0, n = noCompare; i < n; i++) {
|
||||
// System.out.println("Checking: " + i);
|
||||
if (expCaptureTime[i] != -1 && cycles > expCaptureTime[i]) {
|
||||
if (DEBUG) {
|
||||
System.out.println(getName() + " CAPTURE: " + i +
|
||||
" Cycles: " + cycles + " expCap: " +
|
||||
expCaptureTime[i] +
|
||||
" => ExpCR: " + Utils.hex16(expCompare[i]) +
|
||||
" TR: " + Utils.hex16(updateCounter(cycles)));
|
||||
}
|
||||
// Set the interrupt flag...
|
||||
tcctl[i] |= CC_IFG;
|
||||
if (expCaptureTime[i] != -1 && cycles >= expCaptureTime[i]) {
|
||||
if (DEBUG) {
|
||||
System.out.println(getName() + " CAPTURE: " + i +
|
||||
" Cycles: " + cycles + " expCap: " +
|
||||
expCaptureTime[i] +
|
||||
" => ExpCR: " + Utils.hex16(expCompare[i]) +
|
||||
" TR: " + Utils.hex16(updateCounter(cycles)));
|
||||
}
|
||||
// Set the interrupt flag...
|
||||
tcctl[i] |= CC_IFG;
|
||||
|
||||
if (captureOn[i]) {
|
||||
// Write the expected capture time to the register (counter could
|
||||
// differ slightly)
|
||||
tccr[i] = expCompare[i];
|
||||
// Update capture times... for next capture
|
||||
expCompare[i] = (expCompare[i] + expCapInterval[i]) & 0xffff;
|
||||
expCaptureTime[i] += expCapInterval[i] * cyclesMultiplicator;
|
||||
if (DEBUG) {
|
||||
System.out.println(getName() +
|
||||
" setting expCaptureTime to next capture: " +
|
||||
expCaptureTime[i]);
|
||||
}
|
||||
} else {
|
||||
// Update expected compare time for this compare/cap reg.
|
||||
// 0x10000 cycles... e.g. a full 16 bits wrap of the timer
|
||||
expCaptureTime[i] = expCaptureTime[i] +
|
||||
(long) (0x10000 * cyclesMultiplicator);
|
||||
if (DEBUG) {
|
||||
System.out.println(getName() +
|
||||
" setting expCaptureTime to full wrap: " +
|
||||
expCaptureTime[i]);
|
||||
}
|
||||
}
|
||||
if (captureOn[i]) {
|
||||
// Write the expected capture time to the register (counter could
|
||||
// differ slightly)
|
||||
tccr[i] = expCompare[i];
|
||||
// Update capture times... for next capture
|
||||
expCompare[i] = (expCompare[i] + expCapInterval[i]) & 0xffff;
|
||||
expCaptureTime[i] += expCapInterval[i] * cyclesMultiplicator;
|
||||
if (DEBUG) {
|
||||
System.out.println(getName() +
|
||||
" setting expCaptureTime to next capture: " +
|
||||
expCaptureTime[i]);
|
||||
}
|
||||
} else {
|
||||
// Update expected compare time for this compare/cap reg.
|
||||
// 0x10000 cycles... e.g. a full 16 bits wrap of the timer
|
||||
expCaptureTime[i] = expCaptureTime[i] +
|
||||
(long) (0x10000 * cyclesMultiplicator);
|
||||
if (DEBUG) {
|
||||
System.out.println(getName() +
|
||||
" setting expCaptureTime to full wrap: " +
|
||||
expCaptureTime[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("Wrote to: " +
|
||||
Utils.hex16(offset + TCCTL0 + i * 2 + 1));
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.println("Wrote to: " +
|
||||
Utils.hex16(offset + TCCTL0 + i * 2 + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Trigger interrupts that are up for triggering!
|
||||
triggerInterrupts();
|
||||
|
||||
return 1000 + cycles;
|
||||
calculateNextEventTime(cycles);
|
||||
}
|
||||
|
||||
|
||||
private void calculateNextEventTime(long cycles) {
|
||||
long time = nextTimerTrigger;
|
||||
// int smallest = -1;
|
||||
for (int i = 0; i < expCaptureTime.length; i++) {
|
||||
long ct = expCaptureTime[i];
|
||||
if (ct > 0 && ct < time) {
|
||||
time = ct;
|
||||
// smallest = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (time == 0) {
|
||||
time = cycles + 1000;
|
||||
}
|
||||
|
||||
if (!timerTrigger.scheduled) {
|
||||
// System.out.println(getName() + " new trigger (nothing sch) ..." + time + " re:" +
|
||||
// smallest + " => " + (smallest > 0 ? expCaptureTime[smallest] + " > " + expCompare[smallest]:
|
||||
// nextTimerTrigger) + " C:"+ cycles);
|
||||
core.scheduleCycleEvent(timerTrigger, time);
|
||||
} else if (timerTrigger.time > time) {
|
||||
// System.out.println(getName() + " new trigger (new time)..." + time + " C:"+ cycles);
|
||||
core.scheduleCycleEvent(timerTrigger, time);
|
||||
}
|
||||
}
|
||||
|
||||
// Can be called to generate any interrupt...
|
||||
public void triggerInterrupts() {
|
||||
// First check if any capture register is generating an interrupt...
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ static int caseID = 0;
|
|||
static int pos = 0;
|
||||
static unsigned int times[10];
|
||||
interrupt(TIMERB1_VECTOR) timerb1 (void) {
|
||||
if(TBIV == 2) {
|
||||
if (TBIV == 2) {
|
||||
if (pos < 10) {
|
||||
times[pos] = TBR;
|
||||
pos++;
|
||||
|
|
@ -309,7 +309,7 @@ static void testTimer() {
|
|||
}
|
||||
|
||||
for (i = 0; i < pos; i++) {
|
||||
printf("Trigg time %d => %d\n", i + 1, times[i]);
|
||||
printf("Trigg time %d => %ud\n", i + 1, times[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue