Network order for telosb.
[goodfet] / firmware / apps / jtag / sbw.c
1 /*! \file sbw.c
2   \author Travis Goodspeed and Mark Rages
3   \brief Spy-Bi-Wire Mod of JTAG430 and JTAG430X
4   
5   As SBW is merely a multiplexed method of handling JTAG signals, this
6   module works by replacing preprocessor definitions in the
7   traditional modules to make them SBW compatible.  Function pointers
8   would be size efficient, but so it goes.
9 */
10
11 #include "platform.h"
12 #include "command.h"
13 //#include "jtag.h"
14 #include "jtag430.h"
15
16 #define SBWREWRITE
17 #include "sbw.h"
18
19 // define the sbw app's app_t
20 app_t const sbw_app = {
21   /* app number */
22   SBW,
23   
24   /* handle fn */
25   sbw_handler_fn,
26   
27   /* name */
28   "SBW",
29   
30   /* desc */
31   "\tThe SBW app adds to the basic JTAG app\n"
32   "\tsupport for SBW'ing MSP430 devices with two wires.\n"
33 };
34
35 //! Shift 8 bits in and out.
36 unsigned char sbwtrans8(unsigned char byte){
37   unsigned int bit;
38   SAVETCLK;
39   for (bit = 0; bit < 8; bit++) {
40     /* write MOSI on trailing edge of previous clock */
41     if (byte & 0x80)
42       {SETMOSI;}
43     else
44       {CLRMOSI;}
45     byte <<= 1;
46     
47     if(bit==7)
48       SETTMS;//TMS high on last bit to exit.
49     
50     TCKTOCK;
51      /* read MISO on trailing edge */
52     byte |= READMISO;
53   }
54   RESTORETCLK;
55   
56   // update state
57   CLRTMS;
58   TCKTOCK;
59   
60   return byte;
61 }
62
63 //! Shift n bits in and out.
64 unsigned long sbwtransn(unsigned long word,
65                          unsigned int bitcount){
66   unsigned int bit;
67   //0x8000
68   unsigned long high=0x8000;
69   
70   if(bitcount==20)
71     high=0x80000;
72   if(bitcount==16)
73     high= 0x8000;
74   
75   SAVETCLK;
76   
77   for (bit = 0; bit < bitcount; bit++) {
78     /* write MOSI on trailing edge of previous clock */
79     if (word & high)
80       {SETMOSI;}
81     else
82       {CLRMOSI;}
83     word <<= 1;
84     
85     if(bit==bitcount-1)
86       SETTMS;//TMS high on last bit to exit.
87     
88     TCKTOCK;
89     /* read MISO on trailing edge */
90     word |= READMISO;
91   }
92   
93   if(bitcount==20){
94     word = ((word << 16) | (word >> 4)) & 0x000FFFFF;
95   }
96   
97   RESTORETCLK;
98   
99   // update state
100   CLRTMS;
101   TCKTOCK;
102   
103   return word;
104 }
105
106
107
108 //! Shift all bits of the DR.
109 u32 sbw_dr_shift20(unsigned long in){
110   // idle
111   SETTMS;
112   TCKTOCK;
113   // select DR
114   CLRTMS;
115   TCKTOCK;
116   // capture IR
117   TCKTOCK;
118   
119   // shift DR, then idle
120   return(sbwtransn(in,20));
121 }
122
123
124 //! Shift 16 bits of the DR.
125 u16 sbw_dr_shift16(unsigned int in){
126   // idle
127   SETTMS; // 1
128   TCKTOCK;
129   // select DR
130   CLRTMS; // 0
131   TCKTOCK;
132   // capture IR
133   TCKTOCK;
134   
135   // shift DR, then idle
136   return(sbwtransn(in,16));
137 }
138
139
140 //! Shift 8 bits of the IR.
141 u8 sbw_ir_shift8(unsigned char in){
142   // idle
143   SETTMS;
144   TCKTOCK;
145   // select DR
146   TCKTOCK;
147   // select IR
148   CLRTMS;
149   TCKTOCK;
150   // capture IR
151   TCKTOCK;
152   
153   // shift IR, then idle.
154   return(sbwtrans8(in));
155 }
156
157
158 //FIXME these should be prefixed with sbw
159 //to prevent name pollution.
160 int tms=1, tdi=1, tdo=0;
161
162 void clock_sbw() {
163   //exchange TMS
164   SETSBWIO(tms);
165   SBWCLK();
166   
167   //exchange TDI
168   SETSBWIO(tdi);
169   SBWCLK();
170   
171   //exchange TDO
172   P5DIR &= ~SBWTDIO; //input mode
173   P5OUT &= ~SBWTCK;  //Drop Metaclock
174   tdo=!!(P5IN & SBWTDIO);
175   P5OUT |= SBWTCK;   //output mode
176   P5DIR |= SBWTDIO;  //Raise Metaclock
177   
178   //TCK implied
179 }
180
181
182 void sbwSETTCLK(){
183   SETSBWIO(tms);
184   SBWCLK();
185
186   SETSBWIO(1);asm("nop");asm("nop");     
187   SETSBWIO(0);asm("nop");asm("nop");     
188   SETSBWIO(1);asm("nop");asm("nop");     
189   SETSBWIO(0);asm("nop");asm("nop");     
190   SETSBWIO(1);asm("nop");asm("nop");     
191
192   SBWCLK();
193   
194   P5DIR &= ~SBWTDIO;
195   P5OUT &= ~SBWTCK; 
196   //tdo=!!(P5IN & SBWTDIO);
197   P5OUT |= SBWTCK;
198   P5DIR |= SBWTDIO; 
199 }
200
201 void sbwCLRTCLK(){
202   SETSBWIO(tms);
203   SBWCLK();
204
205   SETSBWIO(0);asm("nop");asm("nop");     
206   SETSBWIO(1);asm("nop");asm("nop");     
207   SETSBWIO(0);asm("nop");asm("nop");     
208   SETSBWIO(1);asm("nop");asm("nop");     
209   SETSBWIO(0);asm("nop");asm("nop");     
210
211   SBWCLK();
212
213   P5DIR &= ~SBWTDIO;
214   P5OUT &= ~SBWTCK; 
215   //tdo=!!(P5IN & SBWTDIO);
216   P5OUT |= SBWTCK;
217   P5DIR |= SBWTDIO;   
218 }
219
220
221
222
223 //! Set the program counter.
224 void sbw430_setpc(unsigned int adr){
225   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
226   sbw_dr_shift16(0x3401);// release low byte
227   sbw_ir_shift8(IR_DATA_16BIT);
228   sbw_dr_shift16(0x4030);//Instruction to load PC
229   CLRTCLK;
230   SETTCLK;
231   sbw_dr_shift16(adr);// Value for PC
232   CLRTCLK;
233   sbw_ir_shift8(IR_ADDR_CAPTURE);
234   SETTCLK;
235   CLRTCLK ;// Now PC is set to "PC_Value"
236   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
237   sbw_dr_shift16(0x2401);// low byte controlled by SBW
238 }
239
240 //! Halt the CPU
241 void sbw430_haltcpu(){
242   //sbw430_setinstrfetch();
243   
244   sbw_ir_shift8(IR_DATA_16BIT);
245   sbw_dr_shift16(0x3FFF);//JMP $+0
246   
247   CLRTCLK;
248   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
249   sbw_dr_shift16(0x2409);//set SBW_HALT bit
250   SETTCLK;
251 }
252
253 //! Release the CPU
254 void sbw430_releasecpu(){
255   CLRTCLK;
256   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
257   sbw_dr_shift16(0x2401);
258   sbw_ir_shift8(IR_ADDR_CAPTURE);
259   SETTCLK;
260 }
261
262 //! Read data from address
263 unsigned int sbw430_readmem(unsigned int adr){
264   unsigned int toret;
265   sbw430_haltcpu();
266   
267   CLRTCLK;
268   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
269   
270   if(adr>0xFF)
271     sbw_dr_shift16(0x2409);//word read
272   else
273     sbw_dr_shift16(0x2419);//byte read
274   sbw_ir_shift8(IR_ADDR_16BIT);
275   sbw_dr_shift16(adr);//address
276   sbw_ir_shift8(IR_DATA_TO_ADDR);
277   SETTCLK;
278
279   CLRTCLK;
280   toret=sbw_dr_shift16(0x0000);//16 bit return
281   
282   return toret;
283 }
284
285 //! Write data to address.
286 void sbw430_writemem(unsigned int adr, unsigned int data){
287   CLRTCLK;
288   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
289   if(adr>0xFF)
290     sbw_dr_shift16(0x2408);//word write
291   else
292     sbw_dr_shift16(0x2418);//byte write
293   sbw_ir_shift8(IR_ADDR_16BIT);
294   sbw_dr_shift16(adr);
295   sbw_ir_shift8(IR_DATA_TO_ADDR);
296   sbw_dr_shift16(data);
297   SETTCLK;
298 }
299
300 //! Write data to flash memory.  Must be preconfigured.
301 void sbw430_writeflashword(unsigned int adr, unsigned int data){
302   
303   CLRTCLK;
304   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
305   sbw_dr_shift16(0x2408);//word write
306   sbw_ir_shift8(IR_ADDR_16BIT);
307   sbw_dr_shift16(adr);
308   sbw_ir_shift8(IR_DATA_TO_ADDR);
309   sbw_dr_shift16(data);
310   SETTCLK;
311   
312   //Return to read mode.
313   CLRTCLK;
314   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
315   sbw_dr_shift16(0x2409);
316   
317   /*
318   sbw430_writemem(adr,data);
319   CLRTCLK;
320   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
321   sbw_dr_shift16(0x2409);
322   */
323   
324   debugstr("ERROR: Haven't got ASM to flash-pulse SBW.");
325   
326   //Pulse TCLK
327   //sbw430_tclk_flashpulses(35); //35 standard
328 }
329
330 //! Configure flash, then write a word.
331 void sbw430_writeflash(unsigned int adr, unsigned int data){
332   sbw430_haltcpu();
333   
334   //FCTL1=0xA540, enabling flash write
335   sbw430_writemem(0x0128, 0xA540);
336   //FCTL2=0xA540, selecting MCLK as source, DIV=1
337   sbw430_writemem(0x012A, 0xA540);
338   //FCTL3=0xA500, should be 0xA540 for Info Seg A on 2xx chips.
339   sbw430_writemem(0x012C, 0xA500); //all but info flash.
340   
341   //Write the word itself.
342   sbw430_writeflashword(adr,data);
343   
344   //FCTL1=0xA500, disabling flash write
345   sbw430_writemem(0x0128, 0xA500);
346   
347   //sbw430_releasecpu();
348 }
349
350
351
352 //! Power-On Reset
353 void sbw430_por(){
354   unsigned int sbwid;
355
356   // Perform Reset
357   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
358   sbw_dr_shift16(0x2C01); // apply
359   sbw_dr_shift16(0x2401); // remove
360   CLRTCLK;
361   SETTCLK;
362   CLRTCLK;
363   SETTCLK;
364   CLRTCLK;
365   sbwid = sbw_ir_shift8(IR_ADDR_CAPTURE); // get SBW identifier
366   SETTCLK;
367   
368   sbw430_writemem(0x0120, 0x5A80);   // Diabled Watchdog
369 }
370
371
372
373 #define ERASE_GLOB 0xA50E
374 #define ERASE_ALLMAIN 0xA50C
375 #define ERASE_MASS 0xA506
376 #define ERASE_MAIN 0xA504
377 #define ERASE_SGMT 0xA502
378
379 //! Configure flash, then write a word.
380 void sbw430_eraseflash(unsigned int mode, unsigned int adr, unsigned int count){
381   sbw430_haltcpu();
382   
383   //FCTL1= erase mode
384   sbw430_writemem(0x0128, mode);
385   //FCTL2=0xA540, selecting MCLK as source, DIV=1
386   sbw430_writemem(0x012A, 0xA540);
387   //FCTL3=0xA500, should be 0xA540 for Info Seg A on 2xx chips.
388   sbw430_writemem(0x012C, 0xA500);
389   
390   //Write the erase word.
391   sbw430_writemem(adr, 0x55AA);
392   //Return to read mode.
393   CLRTCLK;
394   sbw_ir_shift8(IR_CNTRL_SIG_16BIT);
395   sbw_dr_shift16(0x2409);
396   
397   //Send the pulses.
398   debugstr("ERROR: Haven't got ASM to flash-pulse SBW.");
399   //sbw430_tclk_flashpulses(count);
400   
401   //FCTL1=0xA500, disabling flash write
402   sbw430_writemem(0x0128, 0xA500);
403   
404   //sbw430_releasecpu();
405 }
406
407
408 //! Reset the TAP state machine.
409 void sbw430_resettap(){
410   int i;
411   // Settle output
412   SETTDI; //430X2
413   SETTMS;
414   //SETTDI; //classic
415   TCKTOCK;
416
417   // Navigate to reset state.
418   // Should be at least six.
419   for(i=0;i<4;i++){
420     TCKTOCK;
421   }
422
423   // test-logic-reset
424   CLRTMS;
425   TCKTOCK;
426
427   SETTMS;
428   // idle
429
430     
431   /* sacred, by spec.
432      Sometimes this isn't necessary.  */
433   // fuse check
434   CLRTMS;
435   delay(50);
436   SETTMS;
437   CLRTMS;
438   delay(50);
439   SETTMS;
440   /**/
441   
442 }
443
444 void sbwsetup(){
445
446   /* To select the 2-wire SBW mode, the SBWTDIO line is held high and
447      the first clock is applied on SBWTCK. After this clock, the
448      normal SBW timings are applied starting with the TMS slot, and
449      the normal JTAG patterns can be applied, typically starting with
450      the Tap Reset and Fuse Check sequence.  The SBW mode is exited by
451      holding the TEST/SWBCLK low for more than 100 μs. 
452   */
453
454   // tdio up, tck low
455   //   
456   P5OUT &= ~SBWTCK;
457   P5OUT |= SBWTDIO;
458   P5DIR |= SBWTDIO|SBWTCK;
459
460   msdelay(5);
461   SBWCLK();
462
463   SBWCLK();
464
465   // now we're in SBW mode
466 }
467
468
469 //! Start SBW, take pins
470 void sbw430_start(){
471   sbwsetup();
472   
473   //Known-good starting position.
474   //Might be unnecessary.
475   SETTST;
476   SETRST;
477   delay(0xFFFF);
478   
479   sbwsetup();
480
481   //Perform a reset and disable watchdog.
482   sbw430_por();
483   sbw430_writemem(0x120,0x5a80);//disable watchdog
484   sbw430_haltcpu();
485 }
486
487 //! Start normally, not SBW.
488 void sbw430_stop(){
489   debugstr("Exiting SBW.");
490   sbwsetup();
491   
492   //Known-good starting position.
493   //Might be unnecessary.
494   //SETTST;
495   CLRTST;
496   SETRST;
497   delay(0xFFFF);
498   
499   //Entry sequence from Page 67 of SLAU265A for 4-wire MSP430 SBW
500   CLRRST;
501   delay(0xFFFF);
502   SETRST;
503   //P5DIR&=~RST;
504   //delay(0xFFFF);
505   
506 }
507
508 //! Set CPU to Instruction Fetch
509 void sbw430_setinstrfetch(){
510   
511   sbw_ir_shift8(IR_CNTRL_SIG_CAPTURE);
512
513   // Wait until instruction fetch state.
514   while(1){
515     if (sbw_dr_shift16(0x0000) & 0x0080)
516       return;
517     CLRTCLK;
518     SETTCLK;
519   }
520 }
521
522
523 //! Stop JTAG, release pins
524 void sbw_stop(){
525   P5OUT=0;
526   P4OUT=0;
527 }
528
529
530
531 //! Handles classic MSP430 SBW commands.  Forwards others to SBW.
532
533 void sbw_handler_fn(u8 app, u8 verb, u32 len){
534   unsigned long at;
535   unsigned int i, val;
536   
537   
538   /* FIXME
539    * Sometimes SBW doesn't init correctly.
540    * This restarts the connection if the masked-rom
541    * chip ID cannot be read.  Should print warning
542    * for testing server.
543    */
544   while((i=sbw430_readmem(0xff0))==0xFFFF){
545     debugstr("start");
546     sbw430_start();
547     P1OUT^=1;
548   }
549   P1OUT&=~1;
550   
551
552   //debughex(verb);
553   switch(verb){
554   case SETUP:
555     sbwsetup();
556     txdata(app,verb,0);
557     break;
558   case START:
559     //Enter SBW mode.
560     sbw430_start();
561     //TAP setup, fuse check
562     sbw430_resettap();
563     
564     cmddata[0]=sbw_ir_shift8(IR_BYPASS);    
565     //cmddata[0]=0x89; //STINT
566     txdata(app,verb,1);
567     break;
568   case STOP:
569     sbw430_stop();
570     txdata(app,verb,0);
571     break;
572   case JTAG430_HALTCPU:
573     sbw430_haltcpu();
574     txdata(app,verb,0);
575     break;
576   case JTAG430_RELEASECPU:
577     sbw430_releasecpu();
578     txdata(app,verb,0);
579     break;
580   case JTAG430_SETINSTRFETCH:
581     sbw430_setinstrfetch();
582     txdata(app,verb,0);
583     break;
584     
585   case JTAG430_READMEM:
586   case PEEK:
587     at=cmddatalong[0];
588     
589     //Fetch large blocks for bulk fetches,
590     //small blocks for individual peeks.
591     if(len>5)
592       len=(cmddataword[2]);//always even.
593     else
594       len=2;
595     len&=~1;//clear lsbit
596     
597     txhead(app,verb,len);
598     for(i=0;i<len;i+=2){
599       sbw430_resettap();
600       val=sbw430_readmem(at);
601       
602       at+=2;
603       serial_tx(val&0xFF);
604       serial_tx((val&0xFF00)>>8);
605     }
606     break;
607   case JTAG430_WRITEMEM:
608   case POKE:
609     sbw430_haltcpu();
610     sbw430_writemem(cmddataword[0],cmddataword[2]);
611     cmddataword[0]=sbw430_readmem(cmddataword[0]);
612     txdata(app,verb,2);
613     break;
614
615   case JTAG430_WRITEFLASH:
616     at=cmddataword[0];
617     
618     for(i=0;i<(len>>1)-2;i++){
619       //debugstr("Poking flash memory.");
620       sbw430_writeflash(at+(i<<1),cmddataword[i+2]);
621       //Reflash if needed.  Try this twice to save grace?
622       if(cmddataword[i]!=sbw430_readmem(at))
623         sbw430_writeflash(at+(i<<1),cmddataword[i+2]);
624     }
625     
626     //Return result of first write as a word.
627     cmddataword[0]=sbw430_readmem(cmddataword[0]);
628     
629     txdata(app,verb,2);
630     break;
631   case JTAG430_ERASEFLASH:
632     sbw430_eraseflash(ERASE_MASS,0xFFFE,0x3000);
633     txdata(app,verb,0);
634     break;
635   case JTAG430_SETPC:
636     sbw430_haltcpu();
637     sbw430_setpc(cmddataword[0]);
638     sbw430_releasecpu();
639     txdata(app,verb,0);
640     break;
641     
642   case JTAG430_COREIP_ID:
643   case JTAG430_DEVICE_ID:
644     cmddataword[0]=0;
645     cmddataword[1]=0;
646     txdata(app,verb,4);
647     break;
648     
649   default:
650     //sbwhandle(app,verb,len);
651     debugstr("ERROR, classic JTAG instruction in SBW.");
652     txdata(app,verb,4);
653   }
654   //sbw430_resettap();  //DO NOT UNCOMMENT
655 }