a4d07c23d58c8c7deb3c1ff4ecd984d22fcd25d5
[goodfet] / client / GoodFET.py
1 #!/usr/bin/env python
2 # GoodFET Client Library
3
4 # (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
5 #
6 # This code is ugly as sin, for bootstrapping the firmware only.
7 # Rewrite cleanly as soon as is convenient.
8
9 import sys, time, string, cStringIO, struct
10 sys.path.append("/usr/lib/tinyos")
11 import serial
12
13
14 class GoodFET:
15     def __init__(self, *args, **kargs):
16         self.data=[0];
17     def timeout(self):
18         print "timout\n";
19     def serInit(self, port):
20         """Open the serial port"""
21         self.serialport = serial.Serial(
22             port,
23             9600,
24             parity = serial.PARITY_NONE
25             )
26         #Drop DTR, which is !RST, low to begin the app.
27         self.serialport.setDTR(0);
28         self.serialport.flushInput()
29         self.serialport.flushOutput()
30         
31         #Read and handle the initial command.
32         time.sleep(1);
33         self.readcmd(); #Read the first command.
34         if(self.verb!=0x7F):
35             print "Verb is wrong.  Incorrect firmware?";
36         
37     def writecmd(self, app, verb, count, data):
38         """Write a command and some data to the GoodFET."""
39         self.serialport.write(chr(app));
40         self.serialport.write(chr(verb));
41         self.serialport.write(chr(count));
42         #print "count=%02x, len(data)=%04x" % (count,len(data));
43         if count!=0:
44             for d in data:
45                 self.serialport.write(chr(d));
46         self.readcmd();  #Uncomment this later, to ensure a response.
47     def readcmd(self):
48         """Read a reply from the GoodFET."""
49         self.app=ord(self.serialport.read(1));
50         self.verb=ord(self.serialport.read(1));
51         self.count=ord(self.serialport.read(1));
52         if self.count>0:
53             self.data=self.serialport.read(self.count);
54         #print "READ %02x %02x %02x " % (self.app, self.verb, self.count);
55         
56     #Monitor stuff
57     def peekbyte(self,address):
58         """Read a byte of memory from the monitor."""
59         self.data=[address&0xff,address>>8];
60         self.writecmd(0,0x02,2,self.data);
61         #self.readcmd();
62         return ord(self.data[0]);
63     def peekword(self,address):
64         """Read a word of memory from the monitor."""
65         return self.peekbyte(address)+(self.peekbyte(address+1)<<8);
66     def pokebyte(self,address,value):
67         """Set a byte of memory by the monitor."""
68         self.data=[address&0xff,address>>8,value];
69         self.writecmd(0,0x03,3,self.data);
70         return ord(self.data[0]);
71     def setBaud(self,baud):
72         rates=[9600, 9600, 19200, 38400];
73         self.data=[baud];
74         print "Changing baud."
75         self.serialport.write(chr(0x00));
76         self.serialport.write(chr(0x80));
77         self.serialport.write(chr(1));
78         self.serialport.write(chr(baud));
79         
80         print "Changed baud."
81         self.serialport.setBaudrate(rates[baud]);
82         return;
83     def monitortest(self):
84         """Self-test several functions through the monitor."""
85         print "Performing monitor self-test.";
86         
87         if self.peekword(0x0c00)!=0x0c04:
88             print "ERROR Fetched wrong value from 0x0c04.";
89         self.pokebyte(0x0021,0); #Drop LED
90         if self.peekbyte(0x0021)!=0:
91             print "ERROR, P1OUT not cleared.";
92         self.pokebyte(0x0021,1); #Light LED
93         
94         print "Self-test complete.";
95     
96     def spisetup(self):
97         """Moved the FET into the SPI application."""
98         self.writecmd(1,0x10,0,self.data); #SPI/SETUP
99         #self.readcmd();
100     def spitrans8(self,byte):
101         """Read and write 8 bits by SPI."""
102         self.data=[byte];
103         self.writecmd(1,0,1,self.data);    #SPI exchange
104         #self.readcmd();
105         
106         if self.app!=1 or self.verb!=0:
107             print "Error in SPI transaction; app=%02x, verb=%02x" % (self.app, self.verb);
108         return ord(self.data[0]);
109     def MSP430setup(self):
110         """Move the FET into the MSP430 JTAG application."""
111         print "Initializing MSP430.";
112         self.writecmd(0x11,0x10,0,self.data);
113     def MSP430peek(self,adr):
114         """Read the contents of memory at an address."""
115         self.data=[adr&0xff, (adr&0xff00)>>8];
116         self.writecmd(0x11,0x02,2,self.data);
117         return ord(self.data[0])+(ord(self.data[1])<<8);
118     def MSP430poke(self,adr,val):
119         """Read the contents of memory at an address."""
120         self.data=[adr&0xff, (adr&0xff00)>>8, val&0xff, (val&0xff00)>>8];
121         self.writecmd(0x11,0x03,4,self.data);
122         return;# ord(self.data[0])+(ord(self.data[1])<<8);
123     
124     def MSP430start(self):
125         """Start debugging."""
126         self.writecmd(0x11,0x20,0,self.data);
127         ident=self.MSP430ident();
128         print "Target identifies as %04x." % ident;
129         
130     def MSP430stop(self):
131         """Stop debugging."""
132         self.writecmd(0x11,0x21,0,self.data);
133     def MSP430haltcpu(self):
134         """Halt the CPU."""
135         self.writecmd(0x11,0xA0,0,self.data);
136     def MSP430releasecpu(self):
137         """Resume the CPU."""
138         self.writecmd(0x11,0xA1,0,self.data);
139
140     def MSP430shiftir8(self,ins):
141         """Shift the 8-bit Instruction Register."""
142         data=[ins];
143         self.writecmd(0x11,0x80,1,data);
144         return ord(self.data[0]);
145     def MSP430shiftdr16(self,dat):
146         """Shift the 16-bit Data Register."""
147         data=[dat&0xFF,(dat&0xFF00)>>8];
148         self.writecmd(0x11,0x81,2,data);
149         return ord(self.data[0])#+(ord(self.data[1])<<8);
150     def MSP430setinstrfetch(self):
151         """Set the instruction fetch mode."""
152         self.writecmd(0x11,0xC1,0,self.data);
153         return self.data[0];
154     def MSP430ident(self):
155         """Grab self-identification word from 0x0FF0 as big endian."""
156         i=self.MSP430peek(0x0ff0);
157         return ((i&0xFF00)>>8)+((i&0xFF)<<8)
158     def MSP430test(self):
159         """Test MSP430 JTAG.  Requires that a chip be attached."""
160         if self.MSP430ident()==0xffff:
161             print "Is anything connected?";
162         print "Testing RAM.";
163         temp=self.MSP430peek(0x0200);
164         self.MSP430poke(0x0200,0xdead);
165         if(self.MSP430peek(0x0200)!=0xdead):
166             print "Poke of 0x0200 did not set to 0xDEAD properly.";
167             return;
168         self.MSP430poke(0x0200,temp); #restore old value.
169     def MSP430flashtest(self):
170         self.MSP430masserase();
171         i=0x2500;
172         while(i<0x2600):
173             if(self.MSP430peek(i)!=0xFFFF):
174                 print "ERROR: Unerased flash at %04x."%i;
175             self.MSP430writeflash(i,0x0000);
176             i+=2;
177     def MSP430masserase(self):
178         """Erase MSP430 flash memory."""
179         self.writecmd(0x11,0xE3,0,None);
180     def MSP430writeflash(self,adr,val):
181         """Write a word of flash memory."""
182         data=[adr&0xFF,(adr&0xFF00)>>8,val&0xFF,(val&0xFF00)>>8];
183         self.writecmd(0x11,0xE1,4,data);
184         rval=ord(self.data[0])+(ord(self.data[1])<<8);
185         if(val!=rval):
186             print "FLASH WRITE ERROR AT %04x.  Found %04x, wrote %04x." % (adr,rval,val);
187             sys.exit(1);
188     def MSP430dumpbsl(self):
189         self.MSP430dumpmem(0xC00,0xfff);
190     def MSP430dumpallmem(self):
191         self.MSP430dumpmem(0x200,0xffff);
192     def MSP430dumpmem(self,begin,end):
193         i=begin;
194         while i<end:
195             print "%04x %04x" % (i, self.MSP430peek(i));
196             i+=2;
197