From: chrishoder Date: Wed, 16 Jan 2013 01:49:07 +0000 (+0000) Subject: added new mcpCAN communication file to allow for easier testing and data storage. X-Git-Url: http://git.rot13.org/?p=goodfet;a=commitdiff_plain;h=0f09afa49bb8b723a270edd816acbdcaddeb7290 added new mcpCAN communication file to allow for easier testing and data storage. git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1374 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- diff --git a/client/GoodFETMCPCANCommunication.py b/client/GoodFETMCPCANCommunication.py new file mode 100644 index 0000000..f979f62 --- /dev/null +++ b/client/GoodFETMCPCANCommunication.py @@ -0,0 +1,386 @@ +#!/usr/bin/env python +# GoodFET SPI Flash Client +# +# (C) 2012 Travis Goodspeed +# +# +# Ted's working copy +# 1) getting hot reads on frequency +# 2) allow sniffing in "normal" mode to get ack bits +# --check if that's whats causing error flags in board-to-board transmission +# +# + +import sys; +import binascii; +import array; +import csv, time, argparse; + +from GoodFETMCPCAN import GoodFETMCPCAN; +from intelhex import IntelHex; + +class GoodFETMCPCANCommunication: + + def __init__(self): + self.client=GoodFETMCPCAN(); + self.client.serInit() + self.client.MCPsetup(); + + + ########################## + # INFO + ########################## + # + # Prints MCP state info + # + def printInfo(self): + print "MCP2515 Info:\n\n"; + + print "Mode: %s" % self.client.MCPcanstatstr(); + print "Read Status: %02x" % self.client.MCPreadstatus(); + print "Rx Status: %02x" % self.client.MCPrxstatus(); + print "Tx Errors: %3d" % self.client.peek8(0x1c); + print "Rx Errors: %3d\n" % self.client.peek8(0x1d); + + print "Timing Info:"; + print "CNF1: %02x" %self.client.peek8(0x2a); + print "CNF2: %02x" %self.client.peek8(0x29); + print "CNF3: %02x\n" %self.client.peek8(0x28); + print "RXB0 CTRL: %02x" %self.client.peek8(0x60); + print "RXB1 CTRL: %02x" %self.client.peek8(0x70); + print "RX Buffers:" + packet0=self.client.readrxbuffer(0); + packet1=self.client.readrxbuffer(1); + for foo in [packet0, packet1]: + print self.client.packet2str(foo); + + def reset(self): + self.client.MCPsetup(); + + def sniff(self,freq,duration,filename,description, verbose=True, comment=None): + self.client.MCPsetrate(freq); + outfile = open(filename,'a'); + dataWriter = csv.writer(outfile,delimiter=','); + dataWriter.writerow(['# Time Error Bytes 1-13']); + dataWriter.writerow(['#' + description]) + + self.client.MCPreqstatListenOnly(); + print "Listening..."; + packetcount = 0; + starttime = time.time(); + + while((time.time()-starttime < duration)): + packet=self.client.rxpacket(); + if packet!=None: + if( verbose==True): + print self.client.packet2str(packet) + packetcount+=1; + row = []; + row.append("%f"%time.time()); + if (self.client.peek8(0x2C) & 0x80): + self.client.MCPbitmodify(0x2C,0x80,0x00); + print "ERROR: Malformed packet recieved: " + self.client.packet2str(packet); + row.append(1); + else: + row.append(0); + + #write comment + row.append(comment) + for byte in packet: + row.append("%02x"%ord(byte)); + dataWriter.writerow(row); + + outfile.close() + print "Listened for %x seconds, captured %x packets." %(duration,packetcount); + + + + def sniffTest(self, freq): + self.client.MCPsetup(); + + rate = freq; + + print "Calling MCPsetrate for %i." %rate; + self.client.MCPsetrate(rate); + self.client.MCPreqstatNormal(); + + print "Mode: %s" % self.client.MCPcanstatstr(); + print "CNF1: %02x" %self.client.peek8(0x2a); + print "CNF2: %02x" %self.client.peek8(0x29); + print "CNF3: %02x\n" %self.client.peek8(0x28); + + while(1): + packet=self.client.rxpacket(); + + if packet!=None: + if (self.client.peek8(0x2C) & 0x80): + self.client.MCPbitmodify(0x2C,0x80,0x00); + print "malformed packet recieved: "+ self.client.packet2str(packet); + else: + print "properly formatted packet recieved" + self.client.packet2str(packet); + + + def freqtest(self,freq): + self.client.MCPsetup(); + + self.client.MCPsetrate(freq); + self.client.MCPreqstatListenOnly(); + + print "CAN Freq Test: %3d kHz" %freq; + + x = 0; + errors = 0; + + starttime = time.time(); + while((time.time()-starttime < args.time)): + packet=self.client.rxpacket(); + if packet!=None: + x+=1; + + if (self.client.peek8(0x2C) & 0x80): + print "malformed packet recieved" + errors+=1; + self.client.MCPbitmodify(0x2C,0x80,0x00); + else: + print self.client.packet2str(packet); + + print "Results for %3.1d kHz: recieved %3d packets, registered %3d RX errors." %(freq, x, errors); + + + def isniff(self,freq): + """ An intelligent sniffer, decodes message format """ + """ More features to be added soon """ + + self.client.MCPsetrate(freq); + self.client.MCPreqstatListenOnly(); + while 1: + packet=self.client.rxpacket(); + if packet!=None: + plist=[]; + for byte in packet: + plist.append(byte); + arbid=plist[0:2]; + eid=plist[2:4]; + dlc=plist[4:5]; + data=plist[5:13]; + print "\nArbID: " + self.client.packet2str(arbid); + print "EID: " + self.client.packet2str(eid); + print "DLC: " + self.client.packet2str(dlc); + print "Data: " + self.client.packet2str(data); + + def test(self): + print "\nMCP2515 Self Test:"; + + #Switch to config mode and try to rewrite TEC. + self.client.MCPreqstatConfiguration(); + self.client.poke8(0x00,0xde); + if self.client.peek8(0x00)!=0xde: + print "ERROR: Poke to TEC failed."; + else: + print "SUCCESS: Register read/write."; + + #Switch to Loopback mode and try to catch our own packet. + self.client.MCPreqstatLoopback(); + + packet1 = [0x00, + 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID + 0x00, 0x00, + 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME + # LOWER nibble is DLC + 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF] + self.client.txpacket(packet1); + self.client.txpacket(packet1); + print "Waiting on loopback packets."; + packet=None; + while(1): + packet=self.client.rxpacket(); + if packet!=None: + print "Message recieved: %s" % self.client.packet2str(packet); + break; + + + def spit(self,freq): + self.client.MCPsetrate(freq); + self.client.MCPreqstatNormal(); + + print "Tx Errors: %3d" % self.client.peek8(0x1c); + print "Rx Errors: %3d" % self.client.peek8(0x1d); + print "Error Flags: %02x\n" % self.client.peek8(0x2d); + print "TXB0CTRL: %02x" %self.client.peek8(0x30); + print "CANINTF: %02x" %self.client.peek8(0x2C); + + + packet = [0x00, + 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID + 0x00, 0x00, + 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME + # LOWER nibble is DLC + 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF] + + self.client.txpacket(packet); + + if(self.client.peek8(0x2C)&0x80)==0x80: + print "Error flag raised on transmission. Clearing this flag and proceeding.\n" + print "INT Flags: %02x" % self.client.peek8(0x2c); + self.client.MCPbitmodify(0x2C,0x80,0x00); + print "INT Flags modified to: %02x\n" % self.client.peek8(0x2c); + print "TXB0CTRL: %02x" %self.client.peek8(0x30); + self.client.MCPbitmodify(0x30,0x08,0x00); + print "TXB0CTRL modified to: %02x\n" %self.client.peek8(0x30); + + print "message sending attempted."; + print "Tx Errors: %02x" % self.client.peek8(0x1c); + print "Rx Errors: %02x" % self.client.peek8(0x1d); + print "Error Flags: %02x" % self.client.peek8(0x2d); + + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description='''\ + + Run commands on the MCP2515. Valid commands are: + + info + test + peek 0x(start) [0x(stop)] + reset + + sniff + freqtest + snifftest + spit + ''') + + + parser.add_argument('verb', choices=['info', 'test','peek', 'reset', 'sniff', 'freqtest','snifftest', 'spit']); + parser.add_argument('-f', '--freq', type=int, default=500, help='The desired frequency (kHz)', choices=[100, 125, 250, 500, 1000]); + parser.add_argument('-t','--time', type=int, default=15, help='The duration to run the command (s)'); + parser.add_argument('-o', '--output', default="../../contrib/ted/sniff_out.csv",help='Output file'); + parser.add_argument("-d", "--description", help='Description of experiment (included in the output file)', default=""); + parser.add_argument('-v',"--verbose",action='store_false',help='-v will stop packet output to terminal', default=True); + parser.add_argument('-c','--comment', help='Comment attached to ech packet uploaded',default=None); + + args = parser.parse_args(); + freq = args.freq + duration = args.time + filename = args.output + description = args.description + verbose = args.verbose + comments = args.comment + + comm = GoodFETMCPCANCommunication(); + + ########################## + # INFO + ########################## + # + # Prints MCP state info + # + if(args.verb=="info"): + comm.printInfo() + + + ########################## + # RESET + ########################## + # + # + + if(args.verb=="reset"): + comm.reset() + + ########################## + # SNIFF + ########################## + # + # runs in ListenOnly mode + # utility function to pull info off the car's CAN bus + # + + if(args.verb=="sniff"): + comm.sniff(freq=freq,duration=duration,filename=filename,description=description,verbose=verbose,comment=comments) + + + + ########################## + # SNIFF TEST + ########################## + # + # runs in NORMAL mode + # intended for NETWORKED MCP chips to verify proper operation + # + + if(args.verb=="snifftest"): + comm.sniffTest(freq=freq) + + ########################## + # FREQ TEST + ########################## + # + # runs in LISTEN ONLY mode + # tests bus for desired frequency --> sniffs bus for specified length of time and reports + # if packets were properly formatted + # + # + + if(args.verb=="freqtest"): + comm.freqtest(freq=freq) + + ########################## + # iSniff + ########################## + # + # """ An intelligent sniffer, decodes message format """ + # """ More features to be added soon """ + if(args.verb=="isniff"): + comm.isniff(freq=freq) + + + ########################## + # MCP TEST + ########################## + # + # Runs in LOOPBACK mode + # self-check diagnostic + # wasn't working before due to improperly formatted packet + # + # ...add automatic packet check rather than making user verify successful packet + if(args.verb=="test"): + comm.test() + + + if(args.verb=="peek"): + start=0x0000; + if(len(sys.argv)>2): + start=int(sys.argv[2],16); + stop=start; + if(len(sys.argv)>3): + stop=int(sys.argv[3],16); + print "Peeking from %04x to %04x." % (start,stop); + while start<=stop: + print "%04x: %02x" % (start,client.peek8(start)); + start=start+1; + + ########################## + # SPIT + ########################## + # + # Basic packet transmission + # runs in NORMAL MODE! + # + # checking TX error flags--> currently throwing error flags on every + # transmission (travis thinks this is because we're sniffing in listen-only + # and thus not generating an ack bit on the recieving board) + if(args.verb=="spit"): + comm.spit(freq=freq) + + + + + + + + + + diff --git a/client/goodfet.mcpcan b/client/goodfet.mcpcan index 0c0779c..a5aa968 100755 --- a/client/goodfet.mcpcan +++ b/client/goodfet.mcpcan @@ -21,6 +21,8 @@ if(len(sys.argv)==1): print "\n%s sniff [kHz]" % sys.argv[0]; print "\n%s isniff [kHz]" % sys.argv[0]; + print "\n%s spit [kHz]" % sys.argv[0]; + print "\nSupported rates: 83.3, 100, 125, 250, 500, 1000 kHz."; sys.exit(); @@ -41,7 +43,14 @@ if(sys.argv[1]=="info"): print "Read Status: %02x" % client.MCPreadstatus(); print "Rx Status: %02x" % client.MCPrxstatus(); print "Tx Errors: %3d" % client.peek8(0x1c); - print "Rx Errors: %3d" % client.peek8(0x1d); + print "Rx Errors: %3d\n" % client.peek8(0x1d); + + print "Timing Info:"; + print "CNF1: %02x" %client.peek8(0x2a); + print "CNF2: %02x" %client.peek8(0x29); + print "CNF3: %02x\n" %client.peek8(0x28); + print "RXB0 CTRL: %02x" %client.peek8(0x60); + print "RXB1 CTRL: %02x" %client.peek8(0x70); print "RX Buffers:" packet0=client.readrxbuffer(0); packet1=client.readrxbuffer(1); @@ -51,12 +60,57 @@ if(sys.argv[1]=="info"): if(sys.argv[1]=="sniff"): if len(sys.argv)>2: rate=float(sys.argv[2]); + print "Calling MCPsetrate for %i." %rate; client.MCPsetrate(rate); client.MCPreqstatListenOnly(); - while 1: + + print "Mode: %s" % client.MCPcanstatstr(); + + print "CNF1: %02x" %client.peek8(0x2a); + print "CNF2: %02x" %client.peek8(0x29); + print "CNF3: %02x\n" %client.peek8(0x28); + + while(1): packet=client.rxpacket(); if packet!=None: print client.packet2str(packet); + + if (client.peek8(0x2C) & 0x80): + client.MCPbitmodify(0x2C,0x80,0x00); + print"...malformed packet recieved"; + +if(sys.argv[1]=="snifftest"): + + freqrange=[10.4, 41.6, 83.3, 100, 125, 250, 500, 1000]; + + for rate in freqrange: + + print "CAN Freq Test: %3d kHz" %rate; + client.MCPsetrate(rate); + #print "CNF1/2/3: %02x %02x %02x" %(client.peek8(0x2a), client.peek8(0x29),client.peek8(0x28)); + client.MCPreqstatListenOnly(); + print "Mode: %s" % client.MCPcanstatstr(); + x = 0; + errors = 0; + + for n in range(0,400): + packet=client.rxpacket(); + if packet!=None: + print client.packet2str(packet); + x+=1; + + if (client.peek8(0x2C) & 0x80): + errors+=1; + client.MCPbitmodify(0x2C,0x80,0x00); + + if x==0: + print "No packets sniffed for %3d kHz" %rate; + else: + percenterror = float(errors/x); + + print "Results for %3.1 kHz: recieved %3d packets, registered %3d RX errors, for a %3.3f percent error rate." %(rate, x, errors, percenterrors); + + client.MCPreset(); if(sys.argv[1]=="isniff"): """ An intelligent sniffer, decodes message format """ @@ -81,7 +135,7 @@ if(sys.argv[1]=="isniff"): print "Data: " + client.packet2str(data); if(sys.argv[1]=="test"): - print "MCP2515 Self Test:"; + print "\nMCP2515 Self Test:"; #Switch to config mode and try to rewrite TEC. client.MCPreqstatConfiguration(); @@ -93,14 +147,24 @@ if(sys.argv[1]=="test"): #Switch to Loopback mode and try to catch our own packet. client.MCPreqstatLoopback(); - client.txpacket([0xb1, 0x6b, 0x00, 0x65, - 0xb1, 0x6b, 0x00, 0x65 - ]); - print "Waiting on loopback packet."; + + packet1 = [0x00, + 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID + 0x00, 0x00, + 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME + # LOWER nibble is DLC + 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF] + client.txpacket(packet1); + client.txpacket(packet1); + print "Waiting on loopback packets."; packet=None; - while packet==None: + while(1): packet=client.rxpacket(); - print "Success! Got %s" % client.packet2str(packet); + if packet!=None: + print "Message recieved: %s" % client.packet2str(packet); + + + if(sys.argv[1]=="peek"): start=0x0000; if(len(sys.argv)>2): @@ -112,3 +176,41 @@ if(sys.argv[1]=="peek"): while start<=stop: print "%04x: %02x" % (start,client.peek8(start)); start=start+1; + +# AWWW YEAAAA CODIN THAT SHIT +# as written, this should + +if(sys.argv[1]=="spit"): + + if len(sys.argv)>2: + rate=float(sys.argv[2]); + print "Calling MCPsetrate for %i." %rate; + client.MCPsetrate(rate); + + client.MCPreqstatNormal(); + + packet = [0x00, + 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID + 0x00, 0x00, + 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME + # LOWER nibble is DLC + 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF] + + client.txpacket(packet); + data = client.peek8(0x30); + while (data&0x08)==0: + print "waiting..."; + data=client.peek8(0x30); + print "message successfully sent!"; + +if(sys.argv[1]=="setbitrate"): + if len(sys.argv)>2: + rate=float(sys.argv[2]); + print "Calling MCPsetrate for %i." %rate; + client.MCPsetrate(rate); + + + + + +