oops. here's the new code. old code will remain in jtagarm7tdmi.c for the time...
[goodfet] / firmware / apps / jtag / jtagarm7.c
1 /*! \file jtagarm7tdmi.c
2   \brief ARM7TDMI JTAG (AT91R40008, AT91SAM7xxx)
3 */
4
5 #include "platform.h"
6 #include "command.h"
7 #include "jtag.h"
8 #include "jtagarm7tdmi.h"
9
10
11 /**** 20-pin Connection Information (pin1 is on top-right for both connectors)****
12 GoodFET  ->  7TDMI 20-pin connector (HE-10 connector)
13   1               13 (TDO)
14   2               1  (Vdd)
15   3               5  (TDI)
16   5               7  (TMS)
17   7               9  (TCK)
18   8               15 (nRST)
19   9               4,6,8,10,12,14,16,18,20 (GND)
20   11              17/3 (nTRST)  (different sources suggest 17 or 3 alternately)
21 ********************************/
22
23 /**** 14-pin Connection Information (pin1 is on top-right for both connectors)****
24 GoodFET  ->  7TDMI 14-pin connector
25   1               11 (TDO)
26   2               1  (Vdd)
27   3               5  (TDI)
28   5               7  (TMS)
29   7               9  (TCK)
30   8               12 (nRST)
31   9               2,4,6,8,10,14 (GND)
32   11              3 (nTRST)
33
34 http://hri.sourceforge.net/tools/jtag_faq_org.html
35 ********************************/
36
37
38 // ! Start JTAG, setup pins, reset TAP and return IDCODE
39 void jtagarm7tdmi_start() {
40   jtagsetup();
41   jtag_resettap();
42 }
43
44
45 //! Reset TAP State Machine       
46
47
48 /*  WHAT SHOULD THIS MODULE DO?
49  *     *start
50  *     *shift_ir
51  *     *shift_dr
52  *      reset_tap
53  *     *scanchain0
54  *     *scanchain1 (instr_primitive)
55  *     *scanchain2 (hmmmm... perhaps we'll need to keep the debug calls)
56  *     *    eice_read
57  *     *    eice_write
58  *     *get_register
59  *     *set_register
60  */
61
62 u32 shift_ir(u32 ir){
63   u32 retval;
64   jtag_goto_shift_ir();
65   retval = jtagtransn(ir, 4, LSB); 
66   return retval;
67 }
68
69 //!  Connect the appropriate scan chain to TDO/TDI.  SCAN_N, INTEST
70 unsigned long jtagarm7tdmi_scan(u8 chain, u8 testmode) {               // PROVEN
71 /*
72 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
73 wise, when in debug state, the core will not be correctly isolated and intrusive
74 commands occur. Therefore, it is recommended to pass directly from the “Update”
75 state” to the “Select DR” state each time the “Update” state is reached.
76 */
77   unsigned long retval;
78   jtag_goto_shift_ir();
79   jtagtransn(ARM7TDMI_IR_SCAN_N, 4, LSB | NORETIDLE);
80   jtag_goto_shift_dr();
81   retval = jtagtransn(chain, 4, LSB | NORETIDLE);
82   jtag_goto_shift_ir();
83   jtagtransn(testmode, 4, LSB); 
84   return(retval);
85 }
86
87
88 /************************* EmbeddedICE Primitives ****************************/
89 //! shifter for writing to chain2 (EmbeddedICE). 
90 unsigned long eice_write(unsigned char reg, unsigned long data){
91   unsigned long retval, temp;
92   jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
93   jtag_goto_shift_dr();
94   retval = jtagtransn(data, 32, LSB| NOEND| NORETIDLE);         // send in the data - 32-bits lsb
95   temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE);             // send in the register address - 5 bits lsb
96   jtagtransn(1, 1, LSB);                                        // send in the WRITE bit
97   return(retval); 
98 }
99
100 //! shifter for reading from chain2 (EmbeddedICE).
101 unsigned long eice_read(unsigned char reg){               // PROVEN
102   unsigned long temp, retval;
103   jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
104   jtag_goto_shift_dr();                                         // send in the register address - 5 bits LSB
105   temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE);
106   jtagtransn(0L, 1, LSB);                                       // clear TDI to select "read only"
107   jtag_goto_shift_dr();                                         // Now shift out the 32 bits
108   retval = jtagtransn(0L, 32, LSB);                             // atmel arm jtag docs pp.10-11: LSB first
109   return(retval);
110   
111 }
112
113 //! push an instruction into the pipeline
114 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){  // PROVEN
115   unsigned long retval;
116   jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
117
118   jtag_goto_shift_dr();
119   // if the next instruction is to run using MCLK (master clock), set TDI
120   if (breakpt)
121     {
122     SETMOSI;
123     count_sysspd_instr_since_debug++;
124     } 
125   else
126     {
127     CLRMOSI; 
128     count_dbgspd_instr_since_debug++;
129     }
130   jtag_tcktock();
131   
132   // Now shift in the 32 bits
133   retval = jtagtransn(instr, 32, 0);    // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
134   return(retval);
135 }
136
137 u32 jtagarm7tdmi_nop(u8 brkpt){
138     return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
139 }
140
141 /******************** Complex Commands **************************/
142
143 //! Retrieve a 32-bit Register value
144 unsigned long jtagarm7tdmi_get_register(unsigned long reg) {                    //PROVEN
145   unsigned long retval=0L, instr;
146   if (eice_read(EICE_DBGSTATUS)& JTAG_ARM7TDMI_DBG_TBIT)
147     instr = THUMB_INSTR_STR_R0_r0 | reg | (reg<<16);
148   else
149     instr = (unsigned long)(reg<<12L) | (unsigned long)ARM_READ_REG;   // STR Rx, [R14] 
150
151   jtagarm7tdmi_nop( 0);
152   jtagarm7tdmi_nop( 0);
153   jtagarm7tdmi_instr_primitive(instr, 0);
154   jtagarm7tdmi_nop( 0);
155   jtagarm7tdmi_nop( 0);
156   jtagarm7tdmi_nop( 0);
157   retval = jtagarm7tdmi_nop( 0);                        // recover 32-bit word
158   return retval;
159 }
160
161 //! Set a 32-bit Register value
162 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) {          // PROVEN (assuming target reg is word aligned)
163   unsigned long instr;
164   //if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
165     //instr = THUMB_WRITE_REG
166     instr = (unsigned long)(((unsigned long)reg<<12L) | ARM_WRITE_REG); //  LDR Rx, [R14]
167   
168   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
169   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
170   jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
171   if (reg == ARM_REG_PC){
172     jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
173     jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
174     jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
175   } else {
176     jtagarm7tdmi_nop( 0);            // push nop into pipeline - decode
177     jtagarm7tdmi_nop( 0);            // push nop into pipeline - execute
178     jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
179   }
180   jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
181   jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
182   jtagarm7tdmi_nop( 0);
183 }
184
185
186 ///////////////////////////////////////////////////////////////////////////////////////////////////
187 //! Handles ARM7TDMI JTAG commands.  Forwards others to JTAG.
188 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
189   unsigned int val;
190  
191   switch(verb){
192   case START:
193     //Enter JTAG mode.
194     jtagarm7tdmi_start();
195     txdata(app,verb,0);
196     break;
197   case JTAG_IR_SHIFT:
198     jtag_goto_shift_ir();
199     cmddataword[0] = jtagtransn(cmddata[0], 4, cmddata[1]);
200     txdata(app,verb,2);
201     break;
202   case JTAG_DR_SHIFT:
203         jtag_resettap();
204     jtag_goto_shift_dr();
205     cmddatalong[0] = jtagtransn(cmddatalong[1],cmddata[0],cmddata[1]);
206     txdata(app,verb,4);
207     break;
208   case JTAGARM7_CHAIN0:
209     jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
210     jtag_goto_shift_dr();
211     debughex32(cmddatalong[0]);
212     debughex(cmddataword[4]);
213     debughex32(cmddatalong[1]);
214     debughex32(cmddatalong[3]);
215     cmddatalong[0] = jtagtransn(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
216     cmddatalong[2] = jtagtransn(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
217     cmddatalong[1] = jtagtransn(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
218     cmddatalong[3] = jtagtransn(cmddatalong[3], 32, MSB);
219     txdata(app,verb,16);
220     break;
221   case JTAGARM7_SCANCHAIN1:
222   case JTAGARM7_DEBUG_INSTR:
223     cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
224     txdata(app,verb,8);
225     break;
226   case JTAGARM7_EICE_READ:
227     cmddatalong[0] = eice_read(cmddata[0]);
228     txdata(app,verb,0x4);
229     break;
230   case JTAGARM7_EICE_WRITE:
231     eice_write(cmddata[4], cmddatalong[0]);
232     txdata(app,verb,0);
233     break;
234   case JTAGARM7_GET_REGISTER:
235     val = cmddata[0];
236     cmddatalong[0] = jtagarm7tdmi_get_register(val);
237     txdata(app,verb,4);
238     break;
239   case JTAGARM7_SET_REGISTER:
240     jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
241     txdata(app,verb,4);
242     break;
243
244
245   //case JTAGARM7_STEP_INSTR:
246 /*  case JTAGARM7_READ_CODE_MEMORY:
247   case JTAGARM7_WRITE_FLASH_PAGE:
248   case JTAGARM7_READ_FLASH_PAGE:
249   case JTAGARM7_MASS_ERASE_FLASH:
250   case JTAGARM7_PROGRAM_FLASH:
251   case JTAGARM7_LOCKCHIP:
252   case JTAGARM7_CHIP_ERASE:
253   */
254   default:
255     jtaghandle(app,verb,len);
256   }
257 }
258
259