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 jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
155 //if (!(last_instr == instr && last_sysstate == breakpt))
158 jtag_shift_register();
159 // if the next instruction is to run using MCLK (master clock), set TDI
162 //debugstr("--breakpt flag set");
171 // Now shift in the 32 bits
172 retval = jtag_trans_n(instr, 32, 0); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
174 last_sysstate = breakpt;
179 //! push an instruction into the pipeline
180 unsigned long jtagarm_instr_primitive(unsigned char *instr, char breakpt){
181 unsigned long retval = 0;
182 jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
184 //if (!(last_instr == instr && last_sysstate == breakpt))
187 jtag_shift_register();
189 // if the next instruction is to run using MCLK (master clock), set TDI
196 // Now shift in the 32 bits
197 retval = jtag_trans_many(instr, 32, 0); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
199 last_sysstate = breakpt;
204 u32 jtagarm7tdmi_nop(u8 brkpt){
205 // WARNING: current_dbgstate must be up-to-date before calling this function!!!!!
206 //debugstr("jtagarm7tdmi_nop");
207 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
208 return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, brkpt);
209 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
212 /******************** Complex Commands **************************/
214 //! Retrieve a 32-bit Register value
215 unsigned long jtagarm7_get_reg_prim(unsigned long instr){
216 //debugstr("jtagarm7_get_reg_prim");
217 jtagarm7tdmi_nop( 0);
218 jtagarm7tdmi_instr_primitive(instr, 0);
219 jtagarm7tdmi_nop( 0);
220 jtagarm7tdmi_nop( 0);
221 jtagarm7tdmi_nop( 0);
222 return jtagarm7tdmi_nop( 0); // recover 32-bit word
225 //! Set a 32-bit Register value
226 void jtagarm7_set_reg_prim(unsigned long instr, unsigned long reg, unsigned long val){ // PROVEN - 100827 (non-PC)
227 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
228 jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
229 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
230 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
231 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
232 if (reg == ARM_REG_PC){
233 //debugstr("setting pc...");
234 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
235 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
237 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
238 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
241 void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){ // PROVEN - 100827
243 jtagarm7tdmi_nop( 0);
245 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)), 0);
247 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)), 0);
249 jtagarm7tdmi_nop( 0);
250 jtagarm7tdmi_nop( 0);
251 jtagarm7tdmi_nop( 0);
254 unsigned long jtagarm7tdmi_get_register(unsigned long reg) { // PROVEN - 100827
255 unsigned long retval=0L, instr, r0;
256 current_dbgstate = eice_read(EICE_DBGSTATUS);
257 //debugstr("current_dbgstate:");
258 //debughex32(current_dbgstate);
260 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
262 //debugstr("debug: jtagarm7tdmi_get_register: thumb reg > 15");
264 r0 = jtagarm7_get_reg_prim( THUMB_READ_REG); // save reg0
265 jtagarm7_thumb_swap_reg(THUMB_SWAP_HiLo, reg); // clobber reg0 with hi reg
266 retval = jtagarm7_get_reg_prim( THUMB_READ_REG); // recover 32-bit word
267 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
270 //debugstr("debug: jtagarm7tdmi_get_register: thumb reg < 15");
271 instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
275 //debugstr("debug: jtagarm7tdmi_get_register: arm");
276 instr = (reg<<12L) | ARM_READ_REG; // STR Rx, [R14]
278 return jtagarm7_get_reg_prim(instr);
281 //! Set a 32-bit Register value
282 // 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.
283 // 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
284 // 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
286 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN - 100827
287 unsigned long instr, r0;
288 current_dbgstate = eice_read(EICE_DBGSTATUS);
289 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
292 r0 = jtagarm7_get_reg_prim(THUMB_READ_REG);
293 jtagarm7_set_reg_prim(THUMB_WRITE_REG, 0, 0);
294 instr = (unsigned long)(THUMB_WRITE_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
295 jtagarm7_set_reg_prim(instr, reg, val);
296 jtagarm7_thumb_swap_reg(THUMB_SWAP_LoHi, reg); // place 32-bit word into a high register
297 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
299 instr = THUMB_WRITE_REG | (reg) | ((reg)<<16) | ((reg)<<3) | ((reg)<<19);
301 instr = ARM_WRITE_REG | (reg<<12L) | (reg<<16); // LDR Rx, [R14]
305 // --- first time to clear the register... this ensures the write is not 8-bit offset ---
306 jtagarm7_set_reg_prim(instr, reg, 0);
307 // --- now we actually write to the register ---
308 jtagarm7_set_reg_prim(instr, reg, val);
312 ///////////////////////////////////////////////////////////////////////////////////////////////////
313 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
314 void jtagarm7_handle_fn( uint8_t const app,
323 jtagarm7tdmi_start();
326 case JTAGARM7_SCAN_N_SIZE:
327 g_jtagarm_scan_n_bitsize = cmddata[0];
330 case JTAGARM7_IR_SIZE:
331 g_jtag_ir_size = cmddata[0];
335 cmddataword[0] = jtagarm_shift_ir(cmddata[0], cmddata[1]);
340 jtag_shift_register();
344 //debughex32(cmddatalong[0]);
345 //debughex32(cmddatalong[1]);
346 cmddatalong[1] = jtag_trans_n(cmddatalong[2], val - 32 ,cmddata[1] | NOEND |NORETIDLE);
347 cmddatalong[0] = jtag_trans_n(cmddatalong[2], 32, cmddata[1]);
351 //debughex32(cmddatalong[0]);
352 cmddatalong[0] = jtag_trans_n(cmddatalong[1], val, cmddata[1]);
354 txdata(app,verb,val/8);
356 case JTAG_DR_SHIFT_MORE:
357 // assumes you just executed JTAG_DR_SHIFT with NOEND flag set
358 debugstr("JTAG_DR_SHIFT_MORE");
362 //debughex32(cmddatalong[0]);
363 //debughex32(cmddatalong[1]);
364 cmddatalong[1] = jtag_trans_n(cmddatalong[2], val - 32 ,cmddata[1] | NOEND |NORETIDLE);
365 cmddatalong[0] = jtag_trans_n(cmddatalong[2], 32, cmddata[1]);
369 debughex32(cmddatalong[0]);
370 cmddatalong[0] = jtag_trans_n(cmddatalong[1], val, cmddata[1]);
372 txdata(app,verb,val/8);
374 case JTAG_DR_SHIFT_MANY:
376 jtag_shift_register();
378 jtag_trans_many(&cmddata[2], val, cmddata[1] );
379 txdata(app,verb,((val+7)/8)+2);
381 case JTAGARM7_CHAIN0:
382 jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
384 jtag_shift_register();
385 //debughex32(cmddatalong[0]);
386 //debughex(cmddataword[4]);
387 //debughex32(cmddatalong[1]);
388 //debughex32(cmddatalong[3]);
389 cmddatalong[0] = jtag_trans_n(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
390 cmddatalong[2] = jtag_trans_n(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
391 cmddatalong[1] = jtag_trans_n(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
392 cmddatalong[3] = jtag_trans_n(cmddatalong[3], 32, MSB);
395 case JTAGARM7_SCANCHAIN1:
396 case JTAGARM7_DEBUG_INSTR:
397 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
400 case JTAGARM_SCAN1_MANY:
401 cmddatalong[0] = jtagarm_instr_primitive(&cmddata[1],cmddata[0]);
404 case JTAGARM7_EICE_READ:
405 cmddatalong[0] = eice_read(cmddata[0]);
406 txdata(app,verb,0x4);
408 case JTAGARM7_EICE_WRITE:
409 eice_write(cmddata[4], cmddatalong[0]);
412 case JTAGARM7_GET_REGISTER:
414 cmddatalong[0] = jtagarm7tdmi_get_register(val);
417 case JTAGARM7_SET_REGISTER:
418 jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
421 case JTAG_RESET_TARGET:
423 debugstr("RESET TARGET");
424 //debughex((P3OUT&RST));
426 //debughex((P3OUT&RST));
427 delay(cmddataword[0]);
429 //debughex((P3OUT&RST));
434 //case JTAGARM7_STEP_INSTR:
435 /* case JTAGARM7_READ_CODE_MEMORY:
436 case JTAGARM7_WRITE_FLASH_PAGE:
437 case JTAGARM7_READ_FLASH_PAGE:
438 case JTAGARM7_MASS_ERASE_FLASH:
439 case JTAGARM7_PROGRAM_FLASH:
440 case JTAGARM7_LOCKCHIP:
441 case JTAGARM7_CHIP_ERASE:
444 (*(jtag_app.handle))(app,verb,len);
448 #define min(x,y) ( (x>y) ? y : x )
449 #define max(x,y) ( (x>y) ? x : y )
451 uint8_t* jtag_trans_many(uint8_t *data,
453 enum eTransFlags flags)
461 if (!in_state(SHIFT_IR | SHIFT_DR))
463 debugstr("jtag_trans_many from invalid TAP state");
471 high = (1L << (min(bitcount,8) - 1));
474 for (bit = bitcount; bit > 0; bit--,bitnum++)
478 high = (1L << (min(bit,8) - 1));
483 /* write MOSI on trailing edge of previous clock */
494 if ((bit == 1) && !(flags & NOEND))
495 SETTMS; //TMS high on last bit to exit.
499 if ((bit == 1) && !(flags & NOEND))
500 jtag_state <<= 1; // Exit1-DR or Exit1-IR
502 /* read MISO on trailing edge */
509 hmask = (high<<1) - 1;
514 // MSB... we need to start at the end of the byte array
515 data += (bitcount/8);
516 bitnum = bitcount % 8;
517 high = (1L << (min(bitnum,8) - 1));
519 hmask = (high<<1) - 1;
521 for (bit = bitcount; bit > 0; bit--,bitnum--)
527 high = (1L << (min(bit,8) - 1));
529 hmask = (high<<1) - 1;
535 /* write MOSI on trailing edge of previous clock */
544 *data = (*data & mask) << 1;
546 if ((bit==1) && !(flags & NOEND))
547 SETTMS; //TMS high on last bit to exit.
551 if ((bit == 1) && !(flags & NOEND))
552 jtag_state <<= 1; // Exit1-DR or Exit1-IR
554 /* read MISO on trailing edge */
560 //This is needed for 20-bit MSP430 chips.
561 //Might break another 20-bit chip, if one exists.
563 //UGH... this needs to be fixed... doesn't work with char*
565 *data = ((*data << 16) | (*data >> 4)) & 0x000FFFFF;
570 if (!(flags & NOEND))
575 jtag_state <<= 3; // Update-DR or Update-IR
578 if (!(flags & NORETIDLE))
583 jtag_state = RUN_TEST_IDLE;