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 ********************************/
42 /****************************************************************
43 Enabling jtag likely differs with most platforms. We will attempt to enable most from here. Override jtagarm7tdmi_start() to extend for other implementations
44 ARM7TDMI enables three different scan chains:
45 * Chain0 - "entire periphery" including data bus
46 * Chain1 - core data bus (subset of Chain0) - Instruction Pipeline
47 * Chain2 - EmbeddedICE Logic Registers - This is our way into the fun stuff.
51 You can disable EmbeddedICE-RT by setting the DBGEN input LOW.
53 Hard wiring the DBGEN input LOW permanently disables all debug functionality.
54 When DBGEN is LOW, it inhibits DBGDEWPT, DBGIEBKPT, and EDBGRQ to
55 the core, and DBGACK from the ARM9E-S core is always LOW.
60 When the ARM9E-S core is in debug state, you can examine the core and system state
61 by forcing the load and store multiples into the instruction pipeline.
62 Before you can examine the core and system state, the debugger must determine
63 whether the processor entered debug from Thumb state or ARM state, by examining
64 bit 4 of the EmbeddedICE-RT debug status register. If bit 4 is HIGH, the core has
65 entered debug from Thumb state.
66 For more details about determining the core state, see Determining the core and system
71 --- olimex - http://www.olimex.com/dev/pdf/arm-jtag.pdf
72 JTAG signals description:
73 PIN.1 (VTREF) Target voltage sense. Used to indicate the target’s operating voltage to thedebug tool.
74 PIN.2 (VTARGET) Target voltage. May be used to supply power to the debug tool.
75 PIN.3 (nTRST) JTAG TAP reset, this signal should be pulled up to Vcc in target board.
76 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.
77 *PIN.5 (TDI) JTAG serial data in, should be pulled up to Vcc on target board.
78 *PIN.7 (TMS) JTAG TAP Mode Select, should be pulled up to Vcc on target board.
79 *PIN.9 (TCK) JTAG clock.
80 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.
81 *PIN.13 (TDO) JTAG serial data out.
82 *PIN.15 (nSRST) Target system reset.
83 *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.
84 PIN.19 (DBGACK) Debug acknowledge. The ARM core acknowledges debug-mode inresponse to a DBGRQ input.
86 ****************************************************************/
89 /************************** JTAGARM7TDMI Primitives ****************************/
90 void jtag_goto_shift_ir() {
100 void jtag_goto_shift_dr() {
108 void jtag_reset_to_runtest_idle() {
117 jtag_arm_tcktock(); // now in Reset state
119 jtag_arm_tcktock(); // now in Run-Test/Idle state
122 void jtag_arm_tcktock() {
129 //! Set up the pins for JTAG mode.
141 // ! Start JTAG, setup pins, reset TAP and return IDCODE
142 unsigned long jtagarm7tdmi_start() {
144 //Known-good starting position.
145 //Might be unnecessary.
161 jtagarm7tdmi_resettap();
162 return jtagarm7tdmi_idcode();
166 //! Reset TAP State Machine
167 void jtagarm7tdmi_resettap(){ // PROVEN
169 jtag_reset_to_runtest_idle();
173 // NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR THE FUNCTIONAL EQUIVALENT
176 //! 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
177 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
179 unsigned long high = 1;
182 for (bit=(bitcount-1)/8; bit>0; bit--)
184 high <<= ((bitcount-1)%8);
189 for (bit = bitcount; bit > 0; bit--) {
190 /* write MOSI on trailing edge of previous clock */
198 SETTMS;//TMS high on last bit to exit.
202 /* read MISO on trailing edge */
208 for (bit = bitcount; bit > 0; bit--) {
209 /* write MOSI on trailing edge of previous clock */
214 word = (word & mask) << 1;
217 SETTMS;//TMS high on last bit to exit.
221 /* read MISO on trailing edge */
243 /************************************************************************
244 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
247 * * Scan Chain Select Register (4 bits_lsb)
248 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
249 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
250 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
251 ************************************************************************/
255 /************************** Basic JTAG Verb Commands *******************************/
256 //! Grab the core ID.
257 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
258 jtagarm7tdmi_resettap();
260 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
262 return jtagarmtransn(0,32, LSB, END, RETIDLE);
265 //! Connect Bypass Register to TDO/TDI
266 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
267 jtagarm7tdmi_resettap();
269 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
271 //! INTEST verb - do internal test
272 unsigned char jtagarm7tdmi_intest() {
273 jtagarm7tdmi_resettap();
275 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
279 unsigned char jtagarm7tdmi_extest() {
280 jtagarm7tdmi_resettap();
282 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
286 //unsigned long jtagarm7tdmi_sample() {
287 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
288 // return jtagtransn(0,32);
292 unsigned char jtagarm7tdmi_restart() {
293 jtagarm7tdmi_resettap();
295 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
298 //! ARM7TDMI_IR_CLAMP 0x5
299 //unsigned long jtagarm7tdmi_clamp() {
300 // jtagarm7tdmi_resettap();
302 // jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
304 // return jtagarmtransn(0, 32, LSB, END, RETIDLE);
307 //! ARM7TDMI_IR_HIGHZ 0x7
308 //unsigned char jtagarm7tdmi_highz() {
309 // jtagarm7tdmi_resettap();
311 // return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
314 //! define ARM7TDMI_IR_CLAMPZ 0x9
315 //unsigned char jtagarm7tdmi_clampz() {
316 // jtagarm7tdmi_resettap();
318 // return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
322 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
323 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
325 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
326 wise, when in debug state, the core will not be correctly isolated and intrusive
327 commands occur. Therefore, it is recommended to pass directly from the “Update”
328 state” to the “Select DR” state each time the “Update” state is reached.
330 unsigned long retval;
331 if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
333 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
335 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
336 current_chain = chain;
338 retval = current_chain;
339 // put in test mode...
341 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
346 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
347 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
348 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
354 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
355 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
356 unsigned long retval;
357 //jtagarm7tdmi_resettap(); // FIXME: DEBUG: seems necessary for some reason. ugh.
358 jtagarm7tdmi_scan_intest(1);
361 // if the next instruction is to run using MCLK (master clock), set TDI
365 count_sysspd_instr_since_debug++;
370 count_dbgspd_instr_since_debug++;
374 // Now shift in the 32 bits
375 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
376 //jtag_arm_tcktock();
382 unsigned long jtagarm7tdmi_nop(char breakpt){
383 //jtagarm7tdmi_scan_intest(1);
385 //return jtagarmtransn(ARM_INSTR_NOP, 32, LSB, END, NORETIDLE);
386 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
389 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
390 STR R0, [R0]; Save R0 before use
391 MOV R0, PC ; Copy PC into R0
392 STR R0, [R0]; Now save the PC in R0
393 BX PC ; Jump into ARM state
400 //! 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();
401 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
402 unsigned long retval = 0xff;
403 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
404 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
405 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
406 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
407 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
408 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
409 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
410 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
411 jtagarm7tdmi_resettap(); // seems necessary for some reason. ugh.
419 /************************* EmbeddedICE Primitives ****************************/
420 //! shifter for writing to chain2 (EmbeddedICE).
421 unsigned long eice_write(unsigned char reg, unsigned long data){
422 unsigned long retval, temp;
423 jtagarm7tdmi_scan_intest(2);
424 // Now shift in the 32 bits
426 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
427 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
428 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the WRITE bit
430 //SETTMS; // Last Bit - Exit UPDATE_DR
431 //// is this update a read/write or just read?
433 //jtag_arm_tcktock();
438 //! shifter for reading from chain2 (EmbeddedICE).
439 unsigned long eice_read(unsigned char reg){ // PROVEN
441 jtagarm7tdmi_scan_intest(2);
443 // send in the register address - 5 bits LSB
445 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
447 // clear TDI to select "read only"
448 jtagarmtransn(0, 1, LSB, END, RETIDLE);
451 // Now shift out the 32 bits
452 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
459 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
460 //! Grab debug register
461 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
462 //jtagarm7tdmi_resettap();
463 return eice_read(EICE_DBGSTATUS);
466 //! Grab debug register
467 unsigned long jtagarm7tdmi_get_dbgctrl() {
468 return eice_read(EICE_DBGCTRL);
471 //! Update debug register
472 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
473 return eice_write(EICE_DBGCTRL, bits);
478 //! Set and Enable Watchpoint 0
479 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
480 // store watchpoint info? - not right now
483 eice_write(EICE_WP0ADDR, addr); // write 0 in watchpoint 0 address
484 eice_write(EICE_WP0ADDRMASK, addrmask); // write 0xffffffff in watchpoint 0 address mask
485 eice_write(EICE_WP0DATA, data); // write 0 in watchpoint 0 data
486 eice_write(EICE_WP0DATAMASK, datamask); // write 0xffffffff in watchpoint 0 data mask
487 eice_write(EICE_WP0CTRL, ctrlmask); // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
488 eice_write(EICE_WP0CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
491 //! Set and Enable Watchpoint 1
492 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
493 // store watchpoint info? - not right now
496 eice_write(EICE_WP1ADDR, addr); // write 0 in watchpoint 1 address
497 eice_write(EICE_WP1ADDRMASK, addrmask); // write 0xffffffff in watchpoint 1 address mask
498 eice_write(EICE_WP1DATA, data); // write 0 in watchpoint 1 data
499 eice_write(EICE_WP1DATAMASK, datamask); // write 0xffffffff in watchpoint 1 data mask
500 eice_write(EICE_WP1CTRL, ctrl); // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
501 eice_write(EICE_WP1CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
504 //! Disable Watchpoint 0
505 void jtagarm7tdmi_disable_watchpoint0(){
506 eice_write(EICE_WP0CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
509 //! Disable Watchpoint 1
510 void jtagarm7tdmi_disable_watchpoint1(){
511 eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
516 /******************** Complex Commands **************************/
517 //! Push an instruction into the CPU pipeline
518 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
519 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
520 unsigned long retval;
522 cmddatalong[1] = jtagarm7tdmi_nop( 0);
523 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
524 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
525 cmddatalong[4] = jtagarm7tdmi_nop( 0);
526 cmddatalong[5] = jtagarm7tdmi_nop( 0);
527 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
528 cmddatalong[7] = jtagarm7tdmi_nop( 0);
529 cmddatalong[8] = jtagarm7tdmi_nop( 0);
530 cmddatalong[9] = jtagarm7tdmi_nop( 0);
531 retval = cmddatalong[9];
537 //! Push an instruction into the CPU pipeline
538 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
539 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
540 unsigned long retval;
542 cmddatalong[1] = jtagarm7tdmi_nop( 0);
543 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
544 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
545 cmddatalong[4] = jtagarm7tdmi_nop( 0);
546 cmddatalong[5] = jtagarm7tdmi_nop( 0);
547 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
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 instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
563 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
564 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
565 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
566 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
567 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
568 cmddatalong[5] = retval;
569 cmddatalong[6] = jtagarm7tdmi_nop( 0);
570 cmddatalong[7] = jtagarm7tdmi_nop( 0);
571 cmddatalong[8] = jtagarm7tdmi_nop( 0);
575 //! Retrieve a 32-bit Register value
576 unsigned long test_get_register(unsigned char reg) {
577 unsigned long retval = 0, instr;
578 // push nop into pipeline - clean out the pipeline...
579 cmddatalong[2] = jtagarm7tdmi_nop( 0);
581 instr = ARM_WRITE_REG | (reg<<12); // push STR Rx, [R14] into pipeline
582 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
583 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
584 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
585 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
586 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
587 cmddatalong[5] = retval;
588 cmddatalong[6] = jtagarm7tdmi_nop( 0);
589 cmddatalong[7] = jtagarm7tdmi_nop( 0);
590 cmddatalong[8] = jtagarm7tdmi_nop( 0);
594 //! Set a 32-bit Register value
595 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
596 unsigned long retval = 0, instr;
597 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
599 instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
600 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
601 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
602 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
604 cmddatalong[4] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus - execute state
605 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
607 if (reg == ARM_REG_PC){
608 cmddatalong[6] = jtagarm7tdmi_nop( 0);
609 cmddatalong[7] = jtagarm7tdmi_nop( 0);
611 cmddatalong[8] = jtagarm7tdmi_nop( 0);
613 retval = cmddatalong[5];
617 //! Set a 32-bit Register value
618 unsigned long test_set_register(unsigned char reg, unsigned long val) {
619 unsigned long retval = 0, instr;
620 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
622 instr = ARM_READ_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
623 cmddatalong[2] = jtagarm7tdmi_instr_primitive(instr, 0);
625 cmddatalong[3] = jtagarm7tdmi_instr_primitive(val+32, 0); // push 32-bit word on data bus - execute state
626 cmddatalong[4] = jtagarm7tdmi_instr_primitive(val+16, 0); // push 32-bit word on data bus - execute state
627 cmddatalong[5] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus - execute state
628 cmddatalong[6] = jtagarm7tdmi_instr_primitive(val-16, 0); // push 32-bit word on data bus - execute state
630 if (reg == ARM_REG_PC){
631 cmddatalong[7] = jtagarm7tdmi_nop( 0);
632 cmddatalong[8] = jtagarm7tdmi_nop( 0);
634 cmddatalong[9] = jtagarm7tdmi_instr_primitive(val-32, 0); // push 32-bit word on data bus - execute state
636 retval = cmddatalong[5];
642 //! Get all registers. Return an array
643 unsigned long* jtagarm7tdmi_get_registers() {
644 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
645 cmddatalong[2] = jtagarm7tdmi_nop( 0);
646 cmddatalong[3] = jtagarm7tdmi_nop( 0);
647 cmddatalong[4] = jtagarm7tdmi_nop( 0);
648 cmddatalong[5] = jtagarm7tdmi_nop( 0);
649 cmddatalong[6] = jtagarm7tdmi_nop( 0);
650 cmddatalong[7] = jtagarm7tdmi_nop( 0);
651 cmddatalong[8] = jtagarm7tdmi_nop( 0);
652 cmddatalong[9] = jtagarm7tdmi_nop( 0);
653 cmddatalong[10] = jtagarm7tdmi_nop( 0);
654 cmddatalong[11] = jtagarm7tdmi_nop( 0);
655 cmddatalong[12] = jtagarm7tdmi_nop( 0);
656 cmddatalong[13] = jtagarm7tdmi_nop( 0);
657 cmddatalong[14] = jtagarm7tdmi_nop( 0);
658 cmddatalong[15] = jtagarm7tdmi_nop( 0);
659 cmddatalong[16] = jtagarm7tdmi_nop( 0);
660 cmddatalong[17] = jtagarm7tdmi_nop( 0);
661 cmddatalong[18] = jtagarm7tdmi_nop( 0);
662 cmddatalong[19] = jtagarm7tdmi_nop( 0);
663 cmddatalong[20] = jtagarm7tdmi_nop( 0);
667 //! Retrieve the CPSR Register value
668 unsigned long jtagarm7tdmi_get_regCPSR() {
669 unsigned long retval = 0;
671 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
672 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0); // push MRS_R0, CPSR into pipeline
673 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
674 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
675 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
676 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
677 cmddatalong[6] = retval;
681 //! Retrieve the CPSR Register value
682 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
683 unsigned long retval = 0;
685 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
686 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0); // push MSR cpsr_cxsf, R0 into pipeline
687 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
688 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
690 retval = jtagarm7tdmi_instr_primitive(val, 0);// push 32-bit word on data bus
691 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
692 cmddatalong[4] = retval;
696 //! Write data to address - Assume TAP in run-test/idle state
697 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
698 unsigned long r0=0, r1=-1;
700 r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
701 r1 = jtagarm7tdmi_get_register(1);
702 jtagarm7tdmi_set_register(0, adr); // write address into R0
703 jtagarm7tdmi_set_register(1, data); // write data in R1
704 jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
705 jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
706 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
707 jtagarm7tdmi_nop( 0); // push nop into pipeline
708 jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
709 jtagarm7tdmi_set_register(0, r0);
716 //! Read data from address
717 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
718 unsigned long retval = 0;
719 unsigned long r0=0, r1=-1;
720 int waitcount = 0xfff;
722 r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
723 r1 = jtagarm7tdmi_get_register(1);
724 jtagarm7tdmi_set_register(0, adr); // write address into R0
725 jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
726 jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
727 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
728 jtagarm7tdmi_nop( 0); // push nop into pipeline
729 jtagarm7tdmi_restart(); // SHIFT_IR with RESTART instruction
731 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
732 while ((jtagarm7tdmi_get_dbgstate() & 9) == 0 && waitcount > 0){
739 retval = jtagarm7tdmi_get_register(1); // read memory value from R1 register
740 jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
741 jtagarm7tdmi_set_register(0, r0);
747 //! Read Program Counter
748 unsigned long jtagarm7tdmi_getpc(){
749 return jtagarm7tdmi_get_register(ARM_REG_PC);
752 //! Set Program Counter
753 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
754 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
757 //! Halt CPU - returns 0xffff if the operation fails to complete within
758 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
759 int waitcount = 0xfff;
761 // store watchpoint info? - not right now
762 eice_write(EICE_WP1ADDR, 0); // write 0 in watchpoint 1 address
763 eice_write(EICE_WP1ADDRMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 address mask
764 eice_write(EICE_WP1DATA, 0); // write 0 in watchpoint 1 data
765 eice_write(EICE_WP1DATAMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 data mask
766 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!? // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
767 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!? // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
769 // poll until debug status says the cpu is in debug mode
770 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount-- > 0){
773 eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
775 // store the debug state
776 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
777 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
778 count_dbgspd_instr_since_debug = 0;
779 count_sysspd_instr_since_debug = 0;
781 // get into ARM mode if the T flag is set (Thumb mode)
782 while (jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT && waitcount-- > 0) {
783 jtagarm7tdmi_setMode_ARM();
785 jtagarm7tdmi_resettap();
789 unsigned long jtagarm7tdmi_releasecpu(){
790 int waitcount = 0xfff;
792 // somehow determine what PC should be (a couple ways possible, calculations required)
793 jtagarm7tdmi_nop(0); // NOP
794 jtagarm7tdmi_nop(1); // NOP/BREAKPT
796 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){ // FIXME: FORNICATED! BX requires register, thus more instrs... could we get away with the same instruction but +1 to offset?
797 instr = ARM_INSTR_B_PC + 0x1000001 - (count_dbgspd_instr_since_debug) - (count_sysspd_instr_since_debug*3); //FIXME: make this right - can't we just do an a7solute b/bx?
798 jtagarm7tdmi_instr_primitive(instr,0);
800 instr = ARM_INSTR_B_PC + 0x1000000 - (count_dbgspd_instr_since_debug*4) - (count_sysspd_instr_since_debug*12);
801 jtagarm7tdmi_instr_primitive(instr,0);
805 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE); // VERB_RESTART
807 // wait until restart-bit set in debug state register
808 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
812 last_halt_debug_state = -1;
820 ///////////////////////////////////////////////////////////////////////////////////////////////////
821 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
822 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
823 register char blocks;
825 unsigned int i,val,mlop;
828 jtagarm7tdmi_resettap();
833 cmddatalong[0] = jtagarm7tdmi_start();
834 cmddatalong[2] = jtagarm7tdmi_haltcpu();
835 //jtagarm7tdmi_resettap();
836 cmddatalong[1] = jtagarm7tdmi_get_dbgstate();
838 // DEBUG: FIXME: NOT PART OF OPERATIONAL CODE
839 //for (mlop=2;mlop<4;mlop++){
840 // jtagarm7tdmi_set_register(mlop, 0x43424140);
842 /////////////////////////////////////////////
843 txdata(app,verb,0xc);
845 case JTAGARM7TDMI_READMEM:
847 blocks=(len>4?cmddata[4]:1);
851 txhead(app,verb,len);
855 jtagarm7tdmi_resettap();
858 val=jtagarm7tdmi_readmem(at);
862 serial_tx((val&0xFF00)>>8);
867 case JTAGARM7TDMI_GET_CHIP_ID:
868 jtagarm7tdmi_resettap();
869 cmddatalong[0] = jtagarm7tdmi_idcode();
874 case JTAGARM7TDMI_WRITEMEM:
876 jtagarm7tdmi_resettap();
877 jtagarm7tdmi_writemem(cmddatalong[0],
879 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
883 case JTAGARM7TDMI_HALTCPU:
884 cmddatalong[0] = jtagarm7tdmi_haltcpu();
887 case JTAGARM7TDMI_RELEASECPU:
888 jtagarm7tdmi_resettap();
889 cmddatalong[0] = jtagarm7tdmi_releasecpu();
892 //unimplemented functions
893 //case JTAGARM7TDMI_SETINSTRFETCH:
894 //case JTAGARM7TDMI_WRITEFLASH:
895 //case JTAGARM7TDMI_ERASEFLASH:
896 case JTAGARM7TDMI_SET_PC:
897 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
900 case JTAGARM7TDMI_GET_DEBUG_CTRL:
901 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
904 case JTAGARM7TDMI_SET_DEBUG_CTRL:
905 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
908 case JTAGARM7TDMI_GET_PC:
909 cmddatalong[0] = jtagarm7tdmi_getpc();
912 case JTAGARM7TDMI_GET_DEBUG_STATE:
913 //jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
914 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
917 //case JTAGARM7TDMI_GET_WATCHPOINT:
918 //case JTAGARM7TDMI_SET_WATCHPOINT:
919 case JTAGARM7TDMI_GET_REGISTER:
920 jtagarm7tdmi_resettap();
921 //cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
922 cmddatalong[0] = test_get_register(cmddata[0]);
925 case JTAGARM7TDMI_SET_REGISTER:
926 jtagarm7tdmi_resettap();
927 cmddatalong[0] = cmddatalong[1];
928 test_set_register(cmddata[0], cmddatalong[1]);
929 //jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
932 case JTAGARM7TDMI_GET_REGISTERS:
933 jtagarm7tdmi_resettap();
934 jtagarm7tdmi_get_registers();
937 //case JTAGARM7TDMI_SET_REGISTERS:
938 case JTAGARM7TDMI_DEBUG_INSTR:
939 jtagarm7tdmi_resettap();
940 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
943 //case JTAGARM7TDMI_STEP_INSTR:
944 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
945 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
946 case JTAGARM7TDMI_READ_FLASH_PAGE:
947 case JTAGARM7TDMI_MASS_ERASE_FLASH:
948 case JTAGARM7TDMI_PROGRAM_FLASH:
949 case JTAGARM7TDMI_LOCKCHIP:
950 case JTAGARM7TDMI_CHIP_ERASE:
952 // Really ARM specific stuff
953 case JTAGARM7TDMI_GET_CPSR:
954 jtagarm7tdmi_resettap();
955 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
958 case JTAGARM7TDMI_SET_CPSR:
959 jtagarm7tdmi_resettap();
960 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
963 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
964 jtagarm7tdmi_resettap();
965 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
968 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
969 jtagarm7tdmi_resettap();
970 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
973 case JTAGARM7TDMI_SET_MODE_THUMB:
974 case JTAGARM7TDMI_SET_MODE_ARM:
975 jtagarm7tdmi_resettap();
976 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
980 case 0xD0: // loopback test
981 jtagarm7tdmi_resettap();
982 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
985 case 0xD8: // EICE_READ
986 jtagarm7tdmi_resettap();
987 cmddatalong[0] = eice_read(cmddatalong[0]);
990 case 0xD9: // EICE_WRITE
991 jtagarm7tdmi_resettap();
992 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
995 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
996 jtagarm7tdmi_resettap();
997 jtagarm7tdmi_scan_intest(0);
998 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
999 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
1000 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
1001 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
1002 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
1003 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
1004 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
1005 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
1006 jtagarm7tdmi_resettap();
1007 jtagarm7tdmi_scan_intest(1);
1008 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
1009 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
1010 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
1011 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1012 jtagarm7tdmi_resettap();
1013 txdata(app,verb,48);
1017 jtaghandle(app,verb,len);