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