public boolean tick(long simTime) { if (stopNextInstruction) { stopNextInstruction = false; throw new RuntimeException("MSPSim requested simulation stop"); } /* Nodes may be added in an ongoing simulation: * Update cycle drift to current simulation time */ if (firstTick) { firstTick = false; cycleDrift += (-NR_CYCLES_PER_MSEC * simTime); } long maxSimTimeCycles = NR_CYCLES_PER_MSEC * (simTime + 1) + cycleDrift; if (maxSimTimeCycles <= cycleCounter) { return false; } // Leave control to emulated CPU cycleCounter += 1; MSP430 cpu = getCPU(); if (cpu.cycles > cycleCounter) { /* CPU already ticked too far - just wait it out */ return true; } myMoteInterfaceHandler.doActiveActionsBeforeTick(); /* Experimental program counter history */ for (int i = pcHistory.length - 1; i > 0; i--) { pcHistory[i] = pcHistory[i - 1]; } pcHistory[0] = cpu.reg[MSP430.PC]; try { cpu.step(cycleCounter); } catch (EmulationException e) { if (e.getMessage().startsWith("Bad operation")) { /* Experimental: print program counter history */ LineListener oldListener = commandListener; LineListener tmpListener = new LineListener() { public void lineRead(String line) { logger.fatal(line); } }; setCLIListener(tmpListener); logger.fatal("Bad operation detected. Program counter history:"); for (int element : pcHistory) { sendCLICommand("line " + element); } setCLIListener(oldListener); } throw (RuntimeException) new RuntimeException("Emulated exception: " + e.getMessage()).initCause(e); } /* Check if radio has pending incoming bytes */ if (myRadio != null && myRadio.hasPendingBytes()) { myRadio.tryDeliverNextByte(cpu.cycles); } if (monitorStackUsage) { int newStack = cpu.reg[MSP430.SP]; if (newStack < stackPointerLow && newStack > 0) { stackPointerLow = cpu.reg[MSP430.SP]; // Check if stack is writing in memory if (stackPointerLow < heapStartAddress) { stackOverflowObservable.signalStackOverflow(); stopNextInstruction = true; getSimulation().stopSimulation(); } } } return true; }