1 /*! \file jtagarm7tdmi.c
2 \author Matthew Carpenter <matt@inguardians.com>
3 \brief ARM7TDMI JTAG (AT91R40008)
9 #include "jtagarm7tdmi.h"
12 /**** 20-pin Connection Information (pin1 is on top-right for both connectors)****
13 GoodFET -> 7TDMI 20-pin connector (HE-10 connector)
20 9 4,6,8,10,12,14,16,18,20 (GND)
21 11 17/3 (nTRST) (different sources suggest 17 or 3 alternately)
22 ********************************/
24 /**** 14-pin Connection Information (pin1 is on top-right for both connectors)****
25 GoodFET -> 7TDMI 14-pin connector
35 http://hri.sourceforge.net/tools/jtag_faq_org.html
36 ********************************/
38 /****************************************************************
39 Enabling jtag likely differs with most platforms. We will attempt to enable most from here. Override jtagarm7tdmi_start() to extend for other implementations
40 ARM7TDMI enables three different scan chains:
41 * Chain0 - "entire periphery" including data bus
42 * Chain1 - core data bus (subset of Chain0) - Instruction Pipeline
43 * Chain2 - EmbeddedICE Logic Registers - This is our way into the fun stuff.
47 You can disable EmbeddedICE-RT by setting the DBGEN input LOW.
49 Hard wiring the DBGEN input LOW permanently disables all debug functionality.
50 When DBGEN is LOW, it inhibits DBGDEWPT, DBGIEBKPT, and EDBGRQ to
51 the core, and DBGACK from the ARM9E-S core is always LOW.
56 When the ARM9E-S core is in debug state, you can examine the core and system state
57 by forcing the load and store multiples into the instruction pipeline.
58 Before you can examine the core and system state, the debugger must determine
59 whether the processor entered debug from Thumb state or ARM state, by examining
60 bit 4 of the EmbeddedICE-RT debug status register. If bit 4 is HIGH, the core has
61 entered debug from Thumb state.
62 For more details about determining the core state, see Determining the core and system
67 --- olimex - http://www.olimex.com/dev/pdf/arm-jtag.pdf
68 JTAG signals description:
69 PIN.1 (VTREF) Target voltage sense. Used to indicate the target’s operating voltage to thedebug tool.
70 PIN.2 (VTARGET) Target voltage. May be used to supply power to the debug tool.
71 PIN.3 (nTRST) JTAG TAP reset, this signal should be pulled up to Vcc in target board.
72 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.
73 *PIN.5 (TDI) JTAG serial data in, should be pulled up to Vcc on target board.
74 *PIN.7 (TMS) JTAG TAP Mode Select, should be pulled up to Vcc on target board.
75 *PIN.9 (TCK) JTAG clock.
76 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.
77 *PIN.13 (TDO) JTAG serial data out.
78 *PIN.15 (nSRST) Target system reset.
79 *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.
80 PIN.19 (DBGACK) Debug acknowledge. The ARM core acknowledges debug-mode inresponse to a DBGRQ input.
82 ****************************************************************/
85 /************************** JTAGARM7TDMI Primitives ****************************/
86 void jtag_goto_shift_ir() {
96 void jtag_goto_shift_dr() {
104 void jtag_reset_to_runtest_idle() {
110 jtag_arm_tcktock(); // now in Reset state
112 jtag_arm_tcktock(); // now in Run-Test/Idle state
115 void jtag_arm_tcktock() {
122 // ! Start JTAG, setup pins, reset TAP and return IDCODE
123 unsigned long jtagarm7tdmi_start() {
125 //Known-good starting position.
126 //Might be unnecessary.
132 //Entry sequence from Page 67 of SLAU265A for 4-wire JTAG
143 jtagarm7tdmi_resettap();
144 return jtagarm7tdmi_idcode();
148 //! Reset TAP State Machine
149 void jtagarm7tdmi_resettap(){ // PROVEN
151 jtag_reset_to_runtest_idle();
155 // NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR THE FUNCTIONAL EQUIVALENT
158 //! 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
159 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
161 unsigned long high = 1;
164 for (bit=(bitcount-1)/16; bit>0; bit--)
166 high <<= ((bitcount-1)%16);
171 for (bit = bitcount; bit > 0; bit--) {
172 /* write MOSI on trailing edge of previous clock */
180 SETTMS;//TMS high on last bit to exit.
184 /* read MISO on trailing edge */
190 for (bit=bitcount; bit>0; bit++) {
191 /* write MOSI on trailing edge of previous clock */
196 word = (word & mask) << 1;
199 SETTMS;//TMS high on last bit to exit.
203 /* read MISO on trailing edge */
222 /************************************************************************
223 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
226 * * Scan Chain Select Register (4 bits_lsb)
227 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
228 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
229 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
230 ************************************************************************/
234 /************************** Basic JTAG Verb Commands *******************************/
235 //! Grab the core ID.
236 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
237 jtagarm7tdmi_resettap();
239 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
241 return jtagarmtransn(0,32, LSB, END, RETIDLE);
244 //! Connect Bypass Register to TDO/TDI
245 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
246 jtagarm7tdmi_resettap();
248 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
250 //! INTEST verb - do internal test
251 unsigned char jtagarm7tdmi_intest() {
252 jtagarm7tdmi_resettap();
254 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
258 unsigned char jtagarm7tdmi_extest() {
259 jtagarm7tdmi_resettap();
261 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
265 //unsigned long jtagarm7tdmi_sample() {
266 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
267 // return jtagtransn(0,32);
271 unsigned char jtagarm7tdmi_restart() {
272 jtagarm7tdmi_resettap();
274 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
277 //! ARM7TDMI_IR_CLAMP 0x5
278 unsigned long jtagarm7tdmi_clamp() {
279 jtagarm7tdmi_resettap();
281 jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
283 return jtagarmtransn(0, 32, LSB, END, RETIDLE);
286 //! ARM7TDMI_IR_HIGHZ 0x7
287 unsigned char jtagarm7tdmi_highz() {
288 jtagarm7tdmi_resettap();
290 return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
293 //! define ARM7TDMI_IR_CLAMPZ 0x9
294 unsigned char jtagarm7tdmi_clampz() {
295 jtagarm7tdmi_resettap();
297 return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
301 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
302 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
304 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
305 wise, when in debug state, the core will not be correctly isolated and intrusive
306 commands occur. Therefore, it is recommended to pass directly from the “Update”
307 state” to the “Select DR” state each time the “Update” state is reached.
309 unsigned long retval;
310 if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
312 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
314 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
315 current_chain = chain;
317 retval = current_chain;
318 // put in test mode...
320 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
325 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
326 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
327 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
333 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
334 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
335 unsigned long retval;
336 jtagarm7tdmi_scan_intest(1);
338 // if the next instruction is to run using MCLK (master clock), set TDI
342 count_sysspd_instr_since_debug++;
347 count_dbgspd_instr_since_debug++;
352 // Now shift in the 32 bits
353 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
354 //jtag_arm_tcktock();
360 unsigned long jtagarm7tdmi_nop(char breakpt){
361 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
364 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
365 STR R0, [R0]; Save R0 before use
366 MOV R0, PC ; Copy PC into R0
367 STR R0, [R0]; Now save the PC in R0
368 BX PC ; Jump into ARM state
375 //! 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();
376 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
377 unsigned long retval = 0xff;
378 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
379 jtagarm7tdmi_scan_intest(1);
380 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
381 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
382 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
383 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
384 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
385 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
386 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
395 /************************* EmbeddedICE Primitives ****************************/
396 //! shifter for writing to chain2 (EmbeddedICE).
397 unsigned long eice_write(unsigned char reg, unsigned long data){
398 unsigned long retval, temp;
399 jtagarm7tdmi_scan_intest(2);
400 // Now shift in the 32 bits
402 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
403 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
404 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the WRITE bit
406 //SETTMS; // Last Bit - Exit UPDATE_DR
407 //// is this update a read/write or just read?
409 //jtag_arm_tcktock();
414 //! shifter for reading from chain2 (EmbeddedICE).
415 unsigned long eice_read(unsigned char reg){ // PROVEN
417 jtagarm7tdmi_scan_intest(2);
419 // send in the register address - 5 bits LSB
421 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
423 // clear TDI to select "read only"
424 jtagarmtransn(0, 1, LSB, END, RETIDLE);
427 // Now shift out the 32 bits
428 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
435 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
436 //! Grab debug register
437 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
438 return eice_read(EICE_DBGSTATUS);
441 //! Grab debug register
442 unsigned long jtagarm7tdmi_get_dbgctrl() {
443 return eice_read(EICE_DBGCTRL);
446 //! Update debug register
447 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
448 return eice_write(EICE_DBGCTRL, bits);
453 //! Set and Enable Watchpoint 0
454 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
455 // store watchpoint info? - not right now
458 // write 0 in watchpoint 0 address
459 eice_write(EICE_WP0ADDR, addr);
460 // write 0xffffffff in watchpoint 0 address mask
461 eice_write(EICE_WP0ADDRMASK, addrmask);
462 // write 0 in watchpoint 0 data
463 eice_write(EICE_WP0DATA, data);
464 // write 0xffffffff in watchpoint 0 data mask
465 eice_write(EICE_WP0DATAMASK, datamask);
466 // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
467 eice_write(EICE_WP0CTRL, ctrlmask);
468 // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
469 eice_write(EICE_WP0CTRLMASK, ctrlmask);
472 //! Set and Enable Watchpoint 1
473 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
474 // store watchpoint info? - not right now
477 // write 0 in watchpoint 1 address
478 eice_write(EICE_WP1ADDR, addr);
479 // write 0xffffffff in watchpoint 1 address mask
480 eice_write(EICE_WP1ADDRMASK, addrmask);
481 // write 0 in watchpoint 1 data
482 eice_write(EICE_WP1DATA, data);
483 // write 0xffffffff in watchpoint 1 data mask
484 eice_write(EICE_WP1DATAMASK, datamask);
485 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
486 eice_write(EICE_WP1CTRL, ctrl);
487 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
488 eice_write(EICE_WP1CTRLMASK, ctrlmask);
491 //! Disable Watchpoint 0
492 void jtagarm7tdmi_disable_watchpoint0(){
493 // write 0 in watchpoint 0 control value - disables watchpoint 0
494 eice_write(EICE_WP0CTRL, 0x0);
497 //! Disable Watchpoint 1
498 void jtagarm7tdmi_disable_watchpoint1(){
499 // write 0 in watchpoint 0 control value - disables watchpoint 0
500 eice_write(EICE_WP1CTRL, 0x0);
505 /******************** Complex Commands **************************/
506 //! Push an instruction into the CPU pipeline
507 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
508 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
509 unsigned long retval;
511 cmddatalong[1] = jtagarm7tdmi_nop( 0);
512 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
513 // write 32-bit instruction code into DR
514 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
515 cmddatalong[4] = jtagarm7tdmi_nop( 0);
516 cmddatalong[5] = jtagarm7tdmi_nop( 0);
518 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
519 cmddatalong[7] = jtagarm7tdmi_nop( 0);
520 cmddatalong[8] = jtagarm7tdmi_nop( 0);
521 cmddatalong[9] = jtagarm7tdmi_nop( 0);
522 retval = cmddatalong[9];
528 //! Push an instruction into the CPU pipeline
529 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
530 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
531 unsigned long retval;
533 cmddatalong[1] = jtagarm7tdmi_nop( 0);
534 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
535 // write 32-bit instruction code into DR
536 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
537 cmddatalong[4] = jtagarm7tdmi_nop( 0);
538 cmddatalong[5] = jtagarm7tdmi_nop( 0);
540 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
541 cmddatalong[7] = jtagarm7tdmi_nop( 0);
542 retval = jtagarm7tdmi_nop( 0);
543 cmddatalong[9] = jtagarm7tdmi_nop( 0);
544 cmddatalong[8] = retval;
549 //! Retrieve a 32-bit Register value
550 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
551 unsigned long retval = 0, instr;
552 // push nop into pipeline - clean out the pipeline...
553 cmddatalong[2] = jtagarm7tdmi_nop( 0);
555 // push STR_Rx, [R14] into pipeline
556 instr = ARM_INSTR_STR_Rx_r14 + ((reg<<12)&0xf00);
557 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
558 // push nop into pipeline - fetched
559 cmddatalong[2] = jtagarm7tdmi_nop( 0);
560 // push nop into pipeline - decoded
561 cmddatalong[3] = jtagarm7tdmi_nop( 0);
562 // push nop into pipeline - executed
563 cmddatalong[4] = jtagarm7tdmi_nop( 0);
564 // recover 32-bit word
565 //retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
566 retval = jtagarm7tdmi_nop( 0);
567 cmddatalong[5] = retval;
568 cmddatalong[6] = jtagarm7tdmi_nop( 0);
569 cmddatalong[7] = jtagarm7tdmi_nop( 0);
570 cmddatalong[8] = jtagarm7tdmi_nop( 0);
574 //! Set a 32-bit Register value
575 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
576 unsigned long retval = 0, instr;
577 // push nop into pipeline - clean out the pipeline...
578 cmddatalong[2] = jtagarm7tdmi_nop( 0);
580 // push STR_Rx, [R14] into pipeline
581 instr = ARM_INSTR_LDR_Rx_r14 + ((reg<<12)&0xf00);
582 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
583 // push nop into pipeline - fetched
584 cmddatalong[2] = jtagarm7tdmi_nop( 0);
585 // push nop into pipeline - decoded
586 cmddatalong[2] = jtagarm7tdmi_nop( 0);
588 // push 32-bit word on data bus - execute state
589 //retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
590 cmddatalong[3] = jtagarm7tdmi_instr_primitive(val, 0);
591 // push nop into pipeline - executed
592 cmddatalong[4] = jtagarm7tdmi_nop( 0);
593 if (reg == ARM_REG_PC){
594 cmddatalong[5] = jtagarm7tdmi_nop( 0);
595 cmddatalong[6] = jtagarm7tdmi_nop( 0);
597 retval = jtagarm7tdmi_nop( 0);
598 cmddatalong[7] = retval;
604 //! Get all registers. Return an array
605 unsigned long* jtagarm7tdmi_get_registers() {
606 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
607 cmddatalong[2] = jtagarm7tdmi_nop( 0);
608 cmddatalong[3] = jtagarm7tdmi_nop( 0);
609 cmddatalong[4] = jtagarm7tdmi_nop( 0);
610 cmddatalong[5] = jtagarm7tdmi_nop( 0);
611 cmddatalong[6] = jtagarm7tdmi_nop( 0);
612 cmddatalong[7] = jtagarm7tdmi_nop( 0);
613 cmddatalong[8] = jtagarm7tdmi_nop( 0);
614 cmddatalong[9] = jtagarm7tdmi_nop( 0);
615 cmddatalong[10] = jtagarm7tdmi_nop( 0);
616 cmddatalong[11] = jtagarm7tdmi_nop( 0);
617 cmddatalong[12] = jtagarm7tdmi_nop( 0);
618 cmddatalong[13] = jtagarm7tdmi_nop( 0);
619 cmddatalong[14] = jtagarm7tdmi_nop( 0);
620 cmddatalong[15] = jtagarm7tdmi_nop( 0);
621 cmddatalong[16] = jtagarm7tdmi_nop( 0);
622 cmddatalong[17] = jtagarm7tdmi_nop( 0);
623 cmddatalong[18] = jtagarm7tdmi_nop( 0);
624 cmddatalong[19] = jtagarm7tdmi_nop( 0);
625 cmddatalong[20] = jtagarm7tdmi_nop( 0);
629 //! Retrieve the CPSR Register value
630 unsigned long jtagarm7tdmi_get_regCPSR() {
631 unsigned long retval = 0;
633 // push nop into pipeline - clean out the pipeline...
634 cmddatalong[1] = jtagarm7tdmi_nop( 0);
635 // push MRS_R0, CPSR into pipeline
636 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0);
637 // push nop into pipeline - fetched
638 cmddatalong[3] = jtagarm7tdmi_nop( 0);
639 // push nop into pipeline - decoded
640 cmddatalong[4] = jtagarm7tdmi_nop( 0);
641 // push nop into pipeline - executed
642 cmddatalong[5] = jtagarm7tdmi_nop( 0);
643 // recover 32-bit word
644 retval = jtagarm7tdmi_nop( 0);
645 cmddatalong[6] = retval;
649 //! Retrieve the CPSR Register value
650 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
651 unsigned long retval = 0;
653 // push nop into pipeline - clean out the pipeline...
654 cmddatalong[1] = jtagarm7tdmi_nop( 0);
655 // push MSR cpsr_cxsf, R0 into pipeline
656 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0);
657 // push nop into pipeline - fetched
658 cmddatalong[2] = jtagarm7tdmi_nop( 0);
659 // push nop into pipeline - decoded
660 cmddatalong[3] = jtagarm7tdmi_nop( 0);
662 // push 32-bit word on data bus
663 retval = jtagarm7tdmi_instr_primitive(val, 0);
664 // push nop into pipeline - executed
665 cmddatalong[5] = jtagarm7tdmi_nop( 0);
666 cmddatalong[4] = retval;
670 //! Write data to address - Assume TAP in run-test/idle state
671 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
672 unsigned long r0=0, r1=-1;
675 r0 = jtagarm7tdmi_get_register(0);
676 r1 = jtagarm7tdmi_get_register(1);
677 // write address into R0
678 jtagarm7tdmi_set_register(0, adr);
680 jtagarm7tdmi_set_register(1, data);
681 //retval = jtagarm7tdmi_exec(ARM_INSTR_LDR_R1_r0_4,1);
682 // push nop into pipeline to "clean" it ???
683 jtagarm7tdmi_nop( 0);
684 // push nop into pipeline with BREAKPT set
685 jtagarm7tdmi_nop( 1);
686 // push LDR R1, R0, #4 into instruction pipeline
687 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
688 // push nop into pipeline
689 jtagarm7tdmi_nop( 0);
691 jtagarm7tdmi_set_register(1, r1);
692 jtagarm7tdmi_set_register(0, r0);
696 //! Read data from address
697 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
698 unsigned long retval = 0;
699 unsigned long r0=0, r1=-1;
700 int waitcount = 0xfff;
703 // store R0 and R1 - not yet...
704 r0 = jtagarm7tdmi_get_register(0);
705 r1 = jtagarm7tdmi_get_register(1);
706 // write address into R0
707 jtagarm7tdmi_set_register(0, adr);
708 // push nop into pipeline to "clean" it ???
709 jtagarm7tdmi_nop( 0);
710 // push nop into pipeline with BREAKPT set
711 jtagarm7tdmi_nop( 1);
712 // push LDR R1, R0, #4 into instruction pipeline
713 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
714 // push nop into pipeline
715 jtagarm7tdmi_nop( 0);
716 // SHIFT_IR with RESTART instruction
717 jtagarm7tdmi_restart();
718 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
719 while ((jtagarm7tdmi_get_dbgstate() & 1) == 0 && waitcount > 0){
723 if (waitcount == 0xffff){
726 retval = jtagarm7tdmi_get_register(1);
727 // read memory value from R1 register
729 jtagarm7tdmi_set_register(1, r1);
730 jtagarm7tdmi_set_register(0, r0);
736 //! Read Program Counter
737 unsigned long jtagarm7tdmi_getpc(){
738 return jtagarm7tdmi_get_register(ARM_REG_PC);
741 //! Set Program Counter
742 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
743 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
746 //! Halt CPU - returns 0xffff if the operation fails to complete within
747 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
748 int waitcount = 0xfff;
750 // store watchpoint info? - not right now
751 // write 0 in watchpoint 1 address
752 eice_write(EICE_WP1ADDR, 0);
753 // write 0xffffffff in watchpoint 1 address mask
754 eice_write(EICE_WP1ADDRMASK, 0xffffffff);
755 // write 0 in watchpoint 1 data
756 eice_write(EICE_WP1DATA, 0);
757 // write 0xffffffff in watchpoint 1 data mask
758 eice_write(EICE_WP1DATAMASK, 0xffffffff);
759 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
760 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!?
761 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
762 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!?
763 // poll until debug status says the cpu is in debug mode
764 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount > 0){
768 // write 0 in watchpoint 0 control value - disables watchpoint 0
769 eice_write(EICE_WP1CTRL, 0x0);
771 // store the debug state
772 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
773 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
774 count_dbgspd_instr_since_debug = 0;
775 count_sysspd_instr_since_debug = 0;
776 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
777 jtagarm7tdmi_setMode_ARM();
782 unsigned long jtagarm7tdmi_releasecpu(){
783 int waitcount = 0xfff;
785 // somehow determine what PC should be (a couple ways possible, calculations required)
791 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){ // FIXME: FORKED.
792 instr = ARM_INSTR_BX_PC + 0x1000000 - (count_dbgspd_instr_since_debug) - (count_sysspd_instr_since_debug*3); //FIXME: make this right - can't we just do an a7solute b/bx?
793 jtagarm7tdmi_instr_primitive(instr,0);
795 instr = ARM_INSTR_B_PC + 0x1000000 - (count_dbgspd_instr_since_debug) - (count_sysspd_instr_since_debug*3); //FIXME: make this right - can't we just do an absolute b/bx?
796 jtagarm7tdmi_instr_primitive(instr,0);
800 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE);
802 // wait until restart-bit set in debug state register
803 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
807 last_halt_debug_state = -1;
815 ///////////////////////////////////////////////////////////////////////////////////////////////////
816 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
817 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
818 register char blocks;
823 jtagarm7tdmi_resettap();
828 cmddatalong[0] = jtagarm7tdmi_start();
829 cmddatalong[2] = jtagarm7tdmi_haltcpu();
830 cmddatalong[1] = jtagarm7tdmi_get_dbgstate();
832 //jtagarm7tdmi_resettap();
833 txdata(app,verb,0xc);
835 case JTAGARM7TDMI_READMEM:
837 blocks=(len>4?cmddata[4]:1);
841 txhead(app,verb,len);
845 jtagarm7tdmi_resettap();
848 val=jtagarm7tdmi_readmem(at);
852 serial_tx((val&0xFF00)>>8);
857 case JTAGARM7TDMI_GET_CHIP_ID:
858 jtagarm7tdmi_resettap();
859 cmddatalong[0] = jtagarm7tdmi_idcode();
864 case JTAGARM7TDMI_WRITEMEM:
866 jtagarm7tdmi_resettap();
867 jtagarm7tdmi_writemem(cmddatalong[0],
869 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
873 case JTAGARM7TDMI_HALTCPU:
874 cmddatalong[0] = jtagarm7tdmi_haltcpu();
877 case JTAGARM7TDMI_RELEASECPU:
878 jtagarm7tdmi_resettap();
879 cmddatalong[0] = jtagarm7tdmi_releasecpu();
882 //unimplemented functions
883 //case JTAGARM7TDMI_SETINSTRFETCH:
884 //case JTAGARM7TDMI_WRITEFLASH:
885 //case JTAGARM7TDMI_ERASEFLASH:
886 case JTAGARM7TDMI_SET_PC:
887 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
890 case JTAGARM7TDMI_GET_DEBUG_CTRL:
891 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
894 case JTAGARM7TDMI_SET_DEBUG_CTRL:
895 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
898 case JTAGARM7TDMI_GET_PC:
899 cmddatalong[0] = jtagarm7tdmi_getpc();
902 case JTAGARM7TDMI_GET_DEBUG_STATE:
903 //jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
904 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
907 //case JTAGARM7TDMI_GET_WATCHPOINT:
908 //case JTAGARM7TDMI_SET_WATCHPOINT:
909 case JTAGARM7TDMI_GET_REGISTER:
910 jtagarm7tdmi_resettap();
911 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
914 case JTAGARM7TDMI_SET_REGISTER:
915 jtagarm7tdmi_resettap();
916 cmddatalong[0] = cmddatalong[1];
917 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
920 case JTAGARM7TDMI_GET_REGISTERS:
921 jtagarm7tdmi_resettap();
922 jtagarm7tdmi_get_registers();
925 //case JTAGARM7TDMI_SET_REGISTERS:
926 case JTAGARM7TDMI_DEBUG_INSTR:
927 jtagarm7tdmi_resettap();
928 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
931 case JTAGARM7TDMI_STEP_INSTR:
932 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
933 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
934 case JTAGARM7TDMI_READ_FLASH_PAGE:
935 case JTAGARM7TDMI_MASS_ERASE_FLASH:
936 case JTAGARM7TDMI_PROGRAM_FLASH:
937 case JTAGARM7TDMI_LOCKCHIP:
938 case JTAGARM7TDMI_CHIP_ERASE:
940 // Really ARM specific stuff
941 case JTAGARM7TDMI_GET_CPSR:
942 jtagarm7tdmi_resettap();
943 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
946 case JTAGARM7TDMI_SET_CPSR:
947 jtagarm7tdmi_resettap();
948 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
951 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
952 jtagarm7tdmi_resettap();
953 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
956 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
957 jtagarm7tdmi_resettap();
958 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
961 case JTAGARM7TDMI_SET_MODE_THUMB:
962 case JTAGARM7TDMI_SET_MODE_ARM:
963 jtagarm7tdmi_resettap();
964 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
968 case 0xD0: // loopback test
969 jtagarm7tdmi_resettap();
970 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
973 case 0xD8: // EICE_READ
974 jtagarm7tdmi_resettap();
975 cmddatalong[0] = eice_read(cmddatalong[0]);
978 case 0xD9: // EICE_WRITE
979 jtagarm7tdmi_resettap();
980 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
983 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
984 jtagarm7tdmi_resettap();
985 jtagarm7tdmi_scan_intest(0);
986 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
987 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
988 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
989 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
990 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
991 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
992 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
993 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
994 jtagarm7tdmi_resettap();
995 jtagarm7tdmi_scan_intest(1);
996 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
997 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
998 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
999 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1000 txdata(app,verb,48);
1004 jtaghandle(app,verb,len);