import unittest import pysimulavr import subprocess import re class XPin(pysimulavr.Pin): def __init__(self, dev, name, pinname, state = None): pysimulavr.Pin.__init__(self) self.name = name if state is not None: self.SetPin(state) # hold the connecting net here, it have not be destroyed, if we leave this method self.__net = pysimulavr.Net() self.__net.Add(self) self.__net.Add(dev.GetPin(pinname)) def SetInState(self, pin): pysimulavr.Pin.SetInState(self, pin) if pin.toChar() != self.toChar(): # print "%s='%s'" % (self.name, pin.toChar()) self.SetPin(pin.toChar()) class SingleDeviceTestCase(unittest.TestCase): def setUp(self): self.__sc = pysimulavr.SystemClock.Instance() self.__sc.ResetClock() self.device = pysimulavr.AvrFactory.instance().makeDevice(self.MCU) self.device.Load(self.PROGRAM) self.device.SetClockFreq(self.CLOCK_SETTING) self.__sc.Add(self.device) self.messages = [] self.breakpoint_callbacks = {} def tearDown(self): del self.device def setPin(self, pin, state): self.pins[pin].SetPin(state) def getPin(self, pin): return self.pins[pin].toChar() def showPin(self, pin): p = self.pins[pin] self.message('%s = %s' % (p.name, p.toChar())) def getCurrentTime(self): return self.__sc.GetCurrentTime() / 1000000.0 def read_uint8(self, symbol): addr = self.device.data.GetAddressAtSymbol(symbol) return self.device.getRWMem(addr) def message(self, m): # This could be improved... if len(self.messages) == 0: print '\n\t' + str(m) else: print '\t' + str(m) self.messages.append(m) def add_breakpoint_callback(self, key, callback): addr = self.breakpoint_adresses[key] self.breakpoint_callbacks.setdefault(addr, []).append((callback, key)) def generic_breakpoint_callback(self, key): self.message('Breakpoint %s reached, time = %s' % (key, self.getCurrentTime())) return 0 # Don't stop def runSteps(self, steps): last_pc = 0 # Needed to avoid double-callbacks for multi-step instructions for i in range(steps): self.assertEqual(self.__sc.Step(), 0) if self.device.PC in self.breakpoint_callbacks and self.device.PC != last_pc: for callback, key in self.breakpoint_callbacks[self.device.PC]: if callback(key): return i last_pc = self.device.PC def read_until_prompt(file, prompt='(gdb)'): lines = [] while 1: line = file.readline(len(prompt)) if line == prompt: return lines line += file.readline() lines.append(line) def ignore_until_prompt(file, prompt='(gdb)'): lines = read_until_prompt(file, prompt) #~ print '-'*10 + ' ignoring' #~ print ''.join(lines) breakpoint_marker = re.compile(r'/\* *Breakpoint (?P.*)\*/') breakpoint_adress_output = re.compile(r'Breakpoint \d+ at 0x(?P[0-9a-fA-F]+):.*') def get_breakpoint_adresses(debug_directory, program, sourcefiles): source_positions = {} breakpoint_adresses = {} # Search for lines with a match for the regex breakpoint_marker. # Store filenames and linenumbers in source_positions. for filename in sourcefiles: for i, line in enumerate(open(debug_directory+filename, 'r')): m = breakpoint_marker.search(line) if m: source_positions[m.group('key').strip()] = '%s:%s' % (filename, i+1) # Call avr-gdb to get the adresses where avr-gdb sets breakpoints # when you set breakpoints at the source lines. # In breakpoint_adresses, store these addreses under the the key from the breakpoint_marker. p = subprocess.Popen(['avr-gdb'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) ignore_until_prompt(p.stdout) # start message p.stdin.write('file ' + debug_directory + program + '\n') ignore_until_prompt(p.stdout) # load message for key, source_position in source_positions.items(): p.stdin.write('break ' + source_position + '\n') result = ''.join(read_until_prompt(p.stdout)).strip() m = breakpoint_adress_output.match(result) if m: # The adress is divided by two because flash is adressed in 16 bit words # (see datasheet, In-System Reprogrammable Flash Program Memory) breakpoint_adresses[key] = int(m.group('bp_addr'), 16)/2 else: print "couldn't match '%s'" % result p.stdin.write('quit\n') unconsumed = p.stdout.read() #~ if unconsumed.strip(): #~ print '-'*10 + ' ignoring' #~ print unconsumed return breakpoint_adresses if __name__ == "__main__": pass