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 ********************************/
37 /****************************************************************
38 Enabling jtag likely differs with most platforms. We will attempt to enable most from here. Override jtagarm7tdmi_start() to extend for other implementations
39 ARM7TDMI enables three different scan chains:
40 * Chain0 - "entire periphery" including data bus
41 * Chain1 - core data bus (subset of Chain0) - Instruction Pipeline
42 * Chain2 - EmbeddedICE Logic Registers - This is our way into the fun stuff.
46 You can disable EmbeddedICE-RT by setting the DBGEN input LOW.
48 Hard wiring the DBGEN input LOW permanently disables all debug functionality.
49 When DBGEN is LOW, it inhibits DBGDEWPT, DBGIEBKPT, and EDBGRQ to
50 the core, and DBGACK from the ARM9E-S core is always LOW.
55 When the ARM9E-S core is in debug state, you can examine the core and system state
56 by forcing the load and store multiples into the instruction pipeline.
57 Before you can examine the core and system state, the debugger must determine
58 whether the processor entered debug from Thumb state or ARM state, by examining
59 bit 4 of the EmbeddedICE-RT debug status register. If bit 4 is HIGH, the core has
60 entered debug from Thumb state.
61 For more details about determining the core state, see Determining the core and system
66 --- olimex - http://www.olimex.com/dev/pdf/arm-jtag.pdf
67 JTAG signals description:
68 PIN.1 (VTREF) Target voltage sense. Used to indicate the target’s operating voltage to thedebug tool.
69 PIN.2 (VTARGET) Target voltage. May be used to supply power to the debug tool.
70 PIN.3 (nTRST) JTAG TAP reset, this signal should be pulled up to Vcc in target board.
71 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.
72 *PIN.5 (TDI) JTAG serial data in, should be pulled up to Vcc on target board.
73 *PIN.7 (TMS) JTAG TAP Mode Select, should be pulled up to Vcc on target board.
74 *PIN.9 (TCK) JTAG clock.
75 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.
76 *PIN.13 (TDO) JTAG serial data out.
77 *PIN.15 (nSRST) Target system reset.
78 *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.
79 PIN.19 (DBGACK) Debug acknowledge. The ARM core acknowledges debug-mode inresponse to a DBGRQ input.
81 ****************************************************************/
84 /************************** JTAGARM7TDMI Primitives ****************************/
85 void jtag_goto_shift_ir() {
95 void jtag_goto_shift_dr() {
103 void jtag_reset_to_runtest_idle() {
109 jtag_arm_tcktock(); // now in Reset state
111 jtag_arm_tcktock(); // now in Run-Test/Idle state
114 void jtag_arm_tcktock() {
121 // ! Start JTAG, setup pins, reset TAP and return IDCODE
122 unsigned long jtagarm7tdmi_start() {
124 //Known-good starting position.
125 //Might be unnecessary.
131 //Entry sequence from Page 67 of SLAU265A for 4-wire JTAG
142 jtagarm7tdmi_resettap();
143 return jtagarm7tdmi_idcode();
147 //! Reset TAP State Machine
148 void jtagarm7tdmi_resettap(){ // PROVEN
150 jtag_reset_to_runtest_idle();
154 // NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR THE FUNCTIONAL EQUIVALENT
157 //! 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
158 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
160 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 */
224 /************************************************************************
225 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
228 * * Scan Chain Select Register (4 bits_lsb)
229 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
230 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
231 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
232 ************************************************************************/
236 /************************** Basic JTAG Verb Commands *******************************/
237 //! Grab the core ID.
238 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
239 jtagarm7tdmi_resettap();
241 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
243 return jtagarmtransn(0,32, LSB, END, RETIDLE);
246 //! Connect Bypass Register to TDO/TDI
247 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
248 jtagarm7tdmi_resettap();
250 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
252 //! INTEST verb - do internal test
253 unsigned char jtagarm7tdmi_intest() {
254 jtagarm7tdmi_resettap();
256 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
260 unsigned char jtagarm7tdmi_extest() {
261 jtagarm7tdmi_resettap();
263 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
267 //unsigned long jtagarm7tdmi_sample() {
268 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
269 // return jtagtransn(0,32);
273 unsigned char jtagarm7tdmi_restart() {
274 jtagarm7tdmi_resettap();
276 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
279 //! ARM7TDMI_IR_CLAMP 0x5
280 //unsigned long jtagarm7tdmi_clamp() {
281 // jtagarm7tdmi_resettap();
283 // jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
285 // return jtagarmtransn(0, 32, LSB, END, RETIDLE);
288 //! ARM7TDMI_IR_HIGHZ 0x7
289 //unsigned char jtagarm7tdmi_highz() {
290 // jtagarm7tdmi_resettap();
292 // return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
295 //! define ARM7TDMI_IR_CLAMPZ 0x9
296 //unsigned char jtagarm7tdmi_clampz() {
297 // jtagarm7tdmi_resettap();
299 // return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
303 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
304 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
306 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
307 wise, when in debug state, the core will not be correctly isolated and intrusive
308 commands occur. Therefore, it is recommended to pass directly from the “Update”
309 state” to the “Select DR” state each time the “Update” state is reached.
311 unsigned long retval;
312 if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
314 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
316 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
317 current_chain = chain;
319 retval = current_chain;
320 // put in test mode...
322 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
327 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
328 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
329 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
335 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
336 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
337 unsigned long retval;
338 jtagarm7tdmi_scan_intest(1);
341 // if the next instruction is to run using MCLK (master clock), set TDI
345 count_sysspd_instr_since_debug++;
350 count_dbgspd_instr_since_debug++;
354 // Now shift in the 32 bits
355 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
356 //jtag_arm_tcktock();
362 unsigned long jtagarm7tdmi_nop(char breakpt){
363 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
366 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
367 STR R0, [R0]; Save R0 before use
368 MOV R0, PC ; Copy PC into R0
369 STR R0, [R0]; Now save the PC in R0
370 BX PC ; Jump into ARM state
377 //! 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();
378 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
379 unsigned long retval = 0xff;
380 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
381 jtagarm7tdmi_scan_intest(1);
382 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
383 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
384 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
385 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
386 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
387 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
388 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
397 /************************* EmbeddedICE Primitives ****************************/
398 //! shifter for writing to chain2 (EmbeddedICE).
399 unsigned long eice_write(unsigned char reg, unsigned long data){
400 unsigned long retval, temp;
401 jtagarm7tdmi_scan_intest(2);
402 // Now shift in the 32 bits
404 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
405 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
406 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the WRITE bit
408 //SETTMS; // Last Bit - Exit UPDATE_DR
409 //// is this update a read/write or just read?
411 //jtag_arm_tcktock();
416 //! shifter for reading from chain2 (EmbeddedICE).
417 unsigned long eice_read(unsigned char reg){ // PROVEN
419 jtagarm7tdmi_scan_intest(2);
421 // send in the register address - 5 bits LSB
423 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
425 // clear TDI to select "read only"
426 jtagarmtransn(0, 1, LSB, END, RETIDLE);
429 // Now shift out the 32 bits
430 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
437 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
438 //! Grab debug register
439 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
440 //jtagarm7tdmi_resettap();
441 return eice_read(EICE_DBGSTATUS);
444 //! Grab debug register
445 unsigned long jtagarm7tdmi_get_dbgctrl() {
446 return eice_read(EICE_DBGCTRL);
449 //! Update debug register
450 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
451 return eice_write(EICE_DBGCTRL, bits);
456 //! Set and Enable Watchpoint 0
457 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
458 // store watchpoint info? - not right now
461 eice_write(EICE_WP0ADDR, addr); // write 0 in watchpoint 0 address
462 eice_write(EICE_WP0ADDRMASK, addrmask); // write 0xffffffff in watchpoint 0 address mask
463 eice_write(EICE_WP0DATA, data); // write 0 in watchpoint 0 data
464 eice_write(EICE_WP0DATAMASK, datamask); // write 0xffffffff in watchpoint 0 data mask
465 eice_write(EICE_WP0CTRL, ctrlmask); // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
466 eice_write(EICE_WP0CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
469 //! Set and Enable Watchpoint 1
470 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
471 // store watchpoint info? - not right now
474 eice_write(EICE_WP1ADDR, addr); // write 0 in watchpoint 1 address
475 eice_write(EICE_WP1ADDRMASK, addrmask); // write 0xffffffff in watchpoint 1 address mask
476 eice_write(EICE_WP1DATA, data); // write 0 in watchpoint 1 data
477 eice_write(EICE_WP1DATAMASK, datamask); // write 0xffffffff in watchpoint 1 data mask
478 eice_write(EICE_WP1CTRL, ctrl); // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
479 eice_write(EICE_WP1CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
482 //! Disable Watchpoint 0
483 void jtagarm7tdmi_disable_watchpoint0(){
484 eice_write(EICE_WP0CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
487 //! Disable Watchpoint 1
488 void jtagarm7tdmi_disable_watchpoint1(){
489 eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
494 /******************** Complex Commands **************************/
495 //! Push an instruction into the CPU pipeline
496 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
497 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
498 unsigned long retval;
500 cmddatalong[1] = jtagarm7tdmi_nop( 0);
501 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
502 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
503 cmddatalong[4] = jtagarm7tdmi_nop( 0);
504 cmddatalong[5] = jtagarm7tdmi_nop( 0);
505 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
506 cmddatalong[7] = jtagarm7tdmi_nop( 0);
507 cmddatalong[8] = jtagarm7tdmi_nop( 0);
508 cmddatalong[9] = jtagarm7tdmi_nop( 0);
509 retval = cmddatalong[9];
515 //! Push an instruction into the CPU pipeline
516 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
517 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
518 unsigned long retval;
520 cmddatalong[1] = jtagarm7tdmi_nop( 0);
521 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
522 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
523 cmddatalong[4] = jtagarm7tdmi_nop( 0);
524 cmddatalong[5] = jtagarm7tdmi_nop( 0);
525 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
526 cmddatalong[7] = jtagarm7tdmi_nop( 0);
527 retval = jtagarm7tdmi_nop( 0);
528 cmddatalong[9] = jtagarm7tdmi_nop( 0);
529 cmddatalong[8] = retval;
534 //! Retrieve a 32-bit Register value
535 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
536 unsigned long retval = 0, instr;
537 // push nop into pipeline - clean out the pipeline...
538 cmddatalong[2] = jtagarm7tdmi_nop( 0);
540 instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
541 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
542 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
543 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
544 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
545 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
546 cmddatalong[5] = retval;
547 cmddatalong[6] = jtagarm7tdmi_nop( 0);
548 cmddatalong[7] = jtagarm7tdmi_nop( 0);
549 cmddatalong[8] = jtagarm7tdmi_nop( 0);
553 //! Set a 32-bit Register value
554 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
555 unsigned long retval = 0, instr;
556 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
558 instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
559 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
560 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
561 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
563 cmddatalong[4] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus - execute state
564 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
566 if (reg == ARM_REG_PC){
567 cmddatalong[6] = jtagarm7tdmi_nop( 0);
568 cmddatalong[7] = jtagarm7tdmi_nop( 0);
570 cmddatalong[8] = jtagarm7tdmi_nop( 0);
572 retval = cmddatalong[5];
578 //! Get all registers. Return an array
579 unsigned long* jtagarm7tdmi_get_registers() {
580 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
581 cmddatalong[2] = jtagarm7tdmi_nop( 0);
582 cmddatalong[3] = jtagarm7tdmi_nop( 0);
583 cmddatalong[4] = jtagarm7tdmi_nop( 0);
584 cmddatalong[5] = jtagarm7tdmi_nop( 0);
585 cmddatalong[6] = jtagarm7tdmi_nop( 0);
586 cmddatalong[7] = jtagarm7tdmi_nop( 0);
587 cmddatalong[8] = jtagarm7tdmi_nop( 0);
588 cmddatalong[9] = jtagarm7tdmi_nop( 0);
589 cmddatalong[10] = jtagarm7tdmi_nop( 0);
590 cmddatalong[11] = jtagarm7tdmi_nop( 0);
591 cmddatalong[12] = jtagarm7tdmi_nop( 0);
592 cmddatalong[13] = jtagarm7tdmi_nop( 0);
593 cmddatalong[14] = jtagarm7tdmi_nop( 0);
594 cmddatalong[15] = jtagarm7tdmi_nop( 0);
595 cmddatalong[16] = jtagarm7tdmi_nop( 0);
596 cmddatalong[17] = jtagarm7tdmi_nop( 0);
597 cmddatalong[18] = jtagarm7tdmi_nop( 0);
598 cmddatalong[19] = jtagarm7tdmi_nop( 0);
599 cmddatalong[20] = jtagarm7tdmi_nop( 0);
603 //! Retrieve the CPSR Register value
604 unsigned long jtagarm7tdmi_get_regCPSR() {
605 unsigned long retval = 0;
607 // push nop into pipeline - clean out the pipeline...
608 cmddatalong[1] = jtagarm7tdmi_nop( 0);
609 // push MRS_R0, CPSR into pipeline
610 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0);
611 // push nop into pipeline - fetched
612 cmddatalong[3] = jtagarm7tdmi_nop( 0);
613 // push nop into pipeline - decoded
614 cmddatalong[4] = jtagarm7tdmi_nop( 0);
615 // push nop into pipeline - executed
616 cmddatalong[5] = jtagarm7tdmi_nop( 0);
617 // recover 32-bit word
618 retval = jtagarm7tdmi_nop( 0);
619 cmddatalong[6] = retval;
623 //! Retrieve the CPSR Register value
624 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
625 unsigned long retval = 0;
627 // push nop into pipeline - clean out the pipeline...
628 cmddatalong[1] = jtagarm7tdmi_nop( 0);
629 // push MSR cpsr_cxsf, R0 into pipeline
630 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0);
631 // push nop into pipeline - fetched
632 cmddatalong[2] = jtagarm7tdmi_nop( 0);
633 // push nop into pipeline - decoded
634 cmddatalong[3] = jtagarm7tdmi_nop( 0);
636 // push 32-bit word on data bus
637 retval = jtagarm7tdmi_instr_primitive(val, 0);
638 // push nop into pipeline - executed
639 cmddatalong[5] = jtagarm7tdmi_nop( 0);
640 cmddatalong[4] = retval;
644 //! Write data to address - Assume TAP in run-test/idle state
645 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
646 unsigned long r0=0, r1=-1;
649 r0 = jtagarm7tdmi_get_register(0);
650 r1 = jtagarm7tdmi_get_register(1);
651 // write address into R0
652 jtagarm7tdmi_set_register(0, adr);
654 jtagarm7tdmi_set_register(1, data);
655 //retval = jtagarm7tdmi_exec(ARM_INSTR_LDR_R1_r0_4,1);
656 // push nop into pipeline to "clean" it ???
657 jtagarm7tdmi_nop( 0);
658 // push nop into pipeline with BREAKPT set
659 jtagarm7tdmi_nop( 1);
660 // push LDR R1, R0, #4 into instruction pipeline
661 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
662 // push nop into pipeline
663 jtagarm7tdmi_nop( 0);
665 jtagarm7tdmi_set_register(1, r1);
666 jtagarm7tdmi_set_register(0, r0);
673 //! Read data from address
674 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
675 unsigned long retval = 0;
676 unsigned long r0=0, r1=-1;
677 int waitcount = 0xfff;
680 // store R0 and R1 - not yet...
681 r0 = jtagarm7tdmi_get_register(0);
682 r1 = jtagarm7tdmi_get_register(1);
683 // write address into R0
684 jtagarm7tdmi_set_register(0, adr);
685 // push nop into pipeline to "clean" it ???
686 jtagarm7tdmi_nop( 0);
687 // push nop into pipeline with BREAKPT set
688 jtagarm7tdmi_nop( 1);
689 // push LDR R1, R0, #4 into instruction pipeline
690 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
691 // push nop into pipeline
692 jtagarm7tdmi_nop( 0);
693 // SHIFT_IR with RESTART instruction
694 jtagarm7tdmi_restart();
695 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
696 while ((jtagarm7tdmi_get_dbgstate() & 1) == 0 && waitcount > 0){
700 if (waitcount == 0xffff){
703 retval = jtagarm7tdmi_get_register(1);
704 // read memory value from R1 register
706 jtagarm7tdmi_set_register(1, r1);
707 jtagarm7tdmi_set_register(0, r0);
713 //! Read Program Counter
714 unsigned long jtagarm7tdmi_getpc(){
715 return jtagarm7tdmi_get_register(ARM_REG_PC);
718 //! Set Program Counter
719 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
720 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
723 //! Halt CPU - returns 0xffff if the operation fails to complete within
724 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
725 int waitcount = 0xfff;
727 // store watchpoint info? - not right now
728 // write 0 in watchpoint 1 address
729 eice_write(EICE_WP1ADDR, 0);
730 // write 0xffffffff in watchpoint 1 address mask
731 eice_write(EICE_WP1ADDRMASK, 0xffffffff);
732 // write 0 in watchpoint 1 data
733 eice_write(EICE_WP1DATA, 0);
734 // write 0xffffffff in watchpoint 1 data mask
735 eice_write(EICE_WP1DATAMASK, 0xffffffff);
736 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
737 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!?
738 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
739 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!?
740 // poll until debug status says the cpu is in debug mode
741 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount > 0){
745 // write 0 in watchpoint 0 control value - disables watchpoint 0
746 eice_write(EICE_WP1CTRL, 0x0);
748 // store the debug state
749 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
750 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
751 count_dbgspd_instr_since_debug = 0;
752 count_sysspd_instr_since_debug = 0;
753 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
754 jtagarm7tdmi_setMode_ARM();
759 unsigned long jtagarm7tdmi_releasecpu(){
760 int waitcount = 0xfff;
762 // somehow determine what PC should be (a couple ways possible, calculations required)
768 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){ // FIXME: FORKED.
769 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?
770 jtagarm7tdmi_instr_primitive(instr,0);
772 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?
773 jtagarm7tdmi_instr_primitive(instr,0);
777 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE);
779 // wait until restart-bit set in debug state register
780 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
784 last_halt_debug_state = -1;
792 ///////////////////////////////////////////////////////////////////////////////////////////////////
793 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
794 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
795 register char blocks;
800 jtagarm7tdmi_resettap();
805 cmddatalong[0] = jtagarm7tdmi_start();
806 cmddatalong[2] = jtagarm7tdmi_haltcpu();
807 cmddatalong[1] = jtagarm7tdmi_get_dbgstate();
809 //jtagarm7tdmi_resettap();
810 txdata(app,verb,0xc);
812 case JTAGARM7TDMI_READMEM:
814 blocks=(len>4?cmddata[4]:1);
818 txhead(app,verb,len);
822 jtagarm7tdmi_resettap();
825 val=jtagarm7tdmi_readmem(at);
829 serial_tx((val&0xFF00)>>8);
834 case JTAGARM7TDMI_GET_CHIP_ID:
835 jtagarm7tdmi_resettap();
836 cmddatalong[0] = jtagarm7tdmi_idcode();
841 case JTAGARM7TDMI_WRITEMEM:
843 jtagarm7tdmi_resettap();
844 jtagarm7tdmi_writemem(cmddatalong[0],
846 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
850 case JTAGARM7TDMI_HALTCPU:
851 cmddatalong[0] = jtagarm7tdmi_haltcpu();
854 case JTAGARM7TDMI_RELEASECPU:
855 jtagarm7tdmi_resettap();
856 cmddatalong[0] = jtagarm7tdmi_releasecpu();
859 //unimplemented functions
860 //case JTAGARM7TDMI_SETINSTRFETCH:
861 //case JTAGARM7TDMI_WRITEFLASH:
862 //case JTAGARM7TDMI_ERASEFLASH:
863 case JTAGARM7TDMI_SET_PC:
864 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
867 case JTAGARM7TDMI_GET_DEBUG_CTRL:
868 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
871 case JTAGARM7TDMI_SET_DEBUG_CTRL:
872 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
875 case JTAGARM7TDMI_GET_PC:
876 cmddatalong[0] = jtagarm7tdmi_getpc();
879 case JTAGARM7TDMI_GET_DEBUG_STATE:
880 //jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
881 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
884 //case JTAGARM7TDMI_GET_WATCHPOINT:
885 //case JTAGARM7TDMI_SET_WATCHPOINT:
886 case JTAGARM7TDMI_GET_REGISTER:
887 jtagarm7tdmi_resettap();
888 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
891 case JTAGARM7TDMI_SET_REGISTER:
892 jtagarm7tdmi_resettap();
893 cmddatalong[0] = cmddatalong[1];
894 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
897 case JTAGARM7TDMI_GET_REGISTERS:
898 jtagarm7tdmi_resettap();
899 jtagarm7tdmi_get_registers();
902 //case JTAGARM7TDMI_SET_REGISTERS:
903 case JTAGARM7TDMI_DEBUG_INSTR:
904 jtagarm7tdmi_resettap();
905 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
908 case JTAGARM7TDMI_STEP_INSTR:
909 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
910 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
911 case JTAGARM7TDMI_READ_FLASH_PAGE:
912 case JTAGARM7TDMI_MASS_ERASE_FLASH:
913 case JTAGARM7TDMI_PROGRAM_FLASH:
914 case JTAGARM7TDMI_LOCKCHIP:
915 case JTAGARM7TDMI_CHIP_ERASE:
917 // Really ARM specific stuff
918 case JTAGARM7TDMI_GET_CPSR:
919 jtagarm7tdmi_resettap();
920 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
923 case JTAGARM7TDMI_SET_CPSR:
924 jtagarm7tdmi_resettap();
925 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
928 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
929 jtagarm7tdmi_resettap();
930 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
933 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
934 jtagarm7tdmi_resettap();
935 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
938 case JTAGARM7TDMI_SET_MODE_THUMB:
939 case JTAGARM7TDMI_SET_MODE_ARM:
940 jtagarm7tdmi_resettap();
941 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
945 case 0xD0: // loopback test
946 jtagarm7tdmi_resettap();
947 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
950 case 0xD8: // EICE_READ
951 jtagarm7tdmi_resettap();
952 cmddatalong[0] = eice_read(cmddatalong[0]);
955 case 0xD9: // EICE_WRITE
956 jtagarm7tdmi_resettap();
957 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
960 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
961 jtagarm7tdmi_resettap();
962 jtagarm7tdmi_scan_intest(0);
963 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
964 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
965 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
966 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
967 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
968 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
969 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
970 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
971 jtagarm7tdmi_resettap();
972 jtagarm7tdmi_scan_intest(1);
973 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
974 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
975 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
976 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
981 jtaghandle(app,verb,len);