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 */
225 /************************************************************************
226 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
229 * * Scan Chain Select Register (4 bits_lsb)
230 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
231 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
232 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
233 ************************************************************************/
237 /************************** Basic JTAG Verb Commands *******************************/
238 //! Grab the core ID.
239 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
240 jtagarm7tdmi_resettap();
242 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
244 return jtagarmtransn(0,32, LSB, END, RETIDLE);
247 //! Connect Bypass Register to TDO/TDI
248 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
249 jtagarm7tdmi_resettap();
251 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
253 //! INTEST verb - do internal test
254 unsigned char jtagarm7tdmi_intest() {
255 jtagarm7tdmi_resettap();
257 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
261 unsigned char jtagarm7tdmi_extest() {
262 jtagarm7tdmi_resettap();
264 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
268 //unsigned long jtagarm7tdmi_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
307 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
308 wise, when in debug state, the core will not be correctly isolated and intrusive
309 commands occur. Therefore, it is recommended to pass directly from the “Update”
310 state” to the “Select DR” state each time the “Update” state is reached.
312 unsigned long retval;
313 if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
315 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
317 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
318 current_chain = chain;
320 retval = current_chain;
321 // put in test mode...
323 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
328 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
329 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
330 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
336 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
337 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
338 unsigned long retval;
339 jtagarm7tdmi_scan_intest(1);
342 // if the next instruction is to run using MCLK (master clock), set TDI
346 count_sysspd_instr_since_debug++;
351 count_dbgspd_instr_since_debug++;
355 // Now shift in the 32 bits
356 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
357 //jtag_arm_tcktock();
363 unsigned long jtagarm7tdmi_nop(char breakpt){
364 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
367 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
368 STR R0, [R0]; Save R0 before use
369 MOV R0, PC ; Copy PC into R0
370 STR R0, [R0]; Now save the PC in R0
371 BX PC ; Jump into ARM state
378 //! 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();
379 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
380 unsigned long retval = 0xff;
381 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
382 jtagarm7tdmi_scan_intest(1);
383 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
384 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
385 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
386 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
387 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
388 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
389 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
398 /************************* EmbeddedICE Primitives ****************************/
399 //! shifter for writing to chain2 (EmbeddedICE).
400 unsigned long eice_write(unsigned char reg, unsigned long data){
401 unsigned long retval, temp;
402 jtagarm7tdmi_scan_intest(2);
403 // Now shift in the 32 bits
405 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
406 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
407 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the WRITE bit
409 //SETTMS; // Last Bit - Exit UPDATE_DR
410 //// is this update a read/write or just read?
412 //jtag_arm_tcktock();
417 //! shifter for reading from chain2 (EmbeddedICE).
418 unsigned long eice_read(unsigned char reg){ // PROVEN
420 jtagarm7tdmi_scan_intest(2);
422 // send in the register address - 5 bits LSB
424 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
426 // clear TDI to select "read only"
427 jtagarmtransn(0, 1, LSB, END, RETIDLE);
430 // Now shift out the 32 bits
431 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
438 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
439 //! Grab debug register
440 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
441 //jtagarm7tdmi_resettap();
442 return eice_read(EICE_DBGSTATUS);
445 //! Grab debug register
446 unsigned long jtagarm7tdmi_get_dbgctrl() {
447 return eice_read(EICE_DBGCTRL);
450 //! Update debug register
451 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
452 return eice_write(EICE_DBGCTRL, bits);
457 //! Set and Enable Watchpoint 0
458 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
459 // store watchpoint info? - not right now
462 // write 0 in watchpoint 0 address
463 eice_write(EICE_WP0ADDR, addr);
464 // write 0xffffffff in watchpoint 0 address mask
465 eice_write(EICE_WP0ADDRMASK, addrmask);
466 // write 0 in watchpoint 0 data
467 eice_write(EICE_WP0DATA, data);
468 // write 0xffffffff in watchpoint 0 data mask
469 eice_write(EICE_WP0DATAMASK, datamask);
470 // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
471 eice_write(EICE_WP0CTRL, ctrlmask);
472 // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
473 eice_write(EICE_WP0CTRLMASK, ctrlmask);
476 //! Set and Enable Watchpoint 1
477 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
478 // store watchpoint info? - not right now
481 // write 0 in watchpoint 1 address
482 eice_write(EICE_WP1ADDR, addr);
483 // write 0xffffffff in watchpoint 1 address mask
484 eice_write(EICE_WP1ADDRMASK, addrmask);
485 // write 0 in watchpoint 1 data
486 eice_write(EICE_WP1DATA, data);
487 // write 0xffffffff in watchpoint 1 data mask
488 eice_write(EICE_WP1DATAMASK, datamask);
489 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
490 eice_write(EICE_WP1CTRL, ctrl);
491 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
492 eice_write(EICE_WP1CTRLMASK, ctrlmask);
495 //! Disable Watchpoint 0
496 void jtagarm7tdmi_disable_watchpoint0(){
497 // write 0 in watchpoint 0 control value - disables watchpoint 0
498 eice_write(EICE_WP0CTRL, 0x0);
501 //! Disable Watchpoint 1
502 void jtagarm7tdmi_disable_watchpoint1(){
503 // write 0 in watchpoint 0 control value - disables watchpoint 0
504 eice_write(EICE_WP1CTRL, 0x0);
509 /******************** Complex Commands **************************/
510 //! Push an instruction into the CPU pipeline
511 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
512 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
513 unsigned long retval;
515 cmddatalong[1] = jtagarm7tdmi_nop( 0);
516 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
517 // write 32-bit instruction code into DR
518 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
519 cmddatalong[4] = jtagarm7tdmi_nop( 0);
520 cmddatalong[5] = jtagarm7tdmi_nop( 0);
522 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
523 cmddatalong[7] = jtagarm7tdmi_nop( 0);
524 cmddatalong[8] = jtagarm7tdmi_nop( 0);
525 cmddatalong[9] = jtagarm7tdmi_nop( 0);
526 retval = cmddatalong[9];
532 //! Push an instruction into the CPU pipeline
533 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
534 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
535 unsigned long retval;
537 cmddatalong[1] = jtagarm7tdmi_nop( 0);
538 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
539 // write 32-bit instruction code into DR
540 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
541 cmddatalong[4] = jtagarm7tdmi_nop( 0);
542 cmddatalong[5] = jtagarm7tdmi_nop( 0);
544 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
545 cmddatalong[7] = jtagarm7tdmi_nop( 0);
546 retval = jtagarm7tdmi_nop( 0);
547 cmddatalong[9] = jtagarm7tdmi_nop( 0);
548 cmddatalong[8] = retval;
553 //! Retrieve a 32-bit Register value
554 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
555 unsigned long retval = 0, instr;
556 // push nop into pipeline - clean out the pipeline...
557 cmddatalong[2] = jtagarm7tdmi_nop( 0);
559 instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
560 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
561 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
562 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
563 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
564 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
565 cmddatalong[5] = retval;
566 cmddatalong[6] = jtagarm7tdmi_nop( 0);
567 cmddatalong[7] = jtagarm7tdmi_nop( 0);
568 cmddatalong[8] = jtagarm7tdmi_nop( 0);
572 //! Set a 32-bit Register value
573 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
574 unsigned long retval = 0, instr;
575 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
577 instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
578 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
579 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
580 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
582 cmddatalong[4] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus - execute state
583 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
585 if (reg == ARM_REG_PC){
586 cmddatalong[6] = jtagarm7tdmi_nop( 0);
587 cmddatalong[7] = jtagarm7tdmi_nop( 0);
589 cmddatalong[8] = jtagarm7tdmi_nop( 0);
591 retval = cmddatalong[5];
597 //! Get all registers. Return an array
598 unsigned long* jtagarm7tdmi_get_registers() {
599 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
600 cmddatalong[2] = jtagarm7tdmi_nop( 0);
601 cmddatalong[3] = jtagarm7tdmi_nop( 0);
602 cmddatalong[4] = jtagarm7tdmi_nop( 0);
603 cmddatalong[5] = jtagarm7tdmi_nop( 0);
604 cmddatalong[6] = jtagarm7tdmi_nop( 0);
605 cmddatalong[7] = jtagarm7tdmi_nop( 0);
606 cmddatalong[8] = jtagarm7tdmi_nop( 0);
607 cmddatalong[9] = jtagarm7tdmi_nop( 0);
608 cmddatalong[10] = jtagarm7tdmi_nop( 0);
609 cmddatalong[11] = jtagarm7tdmi_nop( 0);
610 cmddatalong[12] = jtagarm7tdmi_nop( 0);
611 cmddatalong[13] = jtagarm7tdmi_nop( 0);
612 cmddatalong[14] = jtagarm7tdmi_nop( 0);
613 cmddatalong[15] = jtagarm7tdmi_nop( 0);
614 cmddatalong[16] = jtagarm7tdmi_nop( 0);
615 cmddatalong[17] = jtagarm7tdmi_nop( 0);
616 cmddatalong[18] = jtagarm7tdmi_nop( 0);
617 cmddatalong[19] = jtagarm7tdmi_nop( 0);
618 cmddatalong[20] = jtagarm7tdmi_nop( 0);
622 //! Retrieve the CPSR Register value
623 unsigned long jtagarm7tdmi_get_regCPSR() {
624 unsigned long retval = 0;
626 // push nop into pipeline - clean out the pipeline...
627 cmddatalong[1] = jtagarm7tdmi_nop( 0);
628 // push MRS_R0, CPSR into pipeline
629 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0);
630 // push nop into pipeline - fetched
631 cmddatalong[3] = jtagarm7tdmi_nop( 0);
632 // push nop into pipeline - decoded
633 cmddatalong[4] = jtagarm7tdmi_nop( 0);
634 // push nop into pipeline - executed
635 cmddatalong[5] = jtagarm7tdmi_nop( 0);
636 // recover 32-bit word
637 retval = jtagarm7tdmi_nop( 0);
638 cmddatalong[6] = retval;
642 //! Retrieve the CPSR Register value
643 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
644 unsigned long retval = 0;
646 // push nop into pipeline - clean out the pipeline...
647 cmddatalong[1] = jtagarm7tdmi_nop( 0);
648 // push MSR cpsr_cxsf, R0 into pipeline
649 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0);
650 // push nop into pipeline - fetched
651 cmddatalong[2] = jtagarm7tdmi_nop( 0);
652 // push nop into pipeline - decoded
653 cmddatalong[3] = jtagarm7tdmi_nop( 0);
655 // push 32-bit word on data bus
656 retval = jtagarm7tdmi_instr_primitive(val, 0);
657 // push nop into pipeline - executed
658 cmddatalong[5] = jtagarm7tdmi_nop( 0);
659 cmddatalong[4] = retval;
663 //! Write data to address - Assume TAP in run-test/idle state
664 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
665 unsigned long r0=0, r1=-1;
668 r0 = jtagarm7tdmi_get_register(0);
669 r1 = jtagarm7tdmi_get_register(1);
670 // write address into R0
671 jtagarm7tdmi_set_register(0, adr);
673 jtagarm7tdmi_set_register(1, data);
674 //retval = jtagarm7tdmi_exec(ARM_INSTR_LDR_R1_r0_4,1);
675 // push nop into pipeline to "clean" it ???
676 jtagarm7tdmi_nop( 0);
677 // push nop into pipeline with BREAKPT set
678 jtagarm7tdmi_nop( 1);
679 // push LDR R1, R0, #4 into instruction pipeline
680 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
681 // push nop into pipeline
682 jtagarm7tdmi_nop( 0);
684 jtagarm7tdmi_set_register(1, r1);
685 jtagarm7tdmi_set_register(0, r0);
692 //! Read data from address
693 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
694 unsigned long retval = 0;
695 unsigned long r0=0, r1=-1;
696 int waitcount = 0xfff;
699 // store R0 and R1 - not yet...
700 r0 = jtagarm7tdmi_get_register(0);
701 r1 = jtagarm7tdmi_get_register(1);
702 // write address into R0
703 jtagarm7tdmi_set_register(0, adr);
704 // push nop into pipeline to "clean" it ???
705 jtagarm7tdmi_nop( 0);
706 // push nop into pipeline with BREAKPT set
707 jtagarm7tdmi_nop( 1);
708 // push LDR R1, R0, #4 into instruction pipeline
709 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
710 // push nop into pipeline
711 jtagarm7tdmi_nop( 0);
712 // SHIFT_IR with RESTART instruction
713 jtagarm7tdmi_restart();
714 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
715 while ((jtagarm7tdmi_get_dbgstate() & 1) == 0 && waitcount > 0){
719 if (waitcount == 0xffff){
722 retval = jtagarm7tdmi_get_register(1);
723 // read memory value from R1 register
725 jtagarm7tdmi_set_register(1, r1);
726 jtagarm7tdmi_set_register(0, r0);
732 //! Read Program Counter
733 unsigned long jtagarm7tdmi_getpc(){
734 return jtagarm7tdmi_get_register(ARM_REG_PC);
737 //! Set Program Counter
738 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
739 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
742 //! Halt CPU - returns 0xffff if the operation fails to complete within
743 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
744 int waitcount = 0xfff;
746 // store watchpoint info? - not right now
747 // write 0 in watchpoint 1 address
748 eice_write(EICE_WP1ADDR, 0);
749 // write 0xffffffff in watchpoint 1 address mask
750 eice_write(EICE_WP1ADDRMASK, 0xffffffff);
751 // write 0 in watchpoint 1 data
752 eice_write(EICE_WP1DATA, 0);
753 // write 0xffffffff in watchpoint 1 data mask
754 eice_write(EICE_WP1DATAMASK, 0xffffffff);
755 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
756 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!?
757 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
758 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!?
759 // poll until debug status says the cpu is in debug mode
760 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount > 0){
764 // write 0 in watchpoint 0 control value - disables watchpoint 0
765 eice_write(EICE_WP1CTRL, 0x0);
767 // store the debug state
768 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
769 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
770 count_dbgspd_instr_since_debug = 0;
771 count_sysspd_instr_since_debug = 0;
772 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
773 jtagarm7tdmi_setMode_ARM();
778 unsigned long jtagarm7tdmi_releasecpu(){
779 int waitcount = 0xfff;
781 // somehow determine what PC should be (a couple ways possible, calculations required)
787 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){ // FIXME: FORKED.
788 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?
789 jtagarm7tdmi_instr_primitive(instr,0);
791 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?
792 jtagarm7tdmi_instr_primitive(instr,0);
796 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE);
798 // wait until restart-bit set in debug state register
799 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
803 last_halt_debug_state = -1;
811 ///////////////////////////////////////////////////////////////////////////////////////////////////
812 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
813 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
814 register char blocks;
819 jtagarm7tdmi_resettap();
824 cmddatalong[0] = jtagarm7tdmi_start();
825 cmddatalong[2] = jtagarm7tdmi_haltcpu();
826 cmddatalong[1] = jtagarm7tdmi_get_dbgstate();
828 //jtagarm7tdmi_resettap();
829 txdata(app,verb,0xc);
831 case JTAGARM7TDMI_READMEM:
833 blocks=(len>4?cmddata[4]:1);
837 txhead(app,verb,len);
841 jtagarm7tdmi_resettap();
844 val=jtagarm7tdmi_readmem(at);
848 serial_tx((val&0xFF00)>>8);
853 case JTAGARM7TDMI_GET_CHIP_ID:
854 jtagarm7tdmi_resettap();
855 cmddatalong[0] = jtagarm7tdmi_idcode();
860 case JTAGARM7TDMI_WRITEMEM:
862 jtagarm7tdmi_resettap();
863 jtagarm7tdmi_writemem(cmddatalong[0],
865 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
869 case JTAGARM7TDMI_HALTCPU:
870 cmddatalong[0] = jtagarm7tdmi_haltcpu();
873 case JTAGARM7TDMI_RELEASECPU:
874 jtagarm7tdmi_resettap();
875 cmddatalong[0] = jtagarm7tdmi_releasecpu();
878 //unimplemented functions
879 //case JTAGARM7TDMI_SETINSTRFETCH:
880 //case JTAGARM7TDMI_WRITEFLASH:
881 //case JTAGARM7TDMI_ERASEFLASH:
882 case JTAGARM7TDMI_SET_PC:
883 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
886 case JTAGARM7TDMI_GET_DEBUG_CTRL:
887 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
890 case JTAGARM7TDMI_SET_DEBUG_CTRL:
891 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
894 case JTAGARM7TDMI_GET_PC:
895 cmddatalong[0] = jtagarm7tdmi_getpc();
898 case JTAGARM7TDMI_GET_DEBUG_STATE:
899 //jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
900 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
903 //case JTAGARM7TDMI_GET_WATCHPOINT:
904 //case JTAGARM7TDMI_SET_WATCHPOINT:
905 case JTAGARM7TDMI_GET_REGISTER:
906 jtagarm7tdmi_resettap();
907 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
910 case JTAGARM7TDMI_SET_REGISTER:
911 jtagarm7tdmi_resettap();
912 cmddatalong[0] = cmddatalong[1];
913 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
916 case JTAGARM7TDMI_GET_REGISTERS:
917 jtagarm7tdmi_resettap();
918 jtagarm7tdmi_get_registers();
921 //case JTAGARM7TDMI_SET_REGISTERS:
922 case JTAGARM7TDMI_DEBUG_INSTR:
923 jtagarm7tdmi_resettap();
924 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
927 case JTAGARM7TDMI_STEP_INSTR:
928 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
929 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
930 case JTAGARM7TDMI_READ_FLASH_PAGE:
931 case JTAGARM7TDMI_MASS_ERASE_FLASH:
932 case JTAGARM7TDMI_PROGRAM_FLASH:
933 case JTAGARM7TDMI_LOCKCHIP:
934 case JTAGARM7TDMI_CHIP_ERASE:
936 // Really ARM specific stuff
937 case JTAGARM7TDMI_GET_CPSR:
938 jtagarm7tdmi_resettap();
939 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
942 case JTAGARM7TDMI_SET_CPSR:
943 jtagarm7tdmi_resettap();
944 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
947 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
948 jtagarm7tdmi_resettap();
949 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
952 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
953 jtagarm7tdmi_resettap();
954 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
957 case JTAGARM7TDMI_SET_MODE_THUMB:
958 case JTAGARM7TDMI_SET_MODE_ARM:
959 jtagarm7tdmi_resettap();
960 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
964 case 0xD0: // loopback test
965 jtagarm7tdmi_resettap();
966 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
969 case 0xD8: // EICE_READ
970 jtagarm7tdmi_resettap();
971 cmddatalong[0] = eice_read(cmddatalong[0]);
974 case 0xD9: // EICE_WRITE
975 jtagarm7tdmi_resettap();
976 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
979 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
980 jtagarm7tdmi_resettap();
981 jtagarm7tdmi_scan_intest(0);
982 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
983 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
984 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
985 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
986 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
987 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
988 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
989 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
990 jtagarm7tdmi_resettap();
991 jtagarm7tdmi_scan_intest(1);
992 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
993 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
994 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
995 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1000 jtaghandle(app,verb,len);