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() {
126 //Known-good starting position.
127 //Might be unnecessary.
133 //Entry sequence from Page 67 of SLAU265A for 4-wire JTAG
144 jtagarm7tdmi_resettap();
145 return jtagarm7tdmi_idcode();
149 //! Reset TAP State Machine
150 void jtagarm7tdmi_resettap(){ // PROVEN
151 debugstr("_resettap");
153 jtag_reset_to_runtest_idle();
156 //! 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
157 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
159 unsigned long high = 1;
163 for (bit=(bitcount-1)/16; bit>0; bit--)
165 high <<= ((bitcount-1)%16);
170 for (bit = bitcount; bit > 0; bit--) {
171 /* write MOSI on trailing edge of previous clock */
179 SETTMS;//TMS high on last bit to exit.
183 /* read MISO on trailing edge */
189 for (bit=bitcount; bit>0; bit++) {
190 /* write MOSI on trailing edge of previous clock */
195 word = (word & mask) << 1;
198 SETTMS;//TMS high on last bit to exit.
202 /* read MISO on trailing edge */
221 /************************************************************************
222 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
225 * * Scan Chain Select Register (4 bits_lsb)
226 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
227 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
228 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
229 ************************************************************************/
233 /************************** Basic JTAG Verb Commands *******************************/
234 //! Grab the core ID.
235 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
247 jtagarm7tdmi_resettap();
249 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
251 //! INTEST verb - do internal test
252 unsigned char jtagarm7tdmi_intest() {
254 jtagarm7tdmi_resettap();
256 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
260 unsigned char jtagarm7tdmi_extest() {
262 jtagarm7tdmi_resettap();
264 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
268 //unsigned long jtagarm7tdmi_sample() {
269 // debugstr("_sample");
270 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
271 // return jtagtransn(0,32);
275 unsigned char jtagarm7tdmi_restart() {
276 debugstr("_restart");
277 jtagarm7tdmi_resettap();
279 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
282 //! ARM7TDMI_IR_CLAMP 0x5
283 unsigned long jtagarm7tdmi_clamp() {
284 jtagarm7tdmi_resettap();
286 jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
288 return jtagarmtransn(0, 32, LSB, END, RETIDLE);
291 //! ARM7TDMI_IR_HIGHZ 0x7
292 unsigned char jtagarm7tdmi_highz() {
293 jtagarm7tdmi_resettap();
295 return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
298 //! define ARM7TDMI_IR_CLAMPZ 0x9
299 unsigned char jtagarm7tdmi_clampz() {
300 jtagarm7tdmi_resettap();
302 return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
306 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
307 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
310 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
311 wise, when in debug state, the core will not be correctly isolated and intrusive
312 commands occur. Therefore, it is recommended to pass directly from the “Update”
313 state” to the “Select DR” state each time the “Update” state is reached.
315 //jtagarm7tdmi_resettap(); // assume already sane?
316 if (current_chain == chain) {
320 unsigned long retval;
322 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
324 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
325 current_chain = chain;
326 // put in test mode...
328 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
330 current_chain = chain;
336 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
337 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
338 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
342 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
343 unsigned long jtagarm7tdmi_scan_extest(int chain) { // PROVEN
344 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_EXTEST);
349 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
350 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
351 unsigned long retval;
352 // TOTALLY TESTING: FIXME: THIS IS NOT AS IT WANTS TO BE
353 jtagarm7tdmi_scan_intest(1);
354 ////////////////////////////////////////////////////////
356 // if the next instruction is to run using MCLK (master clock), set TDI
360 count_sysspd_instr_since_debug++;
365 count_dbgspd_instr_since_debug++;
370 // Now shift in the 32 bits
371 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
372 //jtag_arm_tcktock();
377 //! push a NOP instruction into the pipeline
378 unsigned long jtagarm7tdmi_nop(char breakpt){
379 return jtagarm7tdmi_nop(breakpt);
383 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
384 STR R0, [R0]; Save R0 before use
385 MOV R0, PC ; Copy PC into R0
386 STR R0, [R0]; Now save the PC in R0
387 BX PC ; Jump into ARM state
394 //! 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();
395 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
396 unsigned long retval = 0xff;
397 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
398 jtagarm7tdmi_scan_intest(1);
399 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
400 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
401 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
402 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
403 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
404 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
413 /************************* EmbeddedICE Primitives ****************************/
414 //! shifter for writing to chain2 (EmbeddedICE).
415 unsigned long eice_write(unsigned char reg, unsigned long data){
416 unsigned long retval, temp;
417 jtagarm7tdmi_scan_intest(2);
418 // Now shift in the 32 bits
420 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
421 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
422 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the register address - 5 bits lsb
424 //SETTMS; // Last Bit - Exit UPDATE_DR
425 //// is this update a read/write or just read?
427 //jtag_arm_tcktock();
432 //! shifter for reading from chain2 (EmbeddedICE).
433 unsigned long eice_read(unsigned char reg){ // PROVEN
435 jtagarm7tdmi_scan_intest(2);
437 // send in the register address - 5 bits LSB
439 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
441 // clear TDI to select "read only"
442 jtagarmtransn(0, 1, LSB, END, RETIDLE);
445 // Now shift out the 32 bits
446 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
453 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
454 //! Grab debug register
455 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
456 //jtagarm7tdmi_resettap();
457 //jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST); // select ICEBreaker
458 return eice_read(EICE_DBGSTATUS);
461 //! Grab debug register
462 unsigned long jtagarm7tdmi_get_dbgctrl() {
463 //jtagarm7tdmi_resettap();
464 //jtagarm7tdmi_scan_intest(2); // select ICEBreaker
465 return eice_read(EICE_DBGCTRL);
468 //! Update debug register
469 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
470 //jtagarm7tdmi_resettap();
471 //jtagarm7tdmi_scan_intest(2); // select ICEBreaker
472 return eice_write(EICE_DBGCTRL, bits);
477 //! Set and Enable Watchpoint 0
478 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
480 jtagarm7tdmi_scan_intest(2);
481 // store watchpoint info? - not right now
482 // write 0 in watchpoint 0 address
483 eice_write(EICE_WP0ADDR, addr);
484 // write 0xffffffff in watchpoint 0 address mask
485 eice_write(EICE_WP0ADDRMASK, addrmask);
486 // write 0 in watchpoint 0 data
487 eice_write(EICE_WP0DATA, data);
488 // write 0xffffffff in watchpoint 0 data mask
489 eice_write(EICE_WP0DATAMASK, datamask);
490 // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
491 eice_write(EICE_WP0CTRL, ctrlmask);
492 // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
493 eice_write(EICE_WP0CTRLMASK, ctrlmask);
496 //! Set and Enable Watchpoint 1
497 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
499 //jtagarm7tdmi_scan_intest(2);
500 // store watchpoint info? - not right now
501 // write 0 in watchpoint 1 address
502 eice_write(EICE_WP1ADDR, addr);
503 // write 0xffffffff in watchpoint 1 address mask
504 eice_write(EICE_WP1ADDRMASK, addrmask);
505 // write 0 in watchpoint 1 data
506 eice_write(EICE_WP1DATA, data);
507 // write 0xffffffff in watchpoint 1 data mask
508 eice_write(EICE_WP1DATAMASK, datamask);
509 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
510 eice_write(EICE_WP1CTRL, ctrl);
511 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
512 eice_write(EICE_WP1CTRLMASK, ctrlmask);
515 //! Disable Watchpoint 0
516 void jtagarm7tdmi_disable_watchpoint0(){
518 //jtagarm7tdmi_scan_intest(2);
519 // write 0 in watchpoint 0 control value - disables watchpoint 0
520 eice_write(EICE_WP0CTRL, 0x0);
523 //! Disable Watchpoint 1
524 void jtagarm7tdmi_disable_watchpoint1(){
526 //jtagarm7tdmi_scan_intest(2);
527 // write 0 in watchpoint 0 control value - disables watchpoint 0
528 eice_write(EICE_WP1CTRL, 0x0);
533 /******************** Complex Commands **************************/
534 //! Push an instruction into the CPU pipeline
535 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
536 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
537 unsigned long retval;
539 //jtagarm7tdmi_scan_intest(1);
541 cmddatalong[1] = jtagarm7tdmi_nop(0);
542 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
543 // write 32-bit instruction code into DR
544 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
545 cmddatalong[4] = jtagarm7tdmi_nop(0);
546 cmddatalong[5] = jtagarm7tdmi_nop(0);
548 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
549 cmddatalong[7] = jtagarm7tdmi_nop(0);
550 cmddatalong[8] = jtagarm7tdmi_nop(0);
551 cmddatalong[9] = jtagarm7tdmi_nop(0);
552 retval = cmddatalong[9];
558 //! Push an instruction into the CPU pipeline
559 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
560 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
561 unsigned long retval;
563 //jtagarm7tdmi_scan_intest(1);
565 cmddatalong[1] = jtagarm7tdmi_nop(0);
566 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
567 // write 32-bit instruction code into DR
568 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
569 cmddatalong[4] = jtagarm7tdmi_nop(0);
570 cmddatalong[5] = jtagarm7tdmi_nop(0);
572 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
573 retval = jtagarm7tdmi_nop(0);
574 cmddatalong[8] = jtagarm7tdmi_nop(0);
575 cmddatalong[9] = jtagarm7tdmi_nop(0);
576 cmddatalong[7] = retval;
581 //! Retrieve a 32-bit Register value
582 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
583 unsigned long retval = 0, instr;
584 //JTAGARM7TDMI_RESETTAP();
585 // select chain 1, automatically put in INTEST
586 //jtagarm7tdmi_scan_intest(1);
587 instr = ARM_INSTR_STR_Rx_r14 + ((reg<<12)&0xf00);
588 //retval = jtagarm7tdmi_exec(instr, 0);
589 // push STR_Rx, [R14] into pipeline
590 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
591 // push nop into pipeline - fetched
592 cmddatalong[2] = jtagarm7tdmi_nop(0);
593 // push nop into pipeline - decoded
594 cmddatalong[3] = jtagarm7tdmi_nop(0);
595 // push nop into pipeline - executed
596 cmddatalong[4] = jtagarm7tdmi_nop(0);
597 // recover 32-bit word
598 //retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
599 retval = jtagarm7tdmi_nop(0);
600 cmddatalong[5] = retval;
601 cmddatalong[6] = jtagarm7tdmi_nop(0);
602 cmddatalong[7] = jtagarm7tdmi_nop(0);
603 cmddatalong[8] = jtagarm7tdmi_nop(0);
607 //! Set a 32-bit Register value
608 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
609 unsigned long retval = 0, instr;
610 //jtagarm7tdmi_resettap();
612 //jtagarm7tdmi_scan_intest(1);
613 instr = ARM_INSTR_LDR_Rx_r14 + ((reg<<12)&0xf00);
614 //retval = jtagarm7tdmi_exec(instr, 0);
615 // push STR_Rx, [R14] into pipeline
616 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
617 // push nop into pipeline - fetched
618 cmddatalong[2] = jtagarm7tdmi_nop(0);
619 // push nop into pipeline - decoded
620 cmddatalong[2] = jtagarm7tdmi_nop(0);
622 // push 32-bit word on data bus - execute state
623 //retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
624 cmddatalong[3] = jtagarm7tdmi_instr_primitive(val, 0);
625 // push nop into pipeline - executed
626 cmddatalong[4] = jtagarm7tdmi_nop(0);
627 if (reg == ARM_REG_PC){
628 cmddatalong[5] = jtagarm7tdmi_nop(0);
629 cmddatalong[6] = jtagarm7tdmi_nop(0);
631 retval = jtagarm7tdmi_nop(0);
632 cmddatalong[7] = retval;
638 //! Get all registers. Return an array
639 unsigned long* jtagarm7tdmi_get_registers() {
640 //jtagarm7tdmi_scan_intest(1);
641 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
642 cmddatalong[2] = jtagarm7tdmi_nop(0);
643 cmddatalong[3] = jtagarm7tdmi_nop(0);
644 cmddatalong[4] = jtagarm7tdmi_nop(0);
645 cmddatalong[5] = jtagarm7tdmi_nop(0);
646 cmddatalong[6] = jtagarm7tdmi_nop(0);
647 cmddatalong[7] = jtagarm7tdmi_nop(0);
648 cmddatalong[8] = jtagarm7tdmi_nop(0);
649 cmddatalong[9] = jtagarm7tdmi_nop(0);
650 cmddatalong[10] = jtagarm7tdmi_nop(0);
651 cmddatalong[11] = jtagarm7tdmi_nop(0);
652 cmddatalong[12] = jtagarm7tdmi_nop(0);
653 cmddatalong[13] = jtagarm7tdmi_nop(0);
654 cmddatalong[14] = jtagarm7tdmi_nop(0);
655 cmddatalong[15] = jtagarm7tdmi_nop(0);
656 cmddatalong[16] = jtagarm7tdmi_nop(0);
657 cmddatalong[17] = jtagarm7tdmi_nop(0);
658 cmddatalong[18] = jtagarm7tdmi_nop(0);
659 cmddatalong[19] = jtagarm7tdmi_nop(0);
660 cmddatalong[20] = jtagarm7tdmi_nop(0);
664 //! Retrieve the CPSR Register value
665 unsigned long jtagarm7tdmi_get_regCPSR() {
666 unsigned long retval = 0;
668 //cmddatalong[1] = jtagarm7tdmi_scan_intest(1);
670 // push STR_Rx, [R14] into pipeline
671 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0);
672 // push nop into pipeline - fetched
673 cmddatalong[2] = jtagarm7tdmi_nop(0);
674 // push nop into pipeline - decoded
675 cmddatalong[3] = jtagarm7tdmi_nop(0);
676 // push nop into pipeline - executed
677 cmddatalong[4] = jtagarm7tdmi_nop(0);
678 // recover 32-bit word
679 retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
680 cmddatalong[5] = retval;
684 //! Retrieve the CPSR Register value
685 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
686 unsigned long retval = 0;
688 //jtagarm7tdmi_scan_intest(1);
690 // push MSR cpsr_cxsf, R0 into pipeline
691 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0);
692 // push nop into pipeline - fetched
693 cmddatalong[2] = jtagarm7tdmi_nop(0);
694 // push nop into pipeline - decoded
695 cmddatalong[3] = jtagarm7tdmi_nop(0);
697 // push 32-bit word on data bus
698 retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
699 // push nop into pipeline - executed
700 cmddatalong[5] = jtagarm7tdmi_nop(0);
701 cmddatalong[4] = retval;
705 //! Write data to address - Assume TAP in run-test/idle state
706 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
707 unsigned long r0=0, r1=-1;
709 //jtagarm7tdmi_scan_intest(1);
712 r0 = jtagarm7tdmi_get_register(0);
713 r1 = jtagarm7tdmi_get_register(1);
714 // write address into R0
715 jtagarm7tdmi_set_register(0, adr);
717 jtagarm7tdmi_set_register(1, data);
718 //retval = jtagarm7tdmi_exec(ARM_INSTR_LDR_R1_r0_4,1);
719 // push nop into pipeline to "clean" it ???
721 // push nop into pipeline with BREAKPT set
723 // push LDR R1, R0, #4 into instruction pipeline
724 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
725 // push nop into pipeline
728 jtagarm7tdmi_set_register(1, r1);
729 jtagarm7tdmi_set_register(0, r0);
733 //! Read data from address
734 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
735 unsigned long retval = 0;
736 unsigned long r0=0, r1=-1;
737 int waitcount = 0xfff;
739 //jtagarm7tdmi_scan_intest(1);
742 // store R0 and R1 - not yet...
743 r0 = jtagarm7tdmi_get_register(0);
744 r1 = jtagarm7tdmi_get_register(1);
745 // write address into R0
746 jtagarm7tdmi_set_register(0, adr);
747 // push nop into pipeline to "clean" it ???
749 // push nop into pipeline with BREAKPT set
751 // push LDR R1, R0, #4 into instruction pipeline
752 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
753 // push nop into pipeline
755 // SHIFT_IR with RESTART instruction
756 jtagarm7tdmi_restart();
757 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
758 while ((jtagarm7tdmi_get_dbgstate() & 1) == 0 && waitcount > 0){
762 if (waitcount == 0xffff){
765 retval = jtagarm7tdmi_get_register(1);
766 // read memory value from R1 register
768 jtagarm7tdmi_set_register(1, r1);
769 jtagarm7tdmi_set_register(0, r0);
775 //! Read Program Counter
776 unsigned long jtagarm7tdmi_getpc(){
777 return jtagarm7tdmi_get_register(ARM_REG_PC);
780 //! Set Program Counter
781 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
782 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
785 //! Halt CPU - returns 0xffff if the operation fails to complete within
786 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
787 int waitcount = 0xfff;
789 jtagarm7tdmi_scan_intest(2);
790 // store watchpoint info? - not right now
791 // write 0 in watchpoint 1 address
792 eice_write(EICE_WP1ADDR, 0);
793 // write 0xffffffff in watchpoint 1 address mask
794 eice_write(EICE_WP1ADDRMASK, 0xffffffff);
795 // write 0 in watchpoint 1 data
796 eice_write(EICE_WP1DATA, 0);
797 // write 0xffffffff in watchpoint 1 data mask
798 eice_write(EICE_WP1DATAMASK, 0xffffffff);
799 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
800 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!?
801 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
802 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!?
803 // poll until debug status says the cpu is in debug mode
804 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount > 0){
808 // write 0 in watchpoint 0 control value - disables watchpoint 0
809 eice_write(EICE_WP1CTRL, 0x0);
811 // store the debug state
812 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
813 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
814 count_dbgspd_instr_since_debug = 0;
815 count_sysspd_instr_since_debug = 0;
816 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
817 jtagarm7tdmi_setMode_ARM();
822 unsigned long jtagarm7tdmi_releasecpu(){
823 int waitcount = 0xfff;
825 // somehow determine what PC should be (a couple ways possible, calculations required)
826 //jtagarm7tdmi_scan_intest(1);
832 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
833 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?
834 jtagarm7tdmi_instr_primitive(instr,0);
836 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?
837 jtagarm7tdmi_instr_primitive(instr,0);
841 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE);
843 // wait until restart-bit set in debug state register
844 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
848 last_halt_debug_state = -1;
867 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
868 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
869 register char blocks;
874 jtagarm7tdmi_resettap();
875 debugstr("Classic ARM JTAG handler.");
881 cmddatalong[0] = jtagarm7tdmi_start();
882 cmddatalong[1] = jtagarm7tdmi_haltcpu();
883 //jtagarm7tdmi_resettap();
884 txdata(app,verb,0x8);
886 case JTAGARM7TDMI_READMEM:
888 blocks=(len>4?cmddata[4]:1);
892 txhead(app,verb,len);
896 jtagarm7tdmi_resettap();
899 val=jtagarm7tdmi_readmem(at);
903 serial_tx((val&0xFF00)>>8);
908 case JTAGARM7TDMI_GET_CHIP_ID:
909 jtagarm7tdmi_resettap();
910 cmddatalong[0] = jtagarm7tdmi_idcode();
916 case JTAGARM7TDMI_WRITEMEM:
918 jtagarm7tdmi_resettap();
919 jtagarm7tdmi_writemem(cmddatalong[0],
921 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
925 case JTAGARM7TDMI_HALTCPU:
926 cmddatalong[0] = jtagarm7tdmi_haltcpu();
929 case JTAGARM7TDMI_RELEASECPU:
930 jtagarm7tdmi_resettap();
931 cmddatalong[0] = jtagarm7tdmi_releasecpu();
934 //unimplemented functions
935 //case JTAGARM7TDMI_SETINSTRFETCH:
936 //case JTAGARM7TDMI_WRITEFLASH:
937 //case JTAGARM7TDMI_ERASEFLASH:
938 case JTAGARM7TDMI_SET_PC:
939 jtagarm7tdmi_resettap();
940 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
943 case JTAGARM7TDMI_GET_DEBUG_CTRL:
944 jtagarm7tdmi_resettap();
945 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
948 case JTAGARM7TDMI_SET_DEBUG_CTRL:
949 jtagarm7tdmi_resettap();
950 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
953 case JTAGARM7TDMI_GET_PC:
954 jtagarm7tdmi_resettap();
955 cmddatalong[0] = jtagarm7tdmi_getpc();
958 case JTAGARM7TDMI_GET_DEBUG_STATE:
959 jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
960 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
963 //case JTAGARM7TDMI_GET_WATCHPOINT:
964 //case JTAGARM7TDMI_SET_WATCHPOINT:
965 case JTAGARM7TDMI_GET_REGISTER:
966 jtagarm7tdmi_resettap();
967 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
970 case JTAGARM7TDMI_SET_REGISTER:
971 jtagarm7tdmi_resettap();
972 cmddatalong[0] = cmddatalong[1];
973 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
976 case JTAGARM7TDMI_GET_REGISTERS:
977 jtagarm7tdmi_resettap();
978 jtagarm7tdmi_get_registers();
981 //case JTAGARM7TDMI_SET_REGISTERS:
982 case JTAGARM7TDMI_DEBUG_INSTR:
983 jtagarm7tdmi_resettap();
984 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
987 case JTAGARM7TDMI_STEP_INSTR:
988 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
989 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
990 case JTAGARM7TDMI_READ_FLASH_PAGE:
991 case JTAGARM7TDMI_MASS_ERASE_FLASH:
992 case JTAGARM7TDMI_PROGRAM_FLASH:
993 case JTAGARM7TDMI_LOCKCHIP:
994 case JTAGARM7TDMI_CHIP_ERASE:
996 // Really ARM specific stuff
997 case JTAGARM7TDMI_GET_CPSR:
998 jtagarm7tdmi_resettap();
999 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
1002 case JTAGARM7TDMI_SET_CPSR:
1003 jtagarm7tdmi_resettap();
1004 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
1007 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
1008 jtagarm7tdmi_resettap();
1009 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
1012 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
1013 jtagarm7tdmi_resettap();
1014 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
1017 case JTAGARM7TDMI_SET_MODE_THUMB:
1018 case JTAGARM7TDMI_SET_MODE_ARM:
1019 jtagarm7tdmi_resettap();
1020 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
1024 case 0xD0: // loopback test
1025 jtagarm7tdmi_resettap();
1026 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
1029 case 0xD1: // Set Scan Chain
1030 jtagarm7tdmi_resettap();
1031 cmddatalong[0] = test_exec(cmddatalong[0], EXECNOPARM, 0);
1032 txdata(app,verb,52);
1034 case 0xD3: // EXECUTE
1035 jtagarm7tdmi_resettap();
1036 //cmddatalong[0] = jtagarm7tdmi_exec(cmddatalong[0], EXECNOPARM, 0);
1037 cmddatalong[0] = test_exec(cmddatalong[0], EXECNOPARM, 0);
1038 txdata(app,verb,52);
1040 case 0xD4: // GET REGISTER
1041 jtagarm7tdmi_resettap();
1042 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
1043 txdata(app,verb,40);
1045 case 0xD5: // SET REGISTER
1046 jtagarm7tdmi_resettap();
1047 cmddatalong[0] = jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
1048 txdata(app,verb,40);
1050 case 0xD6: // SHIFT_DR
1052 cmddatalong[0] = jtagarmtransn(cmddatalong[0], 32, LSB, END, RETIDLE);
1055 case 0xD7: // INSTR_PRIMITIVE
1056 jtagarm7tdmi_resettap();
1058 jtagarm7tdmi_scan_intest(1);
1059 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0], 0);
1062 case 0xD8: // EICE_READ
1063 jtagarm7tdmi_resettap();
1064 cmddatalong[0] = eice_read(cmddatalong[0]);
1067 case 0xD9: // EICE_WRITE
1068 jtagarm7tdmi_resettap();
1069 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
1072 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
1073 jtagarm7tdmi_resettap();
1074 jtagarm7tdmi_scan_intest(0);
1075 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
1076 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
1077 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
1078 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
1079 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
1080 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
1081 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
1082 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
1083 jtagarm7tdmi_resettap();
1084 jtagarm7tdmi_scan_intest(1);
1085 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
1086 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
1087 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
1088 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1089 txdata(app,verb,48);
1093 jtaghandle(app,verb,len);