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
152 jtag_reset_to_runtest_idle();
156 // NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR THE FUNCTIONAL EQUIVALENT
159 //! 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
160 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
162 unsigned long high = 1;
166 for (bit=(bitcount-1)/16; bit>0; bit--)
168 high <<= ((bitcount-1)%16);
173 for (bit = bitcount; bit > 0; bit--) {
174 /* write MOSI on trailing edge of previous clock */
182 SETTMS;//TMS high on last bit to exit.
186 /* read MISO on trailing edge */
192 for (bit=bitcount; bit>0; bit++) {
193 /* write MOSI on trailing edge of previous clock */
198 word = (word & mask) << 1;
201 SETTMS;//TMS high on last bit to exit.
205 /* 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 // debugstr("_sample");
269 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
270 // return jtagtransn(0,32);
274 unsigned char jtagarm7tdmi_restart() {
275 jtagarm7tdmi_resettap();
277 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
280 //! ARM7TDMI_IR_CLAMP 0x5
281 unsigned long jtagarm7tdmi_clamp() {
282 jtagarm7tdmi_resettap();
284 jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
286 return jtagarmtransn(0, 32, LSB, END, RETIDLE);
289 //! ARM7TDMI_IR_HIGHZ 0x7
290 unsigned char jtagarm7tdmi_highz() {
291 jtagarm7tdmi_resettap();
293 return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
296 //! define ARM7TDMI_IR_CLAMPZ 0x9
297 unsigned char jtagarm7tdmi_clampz() {
298 jtagarm7tdmi_resettap();
300 return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
304 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
305 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
308 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
309 wise, when in debug state, the core will not be correctly isolated and intrusive
310 commands occur. Therefore, it is recommended to pass directly from the “Update”
311 state” to the “Select DR” state each time the “Update” state is reached.
313 unsigned long retval;
314 if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
316 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
318 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
319 current_chain = chain;
321 retval = current_chain;
322 // put in test mode...
324 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
326 current_chain = chain;
332 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
333 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
334 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
340 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
341 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
342 unsigned long retval;
343 jtagarm7tdmi_scan_intest(1);
345 // if the next instruction is to run using MCLK (master clock), set TDI
349 count_sysspd_instr_since_debug++;
354 count_dbgspd_instr_since_debug++;
359 // Now shift in the 32 bits
360 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
361 //jtag_arm_tcktock();
367 unsigned long jtagarm7tdmi_nop(char breakpt){
368 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
371 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
372 STR R0, [R0]; Save R0 before use
373 MOV R0, PC ; Copy PC into R0
374 STR R0, [R0]; Now save the PC in R0
375 BX PC ; Jump into ARM state
382 //! 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();
383 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
384 unsigned long retval = 0xff;
385 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
386 jtagarm7tdmi_scan_intest(1);
387 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
388 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
389 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
390 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
391 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
392 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
393 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
402 /************************* EmbeddedICE Primitives ****************************/
403 //! shifter for writing to chain2 (EmbeddedICE).
404 unsigned long eice_write(unsigned char reg, unsigned long data){
405 unsigned long retval, temp;
406 jtagarm7tdmi_scan_intest(2);
407 // Now shift in the 32 bits
409 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
410 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
411 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the register address - 5 bits lsb
413 //SETTMS; // Last Bit - Exit UPDATE_DR
414 //// is this update a read/write or just read?
416 //jtag_arm_tcktock();
421 //! shifter for reading from chain2 (EmbeddedICE).
422 unsigned long eice_read(unsigned char reg){ // PROVEN
424 jtagarm7tdmi_scan_intest(2);
426 // send in the register address - 5 bits LSB
428 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
430 // clear TDI to select "read only"
431 jtagarmtransn(0, 1, LSB, END, RETIDLE);
434 // Now shift out the 32 bits
435 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
442 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
443 //! Grab debug register
444 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
445 return eice_read(EICE_DBGSTATUS);
448 //! Grab debug register
449 unsigned long jtagarm7tdmi_get_dbgctrl() {
450 return eice_read(EICE_DBGCTRL);
453 //! Update debug register
454 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
455 return eice_write(EICE_DBGCTRL, bits);
460 //! Set and Enable Watchpoint 0
461 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
462 // store watchpoint info? - not right now
465 // write 0 in watchpoint 0 address
466 eice_write(EICE_WP0ADDR, addr);
467 // write 0xffffffff in watchpoint 0 address mask
468 eice_write(EICE_WP0ADDRMASK, addrmask);
469 // write 0 in watchpoint 0 data
470 eice_write(EICE_WP0DATA, data);
471 // write 0xffffffff in watchpoint 0 data mask
472 eice_write(EICE_WP0DATAMASK, datamask);
473 // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
474 eice_write(EICE_WP0CTRL, ctrlmask);
475 // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
476 eice_write(EICE_WP0CTRLMASK, ctrlmask);
479 //! Set and Enable Watchpoint 1
480 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
481 // store watchpoint info? - not right now
484 // write 0 in watchpoint 1 address
485 eice_write(EICE_WP1ADDR, addr);
486 // write 0xffffffff in watchpoint 1 address mask
487 eice_write(EICE_WP1ADDRMASK, addrmask);
488 // write 0 in watchpoint 1 data
489 eice_write(EICE_WP1DATA, data);
490 // write 0xffffffff in watchpoint 1 data mask
491 eice_write(EICE_WP1DATAMASK, datamask);
492 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
493 eice_write(EICE_WP1CTRL, ctrl);
494 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
495 eice_write(EICE_WP1CTRLMASK, ctrlmask);
498 //! Disable Watchpoint 0
499 void jtagarm7tdmi_disable_watchpoint0(){
500 // write 0 in watchpoint 0 control value - disables watchpoint 0
501 eice_write(EICE_WP0CTRL, 0x0);
504 //! Disable Watchpoint 1
505 void jtagarm7tdmi_disable_watchpoint1(){
506 // write 0 in watchpoint 0 control value - disables watchpoint 0
507 eice_write(EICE_WP1CTRL, 0x0);
512 /******************** Complex Commands **************************/
513 //! Push an instruction into the CPU pipeline
514 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
515 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
516 unsigned long retval;
518 cmddatalong[1] = jtagarm7tdmi_nop( 0);
519 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
520 // write 32-bit instruction code into DR
521 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
522 cmddatalong[4] = jtagarm7tdmi_nop( 0);
523 cmddatalong[5] = jtagarm7tdmi_nop( 0);
525 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
526 cmddatalong[7] = jtagarm7tdmi_nop( 0);
527 cmddatalong[8] = jtagarm7tdmi_nop( 0);
528 cmddatalong[9] = jtagarm7tdmi_nop( 0);
529 retval = cmddatalong[9];
535 //! Push an instruction into the CPU pipeline
536 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
537 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
538 unsigned long retval;
540 cmddatalong[1] = jtagarm7tdmi_nop( 0);
541 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
542 // write 32-bit instruction code into DR
543 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
544 cmddatalong[4] = jtagarm7tdmi_nop( 0);
545 cmddatalong[5] = jtagarm7tdmi_nop( 0);
547 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
548 cmddatalong[7] = jtagarm7tdmi_nop( 0);
549 retval = jtagarm7tdmi_nop( 0);
550 cmddatalong[9] = jtagarm7tdmi_nop( 0);
551 cmddatalong[8] = retval;
556 //! Retrieve a 32-bit Register value
557 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
558 unsigned long retval = 0, instr;
559 // push nop into pipeline - clean out the pipeline...
560 cmddatalong[2] = jtagarm7tdmi_nop( 0);
562 // push STR_Rx, [R14] into pipeline
563 instr = ARM_INSTR_STR_Rx_r14 + ((reg<<12)&0xf00);
564 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
565 // push nop into pipeline - fetched
566 cmddatalong[2] = jtagarm7tdmi_nop( 0);
567 // push nop into pipeline - decoded
568 cmddatalong[3] = jtagarm7tdmi_nop( 0);
569 // push nop into pipeline - executed
570 cmddatalong[4] = jtagarm7tdmi_nop( 0);
571 // recover 32-bit word
572 //retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
573 retval = jtagarm7tdmi_nop( 0);
574 cmddatalong[5] = retval;
575 cmddatalong[6] = jtagarm7tdmi_nop( 0);
576 cmddatalong[7] = jtagarm7tdmi_nop( 0);
577 cmddatalong[8] = jtagarm7tdmi_nop( 0);
581 //! Set a 32-bit Register value
582 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
583 unsigned long retval = 0, instr;
584 // push nop into pipeline - clean out the pipeline...
585 cmddatalong[2] = jtagarm7tdmi_nop( 0);
587 // push STR_Rx, [R14] into pipeline
588 instr = ARM_INSTR_LDR_Rx_r14 + ((reg<<12)&0xf00);
589 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
590 // push nop into pipeline - fetched
591 cmddatalong[2] = jtagarm7tdmi_nop( 0);
592 // push nop into pipeline - decoded
593 cmddatalong[2] = jtagarm7tdmi_nop( 0);
595 // push 32-bit word on data bus - execute state
596 //retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
597 cmddatalong[3] = jtagarm7tdmi_instr_primitive(val, 0);
598 // push nop into pipeline - executed
599 cmddatalong[4] = jtagarm7tdmi_nop( 0);
600 if (reg == ARM_REG_PC){
601 cmddatalong[5] = jtagarm7tdmi_nop( 0);
602 cmddatalong[6] = jtagarm7tdmi_nop( 0);
604 retval = jtagarm7tdmi_nop( 0);
605 cmddatalong[7] = retval;
611 //! Get all registers. Return an array
612 unsigned long* jtagarm7tdmi_get_registers() {
613 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
614 cmddatalong[2] = jtagarm7tdmi_nop( 0);
615 cmddatalong[3] = jtagarm7tdmi_nop( 0);
616 cmddatalong[4] = jtagarm7tdmi_nop( 0);
617 cmddatalong[5] = jtagarm7tdmi_nop( 0);
618 cmddatalong[6] = jtagarm7tdmi_nop( 0);
619 cmddatalong[7] = jtagarm7tdmi_nop( 0);
620 cmddatalong[8] = jtagarm7tdmi_nop( 0);
621 cmddatalong[9] = jtagarm7tdmi_nop( 0);
622 cmddatalong[10] = jtagarm7tdmi_nop( 0);
623 cmddatalong[11] = jtagarm7tdmi_nop( 0);
624 cmddatalong[12] = jtagarm7tdmi_nop( 0);
625 cmddatalong[13] = jtagarm7tdmi_nop( 0);
626 cmddatalong[14] = jtagarm7tdmi_nop( 0);
627 cmddatalong[15] = jtagarm7tdmi_nop( 0);
628 cmddatalong[16] = jtagarm7tdmi_nop( 0);
629 cmddatalong[17] = jtagarm7tdmi_nop( 0);
630 cmddatalong[18] = jtagarm7tdmi_nop( 0);
631 cmddatalong[19] = jtagarm7tdmi_nop( 0);
632 cmddatalong[20] = jtagarm7tdmi_nop( 0);
636 //! Retrieve the CPSR Register value
637 unsigned long jtagarm7tdmi_get_regCPSR() {
638 unsigned long retval = 0;
640 // push nop into pipeline - clean out the pipeline...
641 cmddatalong[1] = jtagarm7tdmi_nop( 0);
642 // push MRS_R0, CPSR into pipeline
643 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0);
644 // push nop into pipeline - fetched
645 cmddatalong[3] = jtagarm7tdmi_nop( 0);
646 // push nop into pipeline - decoded
647 cmddatalong[4] = jtagarm7tdmi_nop( 0);
648 // push nop into pipeline - executed
649 cmddatalong[5] = jtagarm7tdmi_nop( 0);
650 // recover 32-bit word
651 retval = jtagarm7tdmi_nop( 0);
652 cmddatalong[5] = retval;
656 //! Retrieve the CPSR Register value
657 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
658 unsigned long retval = 0;
660 // push nop into pipeline - clean out the pipeline...
661 cmddatalong[1] = jtagarm7tdmi_nop( 0);
662 // push MSR cpsr_cxsf, R0 into pipeline
663 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0);
664 // push nop into pipeline - fetched
665 cmddatalong[2] = jtagarm7tdmi_nop( 0);
666 // push nop into pipeline - decoded
667 cmddatalong[3] = jtagarm7tdmi_nop( 0);
669 // push 32-bit word on data bus
670 retval = jtagarm7tdmi_instr_primitive(val, 0);
671 // push nop into pipeline - executed
672 cmddatalong[5] = jtagarm7tdmi_nop( 0);
673 cmddatalong[4] = retval;
677 //! Write data to address - Assume TAP in run-test/idle state
678 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
679 unsigned long r0=0, r1=-1;
682 r0 = jtagarm7tdmi_get_register(0);
683 r1 = jtagarm7tdmi_get_register(1);
684 // write address into R0
685 jtagarm7tdmi_set_register(0, adr);
687 jtagarm7tdmi_set_register(1, data);
688 //retval = jtagarm7tdmi_exec(ARM_INSTR_LDR_R1_r0_4,1);
689 // push nop into pipeline to "clean" it ???
690 jtagarm7tdmi_nop( 0);
691 // push nop into pipeline with BREAKPT set
692 jtagarm7tdmi_nop( 1);
693 // push LDR R1, R0, #4 into instruction pipeline
694 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
695 // push nop into pipeline
696 jtagarm7tdmi_nop( 0);
698 jtagarm7tdmi_set_register(1, r1);
699 jtagarm7tdmi_set_register(0, r0);
703 //! Read data from address
704 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
705 unsigned long retval = 0;
706 unsigned long r0=0, r1=-1;
707 int waitcount = 0xfff;
710 // store R0 and R1 - not yet...
711 r0 = jtagarm7tdmi_get_register(0);
712 r1 = jtagarm7tdmi_get_register(1);
713 // write address into R0
714 jtagarm7tdmi_set_register(0, adr);
715 // push nop into pipeline to "clean" it ???
716 jtagarm7tdmi_nop( 0);
717 // push nop into pipeline with BREAKPT set
718 jtagarm7tdmi_nop( 1);
719 // push LDR R1, R0, #4 into instruction pipeline
720 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
721 // push nop into pipeline
722 jtagarm7tdmi_nop( 0);
723 // SHIFT_IR with RESTART instruction
724 jtagarm7tdmi_restart();
725 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
726 while ((jtagarm7tdmi_get_dbgstate() & 1) == 0 && waitcount > 0){
730 if (waitcount == 0xffff){
733 retval = jtagarm7tdmi_get_register(1);
734 // read memory value from R1 register
736 jtagarm7tdmi_set_register(1, r1);
737 jtagarm7tdmi_set_register(0, r0);
743 //! Read Program Counter
744 unsigned long jtagarm7tdmi_getpc(){
745 return jtagarm7tdmi_get_register(ARM_REG_PC);
748 //! Set Program Counter
749 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
750 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
753 //! Halt CPU - returns 0xffff if the operation fails to complete within
754 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
755 int waitcount = 0xfff;
757 // store watchpoint info? - not right now
758 // write 0 in watchpoint 1 address
759 eice_write(EICE_WP1ADDR, 0);
760 // write 0xffffffff in watchpoint 1 address mask
761 eice_write(EICE_WP1ADDRMASK, 0xffffffff);
762 // write 0 in watchpoint 1 data
763 eice_write(EICE_WP1DATA, 0);
764 // write 0xffffffff in watchpoint 1 data mask
765 eice_write(EICE_WP1DATAMASK, 0xffffffff);
766 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
767 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!?
768 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
769 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!?
770 // poll until debug status says the cpu is in debug mode
771 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount > 0){
775 // write 0 in watchpoint 0 control value - disables watchpoint 0
776 eice_write(EICE_WP1CTRL, 0x0);
778 // store the debug state
779 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
780 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
781 count_dbgspd_instr_since_debug = 0;
782 count_sysspd_instr_since_debug = 0;
783 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
784 jtagarm7tdmi_setMode_ARM();
789 unsigned long jtagarm7tdmi_releasecpu(){
790 int waitcount = 0xfff;
792 // somehow determine what PC should be (a couple ways possible, calculations required)
798 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
799 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?
800 jtagarm7tdmi_instr_primitive(instr,0);
802 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?
803 jtagarm7tdmi_instr_primitive(instr,0);
807 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE);
809 // wait until restart-bit set in debug state register
810 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
814 last_halt_debug_state = -1;
822 ///////////////////////////////////////////////////////////////////////////////////////////////////
823 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
824 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
825 register char blocks;
830 jtagarm7tdmi_resettap();
831 debugstr("Classic ARM JTAG handler.");
837 cmddatalong[0] = jtagarm7tdmi_start();
838 cmddatalong[1] = jtagarm7tdmi_haltcpu();
839 //jtagarm7tdmi_resettap();
840 txdata(app,verb,0x8);
842 case JTAGARM7TDMI_READMEM:
844 blocks=(len>4?cmddata[4]:1);
848 txhead(app,verb,len);
852 jtagarm7tdmi_resettap();
855 val=jtagarm7tdmi_readmem(at);
859 serial_tx((val&0xFF00)>>8);
864 case JTAGARM7TDMI_GET_CHIP_ID:
865 jtagarm7tdmi_resettap();
866 cmddatalong[0] = jtagarm7tdmi_idcode();
872 case JTAGARM7TDMI_WRITEMEM:
874 jtagarm7tdmi_resettap();
875 jtagarm7tdmi_writemem(cmddatalong[0],
877 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
881 case JTAGARM7TDMI_HALTCPU:
882 cmddatalong[0] = jtagarm7tdmi_haltcpu();
885 case JTAGARM7TDMI_RELEASECPU:
886 jtagarm7tdmi_resettap();
887 cmddatalong[0] = jtagarm7tdmi_releasecpu();
890 //unimplemented functions
891 //case JTAGARM7TDMI_SETINSTRFETCH:
892 //case JTAGARM7TDMI_WRITEFLASH:
893 //case JTAGARM7TDMI_ERASEFLASH:
894 case JTAGARM7TDMI_SET_PC:
895 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
898 case JTAGARM7TDMI_GET_DEBUG_CTRL:
899 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
902 case JTAGARM7TDMI_SET_DEBUG_CTRL:
903 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
906 case JTAGARM7TDMI_GET_PC:
907 cmddatalong[0] = jtagarm7tdmi_getpc();
910 case JTAGARM7TDMI_GET_DEBUG_STATE:
911 //jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
912 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
915 //case JTAGARM7TDMI_GET_WATCHPOINT:
916 //case JTAGARM7TDMI_SET_WATCHPOINT:
917 case JTAGARM7TDMI_GET_REGISTER:
918 jtagarm7tdmi_resettap();
919 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
922 case JTAGARM7TDMI_SET_REGISTER:
923 jtagarm7tdmi_resettap();
924 cmddatalong[0] = cmddatalong[1];
925 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
928 case JTAGARM7TDMI_GET_REGISTERS:
929 jtagarm7tdmi_resettap();
930 jtagarm7tdmi_get_registers();
933 //case JTAGARM7TDMI_SET_REGISTERS:
934 case JTAGARM7TDMI_DEBUG_INSTR:
935 jtagarm7tdmi_resettap();
936 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
939 case JTAGARM7TDMI_STEP_INSTR:
940 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
941 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
942 case JTAGARM7TDMI_READ_FLASH_PAGE:
943 case JTAGARM7TDMI_MASS_ERASE_FLASH:
944 case JTAGARM7TDMI_PROGRAM_FLASH:
945 case JTAGARM7TDMI_LOCKCHIP:
946 case JTAGARM7TDMI_CHIP_ERASE:
948 // Really ARM specific stuff
949 case JTAGARM7TDMI_GET_CPSR:
950 jtagarm7tdmi_resettap();
951 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
954 case JTAGARM7TDMI_SET_CPSR:
955 jtagarm7tdmi_resettap();
956 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
959 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
960 jtagarm7tdmi_resettap();
961 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
964 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
965 jtagarm7tdmi_resettap();
966 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
969 case JTAGARM7TDMI_SET_MODE_THUMB:
970 case JTAGARM7TDMI_SET_MODE_ARM:
971 jtagarm7tdmi_resettap();
972 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
976 case 0xD0: // loopback test
977 jtagarm7tdmi_resettap();
978 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
981 case 0xD8: // EICE_READ
982 jtagarm7tdmi_resettap();
983 cmddatalong[0] = eice_read(cmddatalong[0]);
986 case 0xD9: // EICE_WRITE
987 jtagarm7tdmi_resettap();
988 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
991 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
992 jtagarm7tdmi_resettap();
993 jtagarm7tdmi_scan_intest(0);
994 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
995 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
996 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
997 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
998 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
999 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
1000 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
1001 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
1002 jtagarm7tdmi_resettap();
1003 jtagarm7tdmi_scan_intest(1);
1004 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
1005 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
1006 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
1007 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1008 txdata(app,verb,48);
1012 jtaghandle(app,verb,len);