x00t!
[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 u8 shift_ir(u8 ir, u8 flags){
63   u8 retval;
64   jtag_goto_shift_ir();
65   retval = jtagtransn(ir, 4, LSB|flags); 
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   shift_ir(ARM7TDMI_IR_SCAN_N, NORETIDLE);
79   jtag_goto_shift_dr();
80   retval = jtagtransn(chain, 4, LSB | NORETIDLE);
81   shift_ir(testmode, NORETIDLE); 
82   return(retval);
83 }
84
85
86 /************************* EmbeddedICE Primitives ****************************/
87 //! shifter for writing to chain2 (EmbeddedICE). 
88 unsigned long eice_write(unsigned char reg, unsigned long data){
89   unsigned long retval, temp;
90   jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
91   jtag_goto_shift_dr();
92   retval = jtagtransn(data, 32, LSB| NOEND| NORETIDLE);         // send in the data - 32-bits lsb
93   temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE);             // send in the register address - 5 bits lsb
94   jtagtransn(1, 1, LSB);                                        // send in the WRITE bit
95   return(retval); 
96 }
97
98 //! shifter for reading from chain2 (EmbeddedICE).
99 unsigned long eice_read(unsigned char reg){               // PROVEN
100   unsigned long temp, retval;
101   jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
102   jtag_goto_shift_dr();                                         // send in the register address - 5 bits LSB
103   temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE);
104   jtagtransn(0L, 1, LSB);                                       // clear TDI to select "read only"
105   jtag_goto_shift_dr();                                         // Now shift out the 32 bits
106   retval = jtagtransn(0L, 32, LSB);                             // atmel arm jtag docs pp.10-11: LSB first
107   return(retval);
108   
109 }
110
111 //! push an instruction into the pipeline
112 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){  // PROVEN
113   unsigned long retval;
114   jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
115
116   jtag_goto_shift_dr();
117   // if the next instruction is to run using MCLK (master clock), set TDI
118   if (breakpt)
119     {
120     SETMOSI;
121     } 
122   else
123     {
124     CLRMOSI; 
125     }
126   jtag_tcktock();
127   
128   // Now shift in the 32 bits
129   retval = jtagtransn(instr, 32, 0);    // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
130   return(retval);
131 }
132
133 u32 jtagarm7tdmi_nop(u8 brkpt){
134     return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
135 }
136
137 /******************** Complex Commands **************************/
138
139 //! Retrieve a 32-bit Register value
140 unsigned long jtagarm7tdmi_get_register(unsigned long reg) {                    //PROVEN
141   unsigned long retval=0L, instr;
142   if (eice_read(EICE_DBGSTATUS)& JTAG_ARM7TDMI_DBG_TBIT)
143     instr = THUMB_INSTR_STR_R0_r0 | reg | (reg<<16);
144   else
145     instr = (unsigned long)(reg<<12L) | (unsigned long)ARM_READ_REG;   // STR Rx, [R14] 
146
147   jtagarm7tdmi_nop( 0);
148   jtagarm7tdmi_nop( 0);
149   jtagarm7tdmi_instr_primitive(instr, 0);
150   jtagarm7tdmi_nop( 0);
151   jtagarm7tdmi_nop( 0);
152   jtagarm7tdmi_nop( 0);
153   retval = jtagarm7tdmi_nop( 0);                        // recover 32-bit word
154   return retval;
155 }
156
157 //! Set a 32-bit Register value
158 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) {          // PROVEN (assuming target reg is word aligned)
159   unsigned long instr;
160   //if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
161     //instr = THUMB_WRITE_REG
162     instr = (unsigned long)(((unsigned long)reg<<12L) | ARM_WRITE_REG); //  LDR Rx, [R14]
163   
164   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
165   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
166   jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
167   if (reg == ARM_REG_PC){
168     jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
169     jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
170     jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
171   } else {
172     jtagarm7tdmi_nop( 0);            // push nop into pipeline - decode
173     jtagarm7tdmi_nop( 0);            // push nop into pipeline - execute
174     jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
175   }
176   jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
177   jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
178   jtagarm7tdmi_nop( 0);
179 }
180
181
182 ///////////////////////////////////////////////////////////////////////////////////////////////////
183 //! Handles ARM7TDMI JTAG commands.  Forwards others to JTAG.
184 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
185   unsigned int val;
186  
187   switch(verb){
188   case START:
189     //Enter JTAG mode.
190     jtagarm7tdmi_start();
191     txdata(app,verb,0);
192     break;
193   case JTAG_IR_SHIFT:
194     cmddataword[0] = shift_ir(cmddata[0], cmddata[1]);
195     txdata(app,verb,1);
196     break;
197   case JTAG_DR_SHIFT:
198     jtag_goto_shift_dr();
199     cmddatalong[0] = jtagtransn(cmddatalong[1],cmddata[0],cmddata[1]);
200     txdata(app,verb,4);
201     break;
202   case JTAGARM7_CHAIN0:
203     jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
204     jtag_goto_shift_dr();
205     //debughex32(cmddatalong[0]);
206     //debughex(cmddataword[4]);
207     //debughex32(cmddatalong[1]);
208     //debughex32(cmddatalong[3]);
209     cmddatalong[0] = jtagtransn(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
210     cmddatalong[2] = jtagtransn(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
211     cmddatalong[1] = jtagtransn(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
212     cmddatalong[3] = jtagtransn(cmddatalong[3], 32, MSB);
213     txdata(app,verb,16);
214     break;
215   case JTAGARM7_SCANCHAIN1:
216   case JTAGARM7_DEBUG_INSTR:
217     cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
218     txdata(app,verb,8);
219     break;
220   case JTAGARM7_EICE_READ:
221     cmddatalong[0] = eice_read(cmddata[0]);
222     txdata(app,verb,0x4);
223     break;
224   case JTAGARM7_EICE_WRITE:
225     eice_write(cmddata[4], cmddatalong[0]);
226     txdata(app,verb,0);
227     break;
228   case JTAGARM7_GET_REGISTER:
229     val = cmddata[0];
230     cmddatalong[0] = jtagarm7tdmi_get_register(val);
231     txdata(app,verb,4);
232     break;
233   case JTAGARM7_SET_REGISTER:
234     jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
235     txdata(app,verb,4);
236     break;
237
238
239   //case JTAGARM7_STEP_INSTR:
240 /*  case JTAGARM7_READ_CODE_MEMORY:
241   case JTAGARM7_WRITE_FLASH_PAGE:
242   case JTAGARM7_READ_FLASH_PAGE:
243   case JTAGARM7_MASS_ERASE_FLASH:
244   case JTAGARM7_PROGRAM_FLASH:
245   case JTAGARM7_LOCKCHIP:
246   case JTAGARM7_CHIP_ERASE:
247   */
248   default:
249     jtaghandle(app,verb,len);
250   }
251 }
252
253