2 \brief ARM7TDMI JTAG (AT91R40008, AT91SAM7xxx)
10 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
11 void jtagarm7_handle_fn( uint8_t const app,
15 // define the jtagarm7 app's app_t
16 app_t const jtagarm7_app = {
28 "\tThe JTAGARM7 app extends the basic JTAG app with support\n"
29 "\tfor JTAG'ing ARM7TDMI based devices.\n"
32 unsigned long last_instr = -1;
33 unsigned char last_sysstate = 0;
34 unsigned char last_ir = -1;
35 unsigned char last_scanchain = -1;
36 unsigned char current_dbgstate = -1;
37 unsigned char g_jtag_ir_size = 4;
38 unsigned char g_jtagarm_scan_n_bitsize = 4;
39 //unsigned char last_halt_debug_state = -1;
40 //unsigned long last_halt_pc = -1;
42 /**** 20-pin Connection Information (pin1 is on top-right for both connectors)****
43 GoodFET -> 7TDMI 20-pin connector (HE-10 connector)
49 9 4,6,8,10,12,14,16,18,20 (GND)
51 // no longer... (11 17/3 (nTRST) (different sources suggest 17 or 3 alternately))
52 ********************************/
54 /**** 14-pin Connection Information (pin1 is on top-right for both connectors)****
55 GoodFET -> 7TDMI 14-pin connector
63 // no longer... (11 3 (nTRST))
65 http://hri.sourceforge.net/tools/jtag_faq_org.html
66 ********************************/
68 /* WHAT SHOULD THIS MODULE DO?
74 * *scanchain1 (instr_primitive)
75 * *scanchain2 (hmmmm... perhaps we'll need to keep the debug calls)
82 // ! Start JTAG, setup pins, reset TAP and return IDCODE
83 void jtagarm7tdmi_start() {
90 u8 jtagarm_shift_ir(u8 ir, u8 flags){
94 jtag_shift_register();
95 retval = jtag_trans_n(ir, g_jtag_ir_size, LSB|flags);
101 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST
102 unsigned long jtagarm7tdmi_scan(u8 chain, u8 testmode) { // PROVEN
104 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
105 wise, when in debug state, the core will not be correctly isolated and intrusive
106 commands occur. Therefore, it is recommended to pass directly from the “Update”
107 state” to the “Select DR” state each time the “Update” state is reached.
109 unsigned long retval = 0;
110 if (last_scanchain != chain){
111 jtagarm_shift_ir(ARM7TDMI_IR_SCAN_N, NORETIDLE);
112 last_scanchain = chain;
114 jtag_shift_register();
115 retval = jtag_trans_n(chain, g_jtagarm_scan_n_bitsize, LSB | NORETIDLE);
117 jtagarm_shift_ir(testmode, NORETIDLE);
122 /************************* EmbeddedICE Primitives ****************************/
123 //! shifter for writing to chain2 (EmbeddedICE).
124 unsigned long eice_write(unsigned char reg, unsigned long data){
125 unsigned long retval;
126 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
128 jtag_shift_register();
129 retval = jtag_trans_n(data, 32, LSB| NOEND| NORETIDLE); // send in the data - 32-bits lsb
130 jtag_trans_n(reg, 5, LSB| NOEND| NORETIDLE); // send in the register address - 5 bits lsb
131 jtag_trans_n(1, 1, LSB); // send in the WRITE bit
135 //! shifter for reading from chain2 (EmbeddedICE).
136 unsigned long eice_read(unsigned char reg){ // PROVEN
137 unsigned long retval;
138 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
140 jtag_shift_register(); // send in the register address - 5 bits LSB
141 jtag_trans_n(reg, 5, LSB| NOEND| NORETIDLE);
142 jtag_trans_n(0L, 1, LSB); // clear TDI to select "read only"
144 jtag_shift_register(); // Now shift out the 32 bits
145 retval = jtag_trans_n(0L, 32, LSB); // atmel arm jtag docs pp.10-11: LSB first
150 //! push an instruction into the pipeline
151 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ // PROVEN
152 unsigned long retval = 0;
153 //debugstr("jtagarm7tdmi_instr_primitive");
154 jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
156 //debugstr("instruction:");
158 //if (!(last_instr == instr && last_sysstate == breakpt))
161 jtag_shift_register();
162 // if the next instruction is to run using MCLK (master clock), set TDI
165 //debugstr("--breakpt flag set");
174 // Now shift in the 32 bits
175 retval = jtag_trans_n(instr, 32, 0); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
176 //debugstr("hot off the pipeline!");
177 //debughex32(retval);
179 last_sysstate = breakpt;
181 //{ // this assumes we don't want retval! wtfo!?
187 u32 jtagarm7tdmi_nop(u8 brkpt){
188 // WARNING: current_dbgstate must be up-to-date before calling this function!!!!!
189 //debugstr("jtagarm7tdmi_nop");
190 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
191 return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, brkpt);
192 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
195 /******************** Complex Commands **************************/
197 //! Retrieve a 32-bit Register value
198 unsigned long jtagarm7_get_reg_prim(unsigned long instr){
199 //debugstr("jtagarm7_get_reg_prim");
200 jtagarm7tdmi_nop( 0);
201 jtagarm7tdmi_instr_primitive(instr, 0);
202 jtagarm7tdmi_nop( 0);
203 jtagarm7tdmi_nop( 0);
204 jtagarm7tdmi_nop( 0);
205 return jtagarm7tdmi_nop( 0); // recover 32-bit word
208 //! Set a 32-bit Register value
209 void jtagarm7_set_reg_prim(unsigned long instr, unsigned long reg, unsigned long val){ // PROVEN - 100827 (non-PC)
210 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
211 jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
212 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
213 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
214 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
215 if (reg == ARM_REG_PC){
216 //debugstr("setting pc...");
217 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
218 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
220 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
221 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
224 void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){ // PROVEN - 100827
226 jtagarm7tdmi_nop( 0);
228 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)), 0);
230 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)), 0);
232 jtagarm7tdmi_nop( 0);
233 jtagarm7tdmi_nop( 0);
234 jtagarm7tdmi_nop( 0);
237 unsigned long jtagarm7tdmi_get_register(unsigned long reg) { // PROVEN - 100827
238 unsigned long retval=0L, instr, r0;
239 current_dbgstate = eice_read(EICE_DBGSTATUS);
240 //debugstr("current_dbgstate:");
241 //debughex32(current_dbgstate);
243 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
245 //debugstr("debug: jtagarm7tdmi_get_register: thumb reg > 15");
247 r0 = jtagarm7_get_reg_prim( THUMB_READ_REG); // save reg0
248 jtagarm7_thumb_swap_reg(THUMB_SWAP_HiLo, reg); // clobber reg0 with hi reg
249 retval = jtagarm7_get_reg_prim( THUMB_READ_REG); // recover 32-bit word
250 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
253 //debugstr("debug: jtagarm7tdmi_get_register: thumb reg < 15");
254 instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
258 //debugstr("debug: jtagarm7tdmi_get_register: arm");
259 instr = (reg<<12L) | ARM_READ_REG; // STR Rx, [R14]
261 return jtagarm7_get_reg_prim(instr);
264 //! Set a 32-bit Register value
265 // writing to a register is a problem child in ARM, actually. if the register you are using as the indirect offset register is misaligned, your results are misaligned.
266 // this set_register implementation normalizes this process at the cost of performance. since we don't know what's in the register, we set it to 0 first
267 // we could use r14 and hope all is well, but only for arm, not thumb mode, and not always is all well then either. this is a performance trade-off we may have to revisit later
269 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN - 100827
270 unsigned long instr, r0;
271 current_dbgstate = eice_read(EICE_DBGSTATUS);
272 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
275 r0 = jtagarm7_get_reg_prim(THUMB_READ_REG);
276 jtagarm7_set_reg_prim(THUMB_WRITE_REG, 0, 0);
277 instr = (unsigned long)(THUMB_WRITE_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
278 jtagarm7_set_reg_prim(instr, reg, val);
279 jtagarm7_thumb_swap_reg(THUMB_SWAP_LoHi, reg); // place 32-bit word into a high register
280 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
282 instr = THUMB_WRITE_REG | (reg) | ((reg)<<16) | ((reg)<<3) | ((reg)<<19);
284 instr = ARM_WRITE_REG | (reg<<12L) | (reg<<16); // LDR Rx, [R14]
288 // --- first time to clear the register... this ensures the write is not 8-bit offset ---
289 jtagarm7_set_reg_prim(instr, reg, 0);
290 // --- now we actually write to the register ---
291 jtagarm7_set_reg_prim(instr, reg, val);
295 ///////////////////////////////////////////////////////////////////////////////////////////////////
296 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
297 void jtagarm7_handle_fn( uint8_t const app,
306 jtagarm7tdmi_start();
309 case JTAGARM7_SCAN_N_SIZE:
310 g_jtagarm_scan_n_bitsize = cmddata[0];
313 case JTAGARM7_IR_SIZE:
314 g_jtag_ir_size = cmddata[0];
318 cmddataword[0] = jtagarm_shift_ir(cmddata[0], cmddata[1]);
323 jtag_shift_register();
327 //debughex32(cmddatalong[0]);
328 //debughex32(cmddatalong[1]);
329 cmddatalong[1] = jtag_trans_n(cmddatalong[2], val - 32 ,cmddata[1] | NOEND |NORETIDLE);
330 cmddatalong[0] = jtag_trans_n(cmddatalong[2], 32, cmddata[1]);
334 //debughex32(cmddatalong[0]);
335 cmddatalong[0] = jtag_trans_n(cmddatalong[1], val, cmddata[1]);
337 txdata(app,verb,val/8);
339 case JTAG_DR_SHIFT_MORE:
340 // assumes you just executed JTAG_DR_SHIFT with NOEND flag set
341 debugstr("JTAG_DR_SHIFT_MORE");
345 //debughex32(cmddatalong[0]);
346 //debughex32(cmddatalong[1]);
347 cmddatalong[1] = jtag_trans_n(cmddatalong[2], val - 32 ,cmddata[1] | NOEND |NORETIDLE);
348 cmddatalong[0] = jtag_trans_n(cmddatalong[2], 32, cmddata[1]);
352 debughex32(cmddatalong[0]);
353 cmddatalong[0] = jtag_trans_n(cmddatalong[1], val, cmddata[1]);
355 txdata(app,verb,val/8);
357 case JTAGARM7_CHAIN0:
358 jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
360 jtag_shift_register();
361 //debughex32(cmddatalong[0]);
362 //debughex(cmddataword[4]);
363 //debughex32(cmddatalong[1]);
364 //debughex32(cmddatalong[3]);
365 cmddatalong[0] = jtag_trans_n(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
366 cmddatalong[2] = jtag_trans_n(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
367 cmddatalong[1] = jtag_trans_n(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
368 cmddatalong[3] = jtag_trans_n(cmddatalong[3], 32, MSB);
371 case JTAGARM7_SCANCHAIN1:
372 case JTAGARM7_DEBUG_INSTR:
373 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
376 case JTAGARM7_EICE_READ:
377 cmddatalong[0] = eice_read(cmddata[0]);
378 txdata(app,verb,0x4);
380 case JTAGARM7_EICE_WRITE:
381 eice_write(cmddata[4], cmddatalong[0]);
384 case JTAGARM7_GET_REGISTER:
386 cmddatalong[0] = jtagarm7tdmi_get_register(val);
389 case JTAGARM7_SET_REGISTER:
390 jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
393 case JTAG_RESET_TARGET:
395 debugstr("RESET TARGET");
396 //debughex((P3OUT&RST));
398 //debughex((P3OUT&RST));
399 delay(cmddataword[0]);
401 //debughex((P3OUT&RST));
406 //case JTAGARM7_STEP_INSTR:
407 /* case JTAGARM7_READ_CODE_MEMORY:
408 case JTAGARM7_WRITE_FLASH_PAGE:
409 case JTAGARM7_READ_FLASH_PAGE:
410 case JTAGARM7_MASS_ERASE_FLASH:
411 case JTAGARM7_PROGRAM_FLASH:
412 case JTAGARM7_LOCKCHIP:
413 case JTAGARM7_CHIP_ERASE:
416 (*(jtag_app.handle))(app,verb,len);