1 /*! \file jtagarm7tdmi.c
2 \brief ARM7TDMI JTAG (AT91R40008)
8 #include "jtagarm7tdmi.h"
11 /**** 20-pin Connection Information (pin1 is on top-right for both connectors)****
12 GoodFET -> 7TDMI 20-pin connector (HE-10 connector)
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 ********************************/
23 /**** 14-pin Connection Information (pin1 is on top-right for both connectors)****
24 GoodFET -> 7TDMI 14-pin connector
34 http://hri.sourceforge.net/tools/jtag_faq_org.html
35 ********************************/
42 /****************************************************************
43 Enabling jtag likely differs with most platforms. We will attempt to enable most from here. Override jtagarm7tdmi_start() to extend for other implementations
44 ARM7TDMI enables three different scan chains:
45 * Chain0 - "entire periphery" including data bus
46 * Chain1 - core data bus (subset of Chain0) - Instruction Pipeline
47 * Chain2 - EmbeddedICE Logic Registers - This is our way into the fun stuff.
51 You can disable EmbeddedICE-RT by setting the DBGEN input LOW.
53 Hard wiring the DBGEN input LOW permanently disables all debug functionality.
54 When DBGEN is LOW, it inhibits DBGDEWPT, DBGIEBKPT, and EDBGRQ to
55 the core, and DBGACK from the ARM9E-S core is always LOW.
60 When the ARM9E-S core is in debug state, you can examine the core and system state
61 by forcing the load and store multiples into the instruction pipeline.
62 Before you can examine the core and system state, the debugger must determine
63 whether the processor entered debug from Thumb state or ARM state, by examining
64 bit 4 of the EmbeddedICE-RT debug status register. If bit 4 is HIGH, the core has
65 entered debug from Thumb state.
66 For more details about determining the core state, see Determining the core and system
71 --- olimex - http://www.olimex.com/dev/pdf/arm-jtag.pdf
72 JTAG signals description:
73 PIN.1 (VTREF) Target voltage sense. Used to indicate the target’s operating voltage to thedebug tool.
74 PIN.2 (VTARGET) Target voltage. May be used to supply power to the debug tool.
75 PIN.3 (nTRST) JTAG TAP reset, this signal should be pulled up to Vcc in target board.
76 PIN4,6, 8, 10,12,14,16,18,20 Ground. The Gnd-Signal-Gnd-Signal strategy implemented on the 20-way connection scheme improves noiseimmunity on the target connect cable.
77 *PIN.5 (TDI) JTAG serial data in, should be pulled up to Vcc on target board.
78 *PIN.7 (TMS) JTAG TAP Mode Select, should be pulled up to Vcc on target board.
79 *PIN.9 (TCK) JTAG clock.
80 PIN.11 (RTCK) JTAG retimed clock.Implemented on certain ASIC ARM implementations the host ASIC may need to synchronize external inputs (such as JTAG inputs) with its own internal clock.
81 *PIN.13 (TDO) JTAG serial data out.
82 *PIN.15 (nSRST) Target system reset.
83 *PIN.17 (DBGRQ) Asynchronous debug request. DBGRQ allows an external signal to force the ARM core into debug mode, should be pull down to GND.
84 PIN.19 (DBGACK) Debug acknowledge. The ARM core acknowledges debug-mode inresponse to a DBGRQ input.
86 ****************************************************************/
89 /************************** JTAGARM7TDMI Primitives ****************************/
90 void jtag_goto_shift_ir() {
100 void jtag_goto_shift_dr() {
108 void jtag_reset_to_runtest_idle() {
117 jtag_arm_tcktock(); // now in Reset state
119 jtag_arm_tcktock(); // now in Run-Test/Idle state
122 void jtag_arm_tcktock() {
130 // ! Start JTAG, setup pins, reset TAP and return IDCODE
131 unsigned long jtagarm7tdmi_start() {
133 //Known-good starting position.
134 //Might be unnecessary.
150 jtagarm7tdmi_resettap();
151 return jtagarm7tdmi_idcode();
155 //! Reset TAP State Machine
156 void jtagarm7tdmi_resettap(){ // PROVEN
158 jtag_reset_to_runtest_idle();
162 // NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR THE FUNCTIONAL EQUIVALENT
165 //! Shift N bits over TDI/TDO. May choose LSB or MSB, and select whether to terminate (TMS-high on last bit) and whether to return to RUNTEST/IDLE
166 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
168 unsigned long high = 1;
171 for (bit=(bitcount-1)/8; bit>0; bit--)
173 high <<= ((bitcount-1)%8);
178 for (bit = bitcount; bit > 0; bit--) {
179 /* write MOSI on trailing edge of previous clock */
187 SETTMS;//TMS high on last bit to exit.
191 /* read MISO on trailing edge */
197 for (bit = bitcount; bit > 0; bit--) {
198 /* write MOSI on trailing edge of previous clock */
203 word = (word & mask) << 1;
206 SETTMS;//TMS high on last bit to exit.
210 /* read MISO on trailing edge */
232 /************************************************************************
233 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
236 * * Scan Chain Select Register (4 bits_lsb)
237 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
238 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
239 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
240 ************************************************************************/
244 /************************** Basic JTAG Verb Commands *******************************/
245 //! Grab the core ID.
246 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
247 jtagarm7tdmi_resettap();
249 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
251 return jtagarmtransn(0,32, LSB, END, RETIDLE);
254 //! Connect Bypass Register to TDO/TDI
255 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
256 //jtagarm7tdmi_resettap();
258 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
260 //! INTEST verb - do internal test
261 unsigned char jtagarm7tdmi_intest() {
262 //jtagarm7tdmi_resettap();
264 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
268 unsigned char jtagarm7tdmi_extest() {
269 //jtagarm7tdmi_resettap();
271 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
275 //unsigned long jtagarm7tdmi_sample() {
276 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
277 // return jtagtransn(0,32);
281 unsigned char jtagarm7tdmi_restart() {
282 //jtagarm7tdmi_resettap();
284 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
287 //! ARM7TDMI_IR_CLAMP 0x5
288 //unsigned long jtagarm7tdmi_clamp() {
289 // jtagarm7tdmi_resettap();
291 // jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
293 // return jtagarmtransn(0, 32, LSB, END, RETIDLE);
296 //! ARM7TDMI_IR_HIGHZ 0x7
297 //unsigned char jtagarm7tdmi_highz() {
298 // jtagarm7tdmi_resettap();
300 // return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
303 //! define ARM7TDMI_IR_CLAMPZ 0x9
304 //unsigned char jtagarm7tdmi_clampz() {
305 // jtagarm7tdmi_resettap();
307 // return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
311 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
312 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
314 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
315 wise, when in debug state, the core will not be correctly isolated and intrusive
316 commands occur. Therefore, it is recommended to pass directly from the “Update”
317 state” to the “Select DR” state each time the “Update” state is reached.
319 unsigned long retval;
320 if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
322 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
324 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
325 current_chain = chain;
327 retval = current_chain;
328 // put in test mode...
330 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
335 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
336 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
337 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
343 //! push an instruction into the pipeline
344 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
345 unsigned long retval;
346 //jtagarm7tdmi_resettap(); // FIXME: DEBUG: seems necessary for some reason. ugh.
347 jtagarm7tdmi_scan_intest(1);
350 // if the next instruction is to run using MCLK (master clock), set TDI
354 count_sysspd_instr_since_debug++;
359 count_dbgspd_instr_since_debug++;
363 // Now shift in the 32 bits
364 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
365 //jtag_arm_tcktock();
371 unsigned long jtagarm7tdmi_nop(char breakpt){
372 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
375 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
376 STR R0, [R0]; Save R0 before use
377 MOV R0, PC ; Copy PC into R0
378 STR R0, [R0]; Now save the PC in R0
379 BX PC ; Jump into ARM state
386 //! set the current mode to ARM, returns PC (FIXME). Should be used by haltcpu(), which should also store PC and the THUMB state, for use by releasecpu();
387 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
388 unsigned long retval = 0xff;
389 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
390 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
391 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
392 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
393 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
394 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
395 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
396 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
397 jtagarm7tdmi_resettap(); // seems necessary for some reason. ugh.
405 /************************* EmbeddedICE Primitives ****************************/
406 //! shifter for writing to chain2 (EmbeddedICE).
407 unsigned long eice_write(unsigned char reg, unsigned long data){
408 unsigned long retval, temp;
409 jtagarm7tdmi_scan_intest(2);
410 // Now shift in the 32 bits
412 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
413 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
414 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the WRITE bit
416 //SETTMS; // Last Bit - Exit UPDATE_DR
417 //// is this update a read/write or just read?
419 //jtag_arm_tcktock();
424 //! shifter for reading from chain2 (EmbeddedICE).
425 unsigned long eice_read(unsigned char reg){ // PROVEN
427 jtagarm7tdmi_scan_intest(2);
429 // send in the register address - 5 bits LSB
431 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
433 // clear TDI to select "read only"
434 jtagarmtransn(0, 1, LSB, END, RETIDLE);
437 // Now shift out the 32 bits
438 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
445 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
446 //! Grab debug register
447 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
448 //jtagarm7tdmi_resettap();
449 return eice_read(EICE_DBGSTATUS);
452 //! Grab debug register
453 unsigned long jtagarm7tdmi_get_dbgctrl() {
454 return eice_read(EICE_DBGCTRL);
457 //! Update debug register
458 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
459 return eice_write(EICE_DBGCTRL, bits);
464 //! Set and Enable Watchpoint 0
465 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
466 // store watchpoint info? - not right now
469 eice_write(EICE_WP0ADDR, addr); // write 0 in watchpoint 0 address
470 eice_write(EICE_WP0ADDRMASK, addrmask); // write 0xffffffff in watchpoint 0 address mask
471 eice_write(EICE_WP0DATA, data); // write 0 in watchpoint 0 data
472 eice_write(EICE_WP0DATAMASK, datamask); // write 0xffffffff in watchpoint 0 data mask
473 eice_write(EICE_WP0CTRL, ctrlmask); // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
474 eice_write(EICE_WP0CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
477 //! Set and Enable Watchpoint 1
478 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
479 // store watchpoint info? - not right now
482 eice_write(EICE_WP1ADDR, addr); // write 0 in watchpoint 1 address
483 eice_write(EICE_WP1ADDRMASK, addrmask); // write 0xffffffff in watchpoint 1 address mask
484 eice_write(EICE_WP1DATA, data); // write 0 in watchpoint 1 data
485 eice_write(EICE_WP1DATAMASK, datamask); // write 0xffffffff in watchpoint 1 data mask
486 eice_write(EICE_WP1CTRL, ctrl); // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
487 eice_write(EICE_WP1CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
490 //! Disable Watchpoint 0
491 void jtagarm7tdmi_disable_watchpoint0(){
492 eice_write(EICE_WP0CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
495 //! Disable Watchpoint 1
496 void jtagarm7tdmi_disable_watchpoint1(){
497 eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
502 /******************** Complex Commands **************************/
503 //! Push an instruction into the CPU pipeline
504 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
505 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
506 unsigned long retval;
508 cmddatalong[1] = jtagarm7tdmi_nop( 0);
509 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
510 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
511 cmddatalong[4] = jtagarm7tdmi_nop( 0);
512 cmddatalong[5] = jtagarm7tdmi_nop( 0);
513 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
514 cmddatalong[7] = jtagarm7tdmi_nop( 0);
515 cmddatalong[8] = jtagarm7tdmi_nop( 0);
516 cmddatalong[9] = jtagarm7tdmi_nop( 0);
517 retval = cmddatalong[9];
523 //! Push an instruction into the CPU pipeline
524 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
525 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
526 unsigned long retval;
528 cmddatalong[1] = jtagarm7tdmi_nop( 0);
529 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
530 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
531 cmddatalong[4] = jtagarm7tdmi_nop( 0);
532 cmddatalong[5] = jtagarm7tdmi_nop( 0);
533 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
534 cmddatalong[7] = jtagarm7tdmi_nop( 0);
535 retval = jtagarm7tdmi_nop( 0);
536 cmddatalong[9] = jtagarm7tdmi_nop( 0);
537 cmddatalong[8] = retval;
542 //! Retrieve a 32-bit Register value
543 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
544 unsigned long retval = 0, instr;
545 // push nop into pipeline - clean out the pipeline...
546 cmddatalong[2] = jtagarm7tdmi_nop( 0);
548 instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
549 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
550 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
551 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
552 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
553 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
554 cmddatalong[5] = retval;
555 cmddatalong[6] = jtagarm7tdmi_nop( 0);
556 cmddatalong[7] = jtagarm7tdmi_nop( 0);
557 cmddatalong[8] = jtagarm7tdmi_nop( 0);
561 //! Retrieve a 32-bit Register value
562 unsigned long test_get_register(unsigned char reg) {
563 unsigned long retval = 0, instr;
564 // push nop into pipeline - clean out the pipeline...
565 cmddatalong[2] = jtagarm7tdmi_nop( 0);
567 instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
568 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
569 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
570 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
571 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
572 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
573 cmddatalong[5] = retval;
574 cmddatalong[6] = jtagarm7tdmi_nop( 0);
575 cmddatalong[7] = jtagarm7tdmi_nop( 0);
576 cmddatalong[8] = jtagarm7tdmi_nop( 0);
580 //! Set a 32-bit Register value
581 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
582 unsigned long retval = 0, instr;
583 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
585 instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
586 cmddatalong[2] = jtagarm7tdmi_instr_primitive(instr, 0); // push nop into pipeline - fetch
587 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
588 cmddatalong[4] = jtagarm7tdmi_instr_primitive(val-16, 0); // push 32-bit word on data bus
589 //cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
591 cmddatalong[5] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
592 cmddatalong[6] = jtagarm7tdmi_instr_primitive(val+16, 0); // push 32-bit word on data bus
593 //cmddatalong[6] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
595 if (reg == ARM_REG_PC){
596 cmddatalong[7] = jtagarm7tdmi_nop( 0);
597 cmddatalong[8] = jtagarm7tdmi_nop( 0);
599 cmddatalong[9] = jtagarm7tdmi_nop( 0);
601 retval = cmddatalong[5];
605 //! Set a 32-bit Register value
606 unsigned long test_set_register(unsigned char reg, unsigned long val) {
607 unsigned long retval = 0, instr;
608 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
610 instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
611 cmddatalong[2] = jtagarm7tdmi_instr_primitive(instr, 0);
613 cmddatalong[3] = jtagarm7tdmi_instr_primitive(val+32, 0); // push 32-bit word on data bus - execute state
614 cmddatalong[4] = jtagarm7tdmi_instr_primitive(val+16, 0); // push 32-bit word on data bus - execute state
615 cmddatalong[5] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus - execute state
616 cmddatalong[6] = jtagarm7tdmi_instr_primitive(val-16, 0); // push 32-bit word on data bus - execute state
618 if (reg == ARM_REG_PC){
619 cmddatalong[7] = jtagarm7tdmi_nop( 0);
620 cmddatalong[8] = jtagarm7tdmi_nop( 0);
622 cmddatalong[9] = jtagarm7tdmi_instr_primitive(val-32, 0); // push 32-bit word on data bus - execute state
624 retval = cmddatalong[5];
631 //! Get all registers. Return an array
632 unsigned long* jtagarm7tdmi_get_registers() {
633 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
634 cmddatalong[2] = jtagarm7tdmi_nop( 0);
635 cmddatalong[3] = jtagarm7tdmi_nop( 0);
636 cmddatalong[4] = jtagarm7tdmi_nop( 0);
637 cmddatalong[5] = jtagarm7tdmi_nop( 0);
638 cmddatalong[6] = jtagarm7tdmi_nop( 0);
639 cmddatalong[7] = jtagarm7tdmi_nop( 0);
640 cmddatalong[8] = jtagarm7tdmi_nop( 0);
641 cmddatalong[9] = jtagarm7tdmi_nop( 0);
642 cmddatalong[10] = jtagarm7tdmi_nop( 0);
643 cmddatalong[11] = jtagarm7tdmi_nop( 0);
644 cmddatalong[12] = jtagarm7tdmi_nop( 0);
645 cmddatalong[13] = jtagarm7tdmi_nop( 0);
646 cmddatalong[14] = jtagarm7tdmi_nop( 0);
647 cmddatalong[15] = jtagarm7tdmi_nop( 0);
648 cmddatalong[16] = jtagarm7tdmi_nop( 0);
649 cmddatalong[17] = jtagarm7tdmi_nop( 0);
650 cmddatalong[18] = jtagarm7tdmi_nop( 0);
651 cmddatalong[19] = jtagarm7tdmi_nop( 0);
652 cmddatalong[20] = jtagarm7tdmi_nop( 0);
656 //! Get all registers. Return an array
657 unsigned long* jtagarm7tdmi_set_registers() {
658 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
659 cmddatalong[2] = jtagarm7tdmi_nop( 0);
660 cmddatalong[3] = jtagarm7tdmi_nop( 0);
661 cmddatalong[4] = jtagarm7tdmi_instr_primitive(0x40,0);
662 cmddatalong[5] = jtagarm7tdmi_instr_primitive(0x41,0);
663 cmddatalong[6] = jtagarm7tdmi_instr_primitive(0x42,0);
664 cmddatalong[7] = jtagarm7tdmi_instr_primitive(0x43,0);
665 cmddatalong[8] = jtagarm7tdmi_instr_primitive(0x44,0);
666 cmddatalong[9] = jtagarm7tdmi_instr_primitive(0x45,0);
667 cmddatalong[10] = jtagarm7tdmi_instr_primitive(0x46,0);
668 cmddatalong[11] = jtagarm7tdmi_instr_primitive(0x47,0);
669 cmddatalong[12] = jtagarm7tdmi_instr_primitive(0x48,0);
670 cmddatalong[13] = jtagarm7tdmi_instr_primitive(0x49,0);
671 cmddatalong[14] = jtagarm7tdmi_instr_primitive(0x4a,0);
672 cmddatalong[15] = jtagarm7tdmi_instr_primitive(0x4b,0);
673 cmddatalong[16] = jtagarm7tdmi_instr_primitive(0x4c,0);
674 cmddatalong[17] = jtagarm7tdmi_instr_primitive(0x4d,0);
675 cmddatalong[18] = jtagarm7tdmi_instr_primitive(0x4e,0);
676 cmddatalong[19] = jtagarm7tdmi_instr_primitive(0x4f,0);
680 //! Retrieve the CPSR Register value
681 unsigned long jtagarm7tdmi_get_regCPSR() {
682 unsigned long retval = 0;
684 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
685 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0); // push MRS_R0, CPSR into pipeline
686 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
687 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
688 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
689 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
690 cmddatalong[6] = retval;
694 //! Retrieve the CPSR Register value
695 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
696 unsigned long retval = 0;
698 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
699 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0); // push MSR cpsr_cxsf, R0 into pipeline
700 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
701 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
703 retval = jtagarm7tdmi_instr_primitive(val, 0);// push 32-bit word on data bus
704 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
705 cmddatalong[4] = retval;
709 //! Write data to address - Assume TAP in run-test/idle state
710 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
711 unsigned long r0=0, r1=-1;
713 r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
714 r1 = jtagarm7tdmi_get_register(1);
715 jtagarm7tdmi_set_register(0, adr); // write address into R0
716 jtagarm7tdmi_set_register(1, data); // write data in R1
717 jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
718 jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
719 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
720 jtagarm7tdmi_nop( 0); // push nop into pipeline
721 jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
722 jtagarm7tdmi_set_register(0, r0);
729 //! Read data from address
730 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
731 unsigned long retval = 0;
732 unsigned long r0=0, r1=-1;
733 int waitcount = 0xfff;
735 r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
736 r1 = jtagarm7tdmi_get_register(1);
737 jtagarm7tdmi_set_register(0, adr); // write address into R0
738 jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
739 jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
740 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
741 jtagarm7tdmi_nop( 0); // push nop into pipeline
742 jtagarm7tdmi_restart(); // SHIFT_IR with RESTART instruction
744 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
745 while ((jtagarm7tdmi_get_dbgstate() & 9) == 0 && waitcount > 0){
752 retval = jtagarm7tdmi_get_register(1); // read memory value from R1 register
753 jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
754 jtagarm7tdmi_set_register(0, r0);
760 //! Read Program Counter
761 unsigned long jtagarm7tdmi_getpc(){
762 return jtagarm7tdmi_get_register(ARM_REG_PC);
765 //! Set Program Counter
766 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
767 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
770 //! Halt CPU - returns 0xffff if the operation fails to complete within
771 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
772 int waitcount = 0xfff;
774 // store watchpoint info? - not right now
775 eice_write(EICE_WP1ADDR, 0); // write 0 in watchpoint 1 address
776 eice_write(EICE_WP1ADDRMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 address mask
777 eice_write(EICE_WP1DATA, 0); // write 0 in watchpoint 1 data
778 eice_write(EICE_WP1DATAMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 data mask
779 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!? // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
780 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!? // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
782 // poll until debug status says the cpu is in debug mode
783 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount-- > 0){
786 eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
788 // store the debug state
789 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
790 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
791 count_dbgspd_instr_since_debug = 0;
792 count_sysspd_instr_since_debug = 0;
794 // get into ARM mode if the T flag is set (Thumb mode)
795 while (jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT && waitcount-- > 0) {
796 jtagarm7tdmi_setMode_ARM();
798 jtagarm7tdmi_resettap();
802 unsigned long jtagarm7tdmi_releasecpu(){
803 int waitcount = 0xfff;
805 // somehow determine what PC should be (a couple ways possible, calculations required)
806 jtagarm7tdmi_nop(0); // NOP
807 jtagarm7tdmi_nop(1); // NOP/BREAKPT
809 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){ // FIXME: FORNICATED! BX requires register, thus more instrs... could we get away with the same instruction but +1 to offset?
810 instr = ARM_INSTR_B_PC + 0x1000001 - (count_dbgspd_instr_since_debug) - (count_sysspd_instr_since_debug*3); //FIXME: make this right - can't we just do an a7solute b/bx?
811 jtagarm7tdmi_instr_primitive(instr,0);
813 instr = ARM_INSTR_B_PC + 0x1000000 - (count_dbgspd_instr_since_debug*4) - (count_sysspd_instr_since_debug*12);
814 jtagarm7tdmi_instr_primitive(instr,0);
818 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE); // VERB_RESTART
820 // wait until restart-bit set in debug state register
821 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
825 last_halt_debug_state = -1;
833 ///////////////////////////////////////////////////////////////////////////////////////////////////
834 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
835 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
836 register char blocks;
838 unsigned int i,val,mlop;
841 jtagarm7tdmi_resettap();
846 cmddatalong[0] = jtagarm7tdmi_start();
847 cmddatalong[2] = jtagarm7tdmi_haltcpu();
848 //jtagarm7tdmi_resettap();
849 cmddatalong[1] = jtagarm7tdmi_get_dbgstate();
851 // DEBUG: FIXME: NOT PART OF OPERATIONAL CODE
852 //for (mlop=2;mlop<4;mlop++){
853 // jtagarm7tdmi_set_register(mlop, 0x43424140);
855 /////////////////////////////////////////////
856 txdata(app,verb,0xc);
858 case JTAGARM7TDMI_READMEM:
860 blocks=(len>4?cmddata[4]:1);
864 txhead(app,verb,len);
868 jtagarm7tdmi_resettap();
871 val=jtagarm7tdmi_readmem(at);
875 serial_tx((val&0xFF00)>>8);
880 case JTAGARM7TDMI_GET_CHIP_ID:
881 jtagarm7tdmi_resettap();
882 cmddatalong[0] = jtagarm7tdmi_idcode();
887 case JTAGARM7TDMI_WRITEMEM:
889 jtagarm7tdmi_resettap();
890 jtagarm7tdmi_writemem(cmddatalong[0],
892 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
896 case JTAGARM7TDMI_HALTCPU:
897 cmddatalong[0] = jtagarm7tdmi_haltcpu();
900 case JTAGARM7TDMI_RELEASECPU:
901 jtagarm7tdmi_resettap();
902 cmddatalong[0] = jtagarm7tdmi_releasecpu();
905 //unimplemented functions
906 //case JTAGARM7TDMI_SETINSTRFETCH:
907 //case JTAGARM7TDMI_WRITEFLASH:
908 //case JTAGARM7TDMI_ERASEFLASH:
909 case JTAGARM7TDMI_SET_PC:
910 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
913 case JTAGARM7TDMI_GET_DEBUG_CTRL:
914 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
917 case JTAGARM7TDMI_SET_DEBUG_CTRL:
918 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
921 case JTAGARM7TDMI_GET_PC:
922 cmddatalong[0] = jtagarm7tdmi_getpc();
925 case JTAGARM7TDMI_GET_DEBUG_STATE:
926 //jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
927 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
930 //case JTAGARM7TDMI_GET_WATCHPOINT:
931 //case JTAGARM7TDMI_SET_WATCHPOINT:
932 case JTAGARM7TDMI_GET_REGISTER:
933 jtagarm7tdmi_resettap();
934 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
935 //cmddatalong[0] = test_get_register(cmddata[0]);
938 case JTAGARM7TDMI_SET_REGISTER: // FIXME: NOT AT ALL CORRECT, THIS IS TESTING CODE ONLY
939 jtagarm7tdmi_resettap();
940 cmddatalong[0] = cmddatalong[1];
941 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
942 //test_set_register(cmddata[0], cmddatalong[1]);
945 case JTAGARM7TDMI_GET_REGISTERS:
946 jtagarm7tdmi_resettap();
947 jtagarm7tdmi_get_registers();
948 txdata(app,verb,200);
950 case JTAGARM7TDMI_SET_REGISTERS:
951 jtagarm7tdmi_resettap();
952 jtagarm7tdmi_set_registers();
953 txdata(app,verb,200);
955 case JTAGARM7TDMI_DEBUG_INSTR:
956 jtagarm7tdmi_resettap();
957 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
960 //case JTAGARM7TDMI_STEP_INSTR:
961 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
962 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
963 case JTAGARM7TDMI_READ_FLASH_PAGE:
964 case JTAGARM7TDMI_MASS_ERASE_FLASH:
965 case JTAGARM7TDMI_PROGRAM_FLASH:
966 case JTAGARM7TDMI_LOCKCHIP:
967 case JTAGARM7TDMI_CHIP_ERASE:
969 // Really ARM specific stuff
970 case JTAGARM7TDMI_GET_CPSR:
971 jtagarm7tdmi_resettap();
972 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
975 case JTAGARM7TDMI_SET_CPSR:
976 jtagarm7tdmi_resettap();
977 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
980 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
981 jtagarm7tdmi_resettap();
982 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
985 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
986 jtagarm7tdmi_resettap();
987 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
990 case JTAGARM7TDMI_SET_MODE_THUMB:
991 case JTAGARM7TDMI_SET_MODE_ARM:
992 jtagarm7tdmi_resettap();
993 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
997 case 0xD0: // loopback test
998 jtagarm7tdmi_resettap();
999 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
1002 case 0xD8: // EICE_READ
1003 jtagarm7tdmi_resettap();
1004 cmddatalong[0] = eice_read(cmddatalong[0]);
1007 case 0xD9: // EICE_WRITE
1008 jtagarm7tdmi_resettap();
1009 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
1012 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
1013 jtagarm7tdmi_resettap();
1014 jtagarm7tdmi_scan_intest(0);
1015 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
1016 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
1017 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
1018 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
1019 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
1020 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
1021 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
1022 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
1023 jtagarm7tdmi_resettap();
1024 jtagarm7tdmi_scan_intest(1);
1025 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
1026 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
1027 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
1028 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1029 jtagarm7tdmi_resettap();
1030 txdata(app,verb,48);
1034 jtaghandle(app,verb,len);