2 # GoodFET SPI Flash Client
4 # (C) 2012 Travis Goodspeed <travis at radiantmachines.com>
8 # 1) getting hot reads on frequency
9 # 2) allow sniffing in "normal" mode to get ack bits
10 # --check if that's whats causing error flags in board-to-board transmission
17 import csv, time, argparse;
20 from GoodFETMCPCAN import GoodFETMCPCAN;
21 from intelhex import IntelHex;
23 class GoodFETMCPCANCommunication:
26 self.client=GoodFETMCPCAN();
28 self.client.MCPsetup();
30 # create a filename with today's date
31 now = datetime.datetime.now()
32 self.filename = "../../contrib/ThayerData/"
33 self.filename += now.strftime("%Y%m%d")
35 ##########################
37 ##########################
39 # Prints MCP state info
42 print "MCP2515 Info:\n\n";
44 print "Mode: %s" % self.client.MCPcanstatstr();
45 print "Read Status: %02x" % self.client.MCPreadstatus();
46 print "Rx Status: %02x" % self.client.MCPrxstatus();
47 print "Tx Errors: %3d" % self.client.peek8(0x1c);
48 print "Rx Errors: %3d\n" % self.client.peek8(0x1d);
51 print "CNF1: %02x" %self.client.peek8(0x2a);
52 print "CNF2: %02x" %self.client.peek8(0x29);
53 print "CNF3: %02x\n" %self.client.peek8(0x28);
54 print "RXB0 CTRL: %02x" %self.client.peek8(0x60);
55 print "RXB1 CTRL: %02x" %self.client.peek8(0x70);
57 packet0=self.client.readrxbuffer(0);
58 packet1=self.client.readrxbuffer(1);
59 for foo in [packet0, packet1]:
60 print self.client.packet2str(foo);
63 self.client.MCPsetup();
65 def sniff(self,freq,duration,description, verbose=True, comment=None, filename=None,):
67 filename=self.filename
68 self.client.MCPsetrate(freq);
69 outfile = open(filename,'a');
70 dataWriter = csv.writer(outfile,delimiter=',');
71 dataWriter.writerow(['# Time Error Bytes 1-13']);
72 dataWriter.writerow(['#' + description])
74 self.client.MCPreqstatListenOnly();
77 starttime = time.time();
79 while((time.time()-starttime < duration)):
80 packet=self.client.rxpacket();
83 print self.client.packet2str(packet)
86 row.append("%f"%time.time());
87 if (self.client.peek8(0x2C) & 0x80):
88 self.client.MCPbitmodify(0x2C,0x80,0x00);
89 print "ERROR: Malformed packet recieved: " + self.client.packet2str(packet);
97 row.append("%02x"%ord(byte));
98 dataWriter.writerow(row);
101 print "Listened for %x seconds, captured %x packets." %(duration,packetcount);
105 def sniffTest(self, freq):
106 self.client.MCPsetup();
110 print "Calling MCPsetrate for %i." %rate;
111 self.client.MCPsetrate(rate);
112 self.client.MCPreqstatNormal();
114 print "Mode: %s" % self.client.MCPcanstatstr();
115 print "CNF1: %02x" %self.client.peek8(0x2a);
116 print "CNF2: %02x" %self.client.peek8(0x29);
117 print "CNF3: %02x\n" %self.client.peek8(0x28);
120 packet=self.client.rxpacket();
123 if (self.client.peek8(0x2C) & 0x80):
124 self.client.MCPbitmodify(0x2C,0x80,0x00);
125 print "malformed packet recieved: "+ self.client.packet2str(packet);
127 print "properly formatted packet recieved" + self.client.packet2str(packet);
130 def freqtest(self,freq):
131 self.client.MCPsetup();
133 self.client.MCPsetrate(freq);
134 self.client.MCPreqstatListenOnly();
136 print "CAN Freq Test: %3d kHz" %freq;
141 starttime = time.time();
142 while((time.time()-starttime < args.time)):
143 packet=self.client.rxpacket();
147 if (self.client.peek8(0x2C) & 0x80):
148 print "malformed packet recieved"
150 self.client.MCPbitmodify(0x2C,0x80,0x00);
152 print self.client.packet2str(packet);
154 print "Results for %3.1d kHz: recieved %3d packets, registered %3d RX errors." %(freq, x, errors);
157 def isniff(self,freq):
158 """ An intelligent sniffer, decodes message format """
159 """ More features to be added soon """
161 self.client.MCPsetrate(freq);
162 self.client.MCPreqstatListenOnly();
164 packet=self.client.rxpacket();
173 print "\nArbID: " + self.client.packet2str(arbid);
174 print "EID: " + self.client.packet2str(eid);
175 print "DLC: " + self.client.packet2str(dlc);
176 print "Data: " + self.client.packet2str(data);
179 print "\nMCP2515 Self Test:";
181 #Switch to config mode and try to rewrite TEC.
182 self.client.MCPreqstatConfiguration();
183 self.client.poke8(0x00,0xde);
184 if self.client.peek8(0x00)!=0xde:
185 print "ERROR: Poke to TEC failed.";
187 print "SUCCESS: Register read/write.";
189 #Switch to Loopback mode and try to catch our own packet.
190 self.client.MCPreqstatLoopback();
193 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID
195 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME
196 # LOWER nibble is DLC
197 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF]
198 self.client.txpacket(packet1);
199 self.client.txpacket(packet1);
200 print "Waiting on loopback packets.";
203 packet=self.client.rxpacket();
205 print "Message recieved: %s" % self.client.packet2str(packet);
210 self.client.MCPsetrate(freq);
211 self.client.MCPreqstatNormal();
213 print "Tx Errors: %3d" % self.client.peek8(0x1c);
214 print "Rx Errors: %3d" % self.client.peek8(0x1d);
215 print "Error Flags: %02x\n" % self.client.peek8(0x2d);
216 print "TXB0CTRL: %02x" %self.client.peek8(0x30);
217 print "CANINTF: %02x" %self.client.peek8(0x2C);
221 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID
223 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME
224 # LOWER nibble is DLC
225 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF]
227 self.client.txpacket(packet);
229 if(self.client.peek8(0x2C)&0x80)==0x80:
230 print "Error flag raised on transmission. Clearing this flag and proceeding.\n"
231 print "INT Flags: %02x" % self.client.peek8(0x2c);
232 self.client.MCPbitmodify(0x2C,0x80,0x00);
233 print "INT Flags modified to: %02x\n" % self.client.peek8(0x2c);
234 print "TXB0CTRL: %02x" %self.client.peek8(0x30);
235 self.client.MCPbitmodify(0x30,0x08,0x00);
236 print "TXB0CTRL modified to: %02x\n" %self.client.peek8(0x30);
238 print "message sending attempted.";
239 print "Tx Errors: %02x" % self.client.peek8(0x1c);
240 print "Rx Errors: %02x" % self.client.peek8(0x1d);
241 print "Error Flags: %02x" % self.client.peek8(0x2d);
245 if __name__ == "__main__":
247 parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description='''\
249 Run commands on the MCP2515. Valid commands are:
253 peek 0x(start) [0x(stop)]
263 parser.add_argument('verb', choices=['info', 'test','peek', 'reset', 'sniff', 'freqtest','snifftest', 'spit']);
264 parser.add_argument('-f', '--freq', type=int, default=500, help='The desired frequency (kHz)', choices=[100, 125, 250, 500, 1000]);
265 parser.add_argument('-t','--time', type=int, default=15, help='The duration to run the command (s)');
266 parser.add_argument('-o', '--output', default=None, elp='Output file');
267 parser.add_argument("-d", "--description", help='Description of experiment (included in the output file)', default="");
268 parser.add_argument('-v',"--verbose",action='store_false',help='-v will stop packet output to terminal', default=True);
269 parser.add_argument('-c','--comment', help='Comment attached to ech packet uploaded',default=None);
271 args = parser.parse_args();
274 filename = args.output
275 description = args.description
276 verbose = args.verbose
277 comments = args.comment
279 comm = GoodFETMCPCANCommunication();
281 ##########################
283 ##########################
285 # Prints MCP state info
287 if(args.verb=="info"):
291 ##########################
293 ##########################
297 if(args.verb=="reset"):
300 ##########################
302 ##########################
304 # runs in ListenOnly mode
305 # utility function to pull info off the car's CAN bus
308 if(args.verb=="sniff"):
309 comm.sniff(freq=freq,duration=duration,description=description,verbose=verbose,comment=comments,filename=filename)
313 ##########################
315 ##########################
317 # runs in NORMAL mode
318 # intended for NETWORKED MCP chips to verify proper operation
321 if(args.verb=="snifftest"):
322 comm.sniffTest(freq=freq)
324 ##########################
326 ##########################
328 # runs in LISTEN ONLY mode
329 # tests bus for desired frequency --> sniffs bus for specified length of time and reports
330 # if packets were properly formatted
334 if(args.verb=="freqtest"):
335 comm.freqtest(freq=freq)
337 ##########################
339 ##########################
341 # """ An intelligent sniffer, decodes message format """
342 # """ More features to be added soon """
343 if(args.verb=="isniff"):
344 comm.isniff(freq=freq)
347 ##########################
349 ##########################
351 # Runs in LOOPBACK mode
352 # self-check diagnostic
353 # wasn't working before due to improperly formatted packet
355 # ...add automatic packet check rather than making user verify successful packet
356 if(args.verb=="test"):
360 if(args.verb=="peek"):
363 start=int(sys.argv[2],16);
366 stop=int(sys.argv[3],16);
367 print "Peeking from %04x to %04x." % (start,stop);
369 print "%04x: %02x" % (start,client.peek8(start));
372 ##########################
374 ##########################
376 # Basic packet transmission
377 # runs in NORMAL MODE!
379 # checking TX error flags--> currently throwing error flags on every
380 # transmission (travis thinks this is because we're sniffing in listen-only
381 # and thus not generating an ack bit on the recieving board)
382 if(args.verb=="spit"):