The GoodFET can program an MSP430's flash memory!
[goodfet] / firmware / apps / jtag / jtag430.c
1
2 #include "platform.h"
3 #include "command.h"
4 #include "jtag.h"
5
6
7 //! Set the program counter.
8 void jtag430_setpc(unsigned int adr){
9   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
10   jtag_dr_shift16(0x3401);// release low byte
11   jtag_ir_shift8(IR_DATA_16BIT);
12   jtag_dr_shift16(0x4030);//Instruction to load PC
13   CLRTCLK;
14   SETTCLK;
15   jtag_dr_shift16(adr);// Value for PC
16   CLRTCLK;
17   jtag_ir_shift8(IR_ADDR_CAPTURE);
18   SETTCLK;
19   CLRTCLK ;// Now PC is set to "PC_Value"
20   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
21   jtag_dr_shift16(0x2401);// low byte controlled by JTAG
22 }
23
24 //! Halt the CPU
25 void jtag430_haltcpu(){
26   //jtag430_setinstrfetch();
27   
28   jtag_ir_shift8(IR_DATA_16BIT);
29   jtag_dr_shift16(0x3FFF);//JMP $+0
30   
31   CLRTCLK;
32   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
33   jtag_dr_shift16(0x2409);//set JTAG_HALT bit
34   SETTCLK;
35 }
36
37 //! Release the CPU
38 void jtag430_releasecpu(){
39   CLRTCLK;
40   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
41   jtag_dr_shift16(0x2401);
42   jtag_ir_shift8(IR_ADDR_CAPTURE);
43   SETTCLK;
44 }
45
46 //! Read data from address
47 unsigned int jtag430_readmem(unsigned int adr){
48   unsigned int toret;
49   
50   CLRTCLK;
51   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
52   if(adr>0xFF)
53     jtag_dr_shift16(0x2409);//word read
54   else
55     jtag_dr_shift16(0x2419);//byte read
56   jtag_ir_shift8(IR_ADDR_16BIT);
57   jtag_dr_shift16(adr);//address
58   jtag_ir_shift8(IR_DATA_TO_ADDR);
59   SETTCLK;
60
61   CLRTCLK;
62   toret=jtag_dr_shift16(0x0000);//16 bit return
63   
64   return toret;
65 }
66
67 //! Write data to address.
68 void jtag430_writemem(unsigned int adr, unsigned int data){
69   CLRTCLK;
70   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
71   if(adr>0xFF)
72     jtag_dr_shift16(0x2408);//word write
73   else
74     jtag_dr_shift16(0x2418);//byte write
75   jtag_ir_shift8(IR_ADDR_16BIT);
76   jtag_dr_shift16(adr);
77   jtag_ir_shift8(IR_DATA_TO_ADDR);
78   jtag_dr_shift16(data);
79   SETTCLK;
80 }
81
82 //! Pulse TCLK at 350kHz +/- 100kHz
83 void jtag430_tclk_flashpulses(unsigned int i){
84   //TODO check this on a scope.
85   
86   //At 2MHz, 350kHz is obtained with 5 clocks of delay
87   
88   /** Pondering:
89       What happens if the frequency is too low or to high?
90       Is there any risk of damaging the chip, or only of a poor write?
91   */
92   while(i--){
93     SETTCLK;
94     _NOP();
95     _NOP();
96     _NOP();
97     _NOP();
98     _NOP();
99     CLRTCLK;
100   }
101 }
102
103 //! Write data to flash memory.  Must be preconfigured.
104 void jtag430_writeflashword(unsigned int adr, unsigned int data){
105   //jtag430_haltcpu();
106   /*
107   CLRTCLK;
108   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
109   jtag_dr_shift16(0x2408);//word write
110   jtag_ir_shift8(IR_ADDR_16BIT);
111   jtag_dr_shift16(adr);
112   jtag_ir_shift8(IR_DATA_TO_ADDR);
113   jtag_dr_shift16(data);
114   SETTCLK;
115   
116   //Return to read mode.
117   CLRTCLK;
118   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
119   jtag_dr_shift16(0x2409);
120   */
121   
122   jtag430_writemem(adr,data);
123   CLRTCLK;
124   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
125   jtag_dr_shift16(0x2409);
126   
127   
128   //Pulse TCLK
129   jtag430_tclk_flashpulses(35);
130   //jtag430_releasecpu();
131 }
132
133 //! Configure flash, then write a word.
134 void jtag430_writeflash(unsigned int adr, unsigned int data){
135   jtag430_haltcpu();
136   
137   //FCTL1=0xA540, enabling flash write
138   jtag430_writemem(0x0128, 0xA540);
139   //FCTL2=0xA540, selecting MCLK as source, DIV=1
140   jtag430_writemem(0x012A, 0xA540);
141   //FCTL3=0xA500, should be 0xA540 for Info Seg A on 2xx chips.
142   jtag430_writemem(0x012C, 0xA500);
143   
144   //Write the word itself.
145   jtag430_writeflashword(adr,data);
146   
147   //FCTL1=0xA500, disabling flash write
148   jtag430_writemem(0x0128, 0xA500);
149   
150   jtag430_releasecpu();
151 }
152
153
154
155 #define ERASE_GLOB 0xA50E
156 #define ERASE_ALLMAIN 0xA50C
157 #define ERASE_MASS 0xA506
158 #define ERASE_MAIN 0xA504
159 #define ERASE_SGMT 0xA502
160
161 //! Configure flash, then write a word.
162 void jtag430_eraseflash(unsigned int mode, unsigned int adr, unsigned int count){
163   //FCTL1= erase mode
164   jtag430_writemem(0x0128, mode);
165   //FCTL2=0xA540, selecting MCLK as source, DIV=1
166   jtag430_writemem(0x012A, 0xA540);
167   //FCTL3=0xA500, should be 0xA540 for Info Seg A on 2xx chips.
168   jtag430_writemem(0x012C, 0xA500);
169   
170   //Write the erase word.
171   jtag430_writemem(adr, 0x55AA);
172   //Return to read mode.
173   CLRTCLK;
174   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
175   jtag_dr_shift16(0x2409);
176   
177   //Send the pulses.
178   jtag430_tclk_flashpulses(count);
179   
180   //FCTL1=0xA500, disabling flash write
181   jtag430_writemem(0x0128, 0xA500);
182 }
183
184
185 //! Reset the TAP state machine.
186 void jtag430_resettap(){
187   int i;
188   // Settle output
189   SETTMS;
190   SETTDI;
191   SETTCK;
192
193   // Navigate to reset state.
194   // Should be at least six.
195   for(i=0;i<4;i++){
196     CLRTCK;
197     SETTCK;
198   }
199
200   // test-logic-reset
201   CLRTCK;
202   CLRTMS;
203   SETTCK;
204   SETTMS;
205   // idle
206
207     
208   /* sacred, by spec.
209      Sometimes this isn't necessary. */
210   // fuse check
211   CLRTMS;
212   delay(50);
213   SETTMS;
214   CLRTMS;
215   delay(50);
216   SETTMS;
217   /**/
218   
219 }
220
221 //! Start JTAG, take pins
222 void jtag430_start(){
223   jtagsetup();
224   
225   //Known-good starting position.
226   //Might be unnecessary.
227   SETTST;
228   SETRST;
229   delay(0xFFFF);
230   
231   //Entry sequence from Page 67 of SLAU265A for 4-wire MSP430 JTAG
232   CLRRST;
233   delay(100);
234   CLRTST;
235   delay(50);
236   SETTST;
237   delay(50);
238   SETRST;
239   P5DIR&=~RST;
240   delay(0xFFFF);
241 }
242
243 //! Set CPU to Instruction Fetch
244 void jtag430_setinstrfetch(){
245   jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
246
247   // Wait until instruction fetch state.
248   while(1){
249     if (jtag_dr_shift16(0x0000) & 0x0080)
250       return;
251     CLRTCLK;
252     SETTCLK;
253   }
254 }
255
256 //! Handles unique MSP430 JTAG commands.  Forwards others to JTAG.
257 void jtag430handle(unsigned char app,
258                    unsigned char verb,
259                    unsigned char len){
260   unsigned char i;
261   switch(verb){
262   case START:
263     //Enter JTAG mode.
264     jtag430_start();
265     //TAP setup, fuse check
266     jtag430_resettap();
267     txdata(app,verb,0);
268     break;
269   case JTAG430_HALTCPU:
270     jtag430_haltcpu();
271     txdata(app,verb,0);
272     break;
273   case JTAG430_RELEASECPU:
274     jtag430_releasecpu();
275     txdata(app,verb,0);
276     break;
277   case JTAG430_SETINSTRFETCH:
278     jtag430_setinstrfetch();
279     txdata(app,verb,0);
280     break;
281
282     
283   case JTAG430_READMEM:
284   case PEEK:
285     cmddataword[0]=jtag430_readmem(cmddataword[0]);
286     txdata(app,verb,2);
287     break;
288   case JTAG430_WRITEMEM:
289   case POKE:
290     jtag430_writemem(cmddataword[0],cmddataword[1]);
291     cmddataword[0]=jtag430_readmem(cmddataword[0]);
292     txdata(app,verb,2);
293     break;
294   case JTAG430_WRITEFLASH:
295     jtag430_writeflash(cmddataword[0],cmddataword[1]);
296     cmddataword[0]=jtag430_readmem(cmddataword[0]);
297     txdata(app,verb,2);
298     break;
299   case JTAG430_ERASEFLASH:
300     jtag430_eraseflash(ERASE_MASS,0xFFFE,0xFFFF);
301     txdata(app,verb,0);
302     break;
303   case JTAG430_SETPC:
304     jtag430_setpc(cmddataword[0]);
305     txdata(app,verb,0);
306     break;
307   default:
308     jtaghandle(app,verb,len);
309   }
310   jtag430_resettap();
311 }
312