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() {
123 // ! Start JTAG, setup pins, reset TAP and return IDCODE
124 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();
146 return jtagarm7tdmi_idcode();
150 //! Reset TAP State Machine
151 void jtagarm7tdmi_resettap(){ // PROVEN
152 jtag_reset_to_runtest_idle();
155 //! 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
156 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
158 unsigned long high = 1;
161 for (bit=(bitcount-1)/8; bit>0; bit--)
163 high <<= ((bitcount-1)%8);
168 for (bit = bitcount; bit > 0; bit--) {
169 /* write MOSI on trailing edge of previous clock */
177 SETTMS;//TMS high on last bit to exit.
181 /* read MISO on trailing edge */
187 for (bit=bitcount; bit>0; bit++) {
188 /* write MOSI on trailing edge of previous clock */
193 word = (word & mask) << 1;
196 SETTMS;//TMS high on last bit to exit.
200 /* read MISO on trailing edge */
219 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
220 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ // PROVEN
221 unsigned long retval;
223 // if the next instruction is to run using MCLK (master clock), set TDI
227 count_sysspd_instr_since_debug++;
232 count_dbgspd_instr_since_debug++;
237 // Now shift in the 32 bits
238 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
244 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
245 STR R0, [R0]; Save R0 before use
246 MOV R0, PC ; Copy PC into R0
247 STR R0, [R0]; Now save the PC in R0
248 BX PC ; Jump into ARM state
255 //! 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();
256 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
257 unsigned long retval = 0xff;
258 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
259 jtagarm7tdmi_scan_intest(1);
260 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
261 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
262 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
263 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
264 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
265 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
274 /************************* EmbeddedICE Primitives ****************************/
275 //! shifter for writing to chain2 (EmbeddedICE).
276 unsigned long eice_write(unsigned char reg, unsigned long data){
277 unsigned long retval, temp;
278 jtagarm7tdmi_scan_intest(2);
279 // Now shift in the 32 bits
281 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
282 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
283 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the register address - 5 bits lsb
285 //SETTMS; // Last Bit - Exit UPDATE_DR
286 //// is this update a read/write or just read?
288 //jtag_arm_tcktock();
293 //! shifter for reading from chain2 (EmbeddedICE).
294 unsigned long eice_read(unsigned char reg){ // PROVEN
296 jtagarm7tdmi_scan_intest(2);
298 // send in the register address - 5 bits LSB
300 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
302 // clear TDI to select "read only"
303 jtagarmtransn(0, 1, LSB, END, RETIDLE);
306 // Now shift out the 32 bits
307 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
314 /************************************************************************
315 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
318 * * Scan Chain Select Register (4 bits_lsb)
319 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
320 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
321 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
322 ************************************************************************/
326 /************************** Basic JTAG Verb Commands *******************************/
327 //! Grab the core ID.
328 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
330 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
332 return jtagarmtransn(0,32, LSB, END, RETIDLE);
335 //! Connect Bypass Register to TDO/TDI
336 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
338 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
340 //! INTEST verb - do internal test
341 unsigned char jtagarm7tdmi_intest() {
343 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
347 unsigned char jtagarm7tdmi_extest() {
349 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
353 //unsigned long jtagarm7tdmi_sample() {
354 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
355 // return jtagtransn(0,32);
359 unsigned char jtagarm7tdmi_restart() {
361 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
364 //! ARM7TDMI_IR_CLAMP 0x5
365 unsigned long jtagarm7tdmi_clamp() {
367 jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
369 return jtagarmtransn(0, 32, LSB, END, RETIDLE);
372 //! ARM7TDMI_IR_HIGHZ 0x7
373 unsigned char jtagarm7tdmi_highz() {
375 return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
378 //! define ARM7TDMI_IR_CLAMPZ 0x9
379 unsigned char jtagarm7tdmi_clampz() {
381 return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
385 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
386 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
387 unsigned long retval;
388 if (current_chain == chain)
389 return current_chain;
390 jtagarm7tdmi_resettap(); // assumed already sane?
392 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
394 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
395 current_chain = chain;
396 jtagarm7tdmi_intest();
404 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
405 //! Grab debug register
406 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
407 jtagarm7tdmi_resettap();
408 jtagarm7tdmi_scan_intest(2); // select ICEBreaker
409 return eice_read(EICE_DBGSTATUS);
412 //! Grab debug register
413 unsigned long jtagarm7tdmi_get_dbgctrl() {
414 jtagarm7tdmi_resettap();
415 jtagarm7tdmi_scan_intest(2); // select ICEBreaker
416 return eice_read(EICE_DBGCTRL);
419 //! Update debug register
420 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
421 jtagarm7tdmi_resettap();
422 jtagarm7tdmi_scan_intest(2); // select ICEBreaker
423 return eice_write(EICE_DBGCTRL, bits);
428 //! Set and Enable Watchpoint 0
429 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
431 jtagarm7tdmi_scan_intest(2);
432 // store watchpoint info? - not right now
433 // write 0 in watchpoint 0 address
434 eice_write(EICE_WP0ADDR, addr);
435 // write 0xffffffff in watchpoint 0 address mask
436 eice_write(EICE_WP0ADDRMASK, addrmask);
437 // write 0 in watchpoint 0 data
438 eice_write(EICE_WP0DATA, data);
439 // write 0xffffffff in watchpoint 0 data mask
440 eice_write(EICE_WP0DATAMASK, datamask);
441 // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
442 eice_write(EICE_WP0CTRL, ctrlmask);
443 // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
444 eice_write(EICE_WP0CTRLMASK, ctrlmask);
447 //! Set and Enable Watchpoint 1
448 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
450 jtagarm7tdmi_scan_intest(2);
451 // store watchpoint info? - not right now
452 // write 0 in watchpoint 1 address
453 eice_write(EICE_WP1ADDR, addr);
454 // write 0xffffffff in watchpoint 1 address mask
455 eice_write(EICE_WP1ADDRMASK, addrmask);
456 // write 0 in watchpoint 1 data
457 eice_write(EICE_WP1DATA, data);
458 // write 0xffffffff in watchpoint 1 data mask
459 eice_write(EICE_WP1DATAMASK, datamask);
460 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
461 eice_write(EICE_WP1CTRL, ctrl);
462 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
463 eice_write(EICE_WP1CTRLMASK, ctrlmask);
466 //! Disable Watchpoint 0
467 void jtagarm7tdmi_disable_watchpoint0(){
469 jtagarm7tdmi_scan_intest(2);
470 // write 0 in watchpoint 0 control value - disables watchpoint 0
471 eice_write(EICE_WP0CTRL, 0x0);
474 //! Disable Watchpoint 1
475 void jtagarm7tdmi_disable_watchpoint1(){
477 jtagarm7tdmi_scan_intest(2);
478 // write 0 in watchpoint 0 control value - disables watchpoint 0
479 eice_write(EICE_WP1CTRL, 0x0);
484 /******************** Complex Commands **************************/
485 //! Push an instruction into the CPU pipeline
486 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
487 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
488 unsigned long retval;
490 jtagarm7tdmi_scan_intest(1);
492 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
493 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,systemspeed);
494 // write 32-bit instruction code into DR
495 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
496 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
497 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
499 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
500 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
501 cmddatalong[8] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
502 cmddatalong[9] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
503 retval = cmddatalong[9];
509 //! Push an instruction into the CPU pipeline
510 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
511 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
512 unsigned long retval;
514 jtagarm7tdmi_scan_intest(1);
516 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
517 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,systemspeed);
518 // write 32-bit instruction code into DR
519 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
520 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
521 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
523 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
524 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
525 retval = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
526 cmddatalong[9] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
527 cmddatalong[8] = retval;
532 //! Retrieve a 32-bit Register value
533 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
534 unsigned long retval = 0, instr;
535 //JTAGARM7TDMI_RESETTAP();
536 // select chain 1, automatically put in INTEST
537 jtagarm7tdmi_scan_intest(1);
538 instr = ARM_INSTR_STR_Rx_r14 + ((reg<<12)&0xf00);
539 //retval = jtagarm7tdmi_exec(instr, 0);
540 // push STR_Rx, [R14] into pipeline
541 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
542 // push nop into pipeline - fetched
543 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
544 // push nop into pipeline - decoded
545 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
546 // push nop into pipeline - executed
547 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
548 // recover 32-bit word
549 //retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
550 retval = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
551 cmddatalong[5] = retval;
552 cmddatalong[6] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
553 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
554 cmddatalong[8] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
558 //! Set a 32-bit Register value
559 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
560 unsigned long retval = 0, instr;
561 //jtagarm7tdmi_resettap();
563 jtagarm7tdmi_scan_intest(1);
564 instr = ARM_INSTR_LDR_Rx_r14 + ((reg<<12)&0xf00);
565 //retval = jtagarm7tdmi_exec(instr, 0);
566 // push STR_Rx, [R14] into pipeline
567 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
568 // push nop into pipeline - fetched
569 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
570 // push nop into pipeline - decoded
571 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
573 // push 32-bit word on data bus - execute state
574 //retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
575 cmddatalong[3] = jtagarm7tdmi_instr_primitive(val, 0);
576 // push nop into pipeline - executed
577 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
578 if (reg == ARM_REG_PC){
579 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
580 cmddatalong[6] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
582 retval = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
583 cmddatalong[7] = retval;
589 //! Get all registers. Return an array
590 unsigned long* jtagarm7tdmi_get_registers() {
591 jtagarm7tdmi_scan_intest(1);
592 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
593 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
594 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
595 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
596 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
597 cmddatalong[6] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
598 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
599 cmddatalong[8] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
600 cmddatalong[9] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
601 cmddatalong[10] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
602 cmddatalong[11] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
603 cmddatalong[12] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
604 cmddatalong[13] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
605 cmddatalong[14] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
606 cmddatalong[15] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
607 cmddatalong[16] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
608 cmddatalong[17] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
609 cmddatalong[18] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
610 cmddatalong[19] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
611 cmddatalong[20] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
615 //! Retrieve the CPSR Register value
616 unsigned long jtagarm7tdmi_get_regCPSR() {
617 unsigned long retval = 0;
619 cmddatalong[1] = jtagarm7tdmi_scan_intest(1);
621 // push STR_Rx, [R14] into pipeline
622 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0);
623 // push nop into pipeline - fetched
624 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
625 // push nop into pipeline - decoded
626 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
627 // push nop into pipeline - executed
628 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
629 // recover 32-bit word
630 retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
631 cmddatalong[6] = retval;
635 //! Retrieve the CPSR Register value
636 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
637 unsigned long retval = 0;
639 jtagarm7tdmi_scan_intest(1);
641 // push MSR cpsr_cxsf, R0 into pipeline
642 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0);
643 // push nop into pipeline - fetched
644 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
645 // push nop into pipeline - decoded
646 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
648 // push 32-bit word on data bus
649 retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
650 // push nop into pipeline - executed
651 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
652 cmddatalong[4] = retval;
656 //! Write data to address - Assume TAP in run-test/idle state
657 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
658 unsigned long r0=0, r1=-1;
660 jtagarm7tdmi_scan_intest(1);
663 r0 = jtagarm7tdmi_get_register(0);
664 r1 = jtagarm7tdmi_get_register(1);
665 // write address into R0
666 jtagarm7tdmi_set_register(0, adr);
668 jtagarm7tdmi_set_register(1, data);
669 //retval = jtagarm7tdmi_exec(ARM_INSTR_LDR_R1_r0_4,1);
670 // push nop into pipeline to "clean" it ???
671 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
672 // push nop into pipeline with BREAKPT set
673 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 1);
674 // push LDR R1, R0, #4 into instruction pipeline
675 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
676 // push nop into pipeline
677 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
679 jtagarm7tdmi_set_register(1, r1);
680 jtagarm7tdmi_set_register(0, r0);
684 //! Read data from address
685 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
686 unsigned long retval = 0;
687 unsigned long r0=0, r1=-1;
688 int waitcount = 0xfff;
690 jtagarm7tdmi_scan_intest(1);
693 // store R0 and R1 - not yet...
694 r0 = jtagarm7tdmi_get_register(0);
695 r1 = jtagarm7tdmi_get_register(1);
696 // write address into R0
697 jtagarm7tdmi_set_register(0, adr);
698 // push nop into pipeline to "clean" it ???
699 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
700 // push nop into pipeline with BREAKPT set
701 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 1);
702 // push LDR R1, R0, #4 into instruction pipeline
703 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
704 // push nop into pipeline
705 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
706 // SHIFT_IR with RESTART instruction
707 jtagarm7tdmi_restart();
708 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
709 while ((jtagarm7tdmi_get_dbgstate() & 1) == 0 && waitcount > 0){
713 if (waitcount == 0xffff){
716 retval = jtagarm7tdmi_get_register(1);
717 // read memory value from R1 register
719 jtagarm7tdmi_set_register(1, r1);
720 jtagarm7tdmi_set_register(0, r0);
726 //! Read Program Counter
727 unsigned long jtagarm7tdmi_getpc(){
728 return jtagarm7tdmi_get_register(ARM_REG_PC);
731 //! Set Program Counter
732 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
733 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
736 //! Halt CPU - returns 0xffff if the operation fails to complete within
737 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
738 int waitcount = 0xfff;
740 jtagarm7tdmi_scan_intest(2);
741 // store watchpoint info? - not right now
742 // write 0 in watchpoint 1 address
743 eice_write(EICE_WP1ADDR, 0);
744 // write 0xffffffff in watchpoint 1 address mask
745 eice_write(EICE_WP1ADDRMASK, 0xffffffff);
746 // write 0 in watchpoint 1 data
747 eice_write(EICE_WP1DATA, 0);
748 // write 0xffffffff in watchpoint 1 data mask
749 eice_write(EICE_WP1DATAMASK, 0xffffffff);
750 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
751 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!?
752 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
753 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!?
754 // poll until debug status says the cpu is in debug mode
755 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount > 0){
759 // write 0 in watchpoint 0 control value - disables watchpoint 0
760 eice_write(EICE_WP1CTRL, 0x0);
762 // store the debug state
763 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
764 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
765 count_dbgspd_instr_since_debug = 0;
766 count_sysspd_instr_since_debug = 0;
767 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
768 jtagarm7tdmi_setMode_ARM();
773 unsigned long jtagarm7tdmi_releasecpu(){
774 int waitcount = 0xfff;
776 // somehow determine what PC should be (a couple ways possible, calculations required)
777 jtagarm7tdmi_scan_intest(1);
779 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,0);
781 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,1);
783 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){ // FIXME: FORKED.
784 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?
785 jtagarm7tdmi_instr_primitive(instr,0);
787 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?
788 jtagarm7tdmi_instr_primitive(instr,0);
792 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE);
794 // wait until restart-bit set in debug state register
795 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
799 last_halt_debug_state = -1;
818 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
819 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
820 register char blocks;
825 //jtagarm7tdmi_resettap();
830 cmddatalong[0] = jtagarm7tdmi_start();
831 cmddatalong[1] = jtagarm7tdmi_haltcpu();
832 //jtagarm7tdmi_resettap();
833 txdata(app,verb,0x8);
835 case JTAGARM7TDMI_READMEM:
837 blocks=(len>4?cmddata[4]:1);
841 txhead(app,verb,len);
845 jtagarm7tdmi_resettap();
848 val=jtagarm7tdmi_readmem(at);
852 serial_tx((val&0xFF00)>>8);
857 case JTAGARM7TDMI_GET_CHIP_ID:
858 jtagarm7tdmi_resettap();
859 cmddatalong[0] = jtagarm7tdmi_idcode();
864 case JTAGARM7TDMI_WRITEMEM:
866 jtagarm7tdmi_resettap();
867 jtagarm7tdmi_writemem(cmddatalong[0],
869 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
873 case JTAGARM7TDMI_HALTCPU:
874 cmddatalong[0] = jtagarm7tdmi_haltcpu();
877 case JTAGARM7TDMI_RELEASECPU:
878 jtagarm7tdmi_resettap();
879 cmddatalong[0] = jtagarm7tdmi_releasecpu();
882 //unimplemented functions
883 //case JTAGARM7TDMI_SETINSTRFETCH:
884 //case JTAGARM7TDMI_WRITEFLASH:
885 //case JTAGARM7TDMI_ERASEFLASH:
886 case JTAGARM7TDMI_SET_PC:
887 jtagarm7tdmi_resettap();
888 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
891 case JTAGARM7TDMI_GET_DEBUG_CTRL:
892 jtagarm7tdmi_resettap();
893 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
896 case JTAGARM7TDMI_SET_DEBUG_CTRL:
897 jtagarm7tdmi_resettap();
898 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
901 case JTAGARM7TDMI_GET_PC:
902 jtagarm7tdmi_resettap();
903 cmddatalong[0] = jtagarm7tdmi_getpc();
906 case JTAGARM7TDMI_GET_DEBUG_STATE:
907 jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
908 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
911 //case JTAGARM7TDMI_GET_WATCHPOINT:
912 //case JTAGARM7TDMI_SET_WATCHPOINT:
913 case JTAGARM7TDMI_GET_REGISTER:
914 jtagarm7tdmi_resettap();
915 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
918 case JTAGARM7TDMI_SET_REGISTER:
919 jtagarm7tdmi_resettap();
920 cmddatalong[0] = cmddatalong[1];
921 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
924 case JTAGARM7TDMI_GET_REGISTERS:
925 jtagarm7tdmi_resettap();
926 jtagarm7tdmi_get_registers();
929 //case JTAGARM7TDMI_SET_REGISTERS:
930 case JTAGARM7TDMI_DEBUG_INSTR:
931 jtagarm7tdmi_resettap();
932 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
935 case JTAGARM7TDMI_STEP_INSTR:
936 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
937 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
938 case JTAGARM7TDMI_READ_FLASH_PAGE:
939 case JTAGARM7TDMI_MASS_ERASE_FLASH:
940 case JTAGARM7TDMI_PROGRAM_FLASH:
941 case JTAGARM7TDMI_LOCKCHIP:
942 case JTAGARM7TDMI_CHIP_ERASE:
944 // Really ARM specific stuff
945 case JTAGARM7TDMI_GET_CPSR:
946 jtagarm7tdmi_resettap();
947 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
950 case JTAGARM7TDMI_SET_CPSR:
951 jtagarm7tdmi_resettap();
952 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
955 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
956 jtagarm7tdmi_resettap();
957 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
960 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
961 jtagarm7tdmi_resettap();
962 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
965 case JTAGARM7TDMI_SET_MODE_THUMB:
966 case JTAGARM7TDMI_SET_MODE_ARM:
967 jtagarm7tdmi_resettap();
968 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
972 case 0xD0: // loopback test
973 jtagarm7tdmi_resettap();
974 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
977 case 0xD1: // Set Scan Chain
978 jtagarm7tdmi_resettap();
979 cmddatalong[1] = jtagarm7tdmi_scan_intest(cmddataword[0]);
981 cmddatalong[0] = jtagarmtransn(cmddataword[2], 32, LSB, END, RETIDLE);
985 case 0xD2: // DBGSTATE
986 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
989 case 0xD3: // EXECUTE
990 jtagarm7tdmi_resettap();
991 //cmddatalong[0] = jtagarm7tdmi_exec(cmddatalong[0], EXECNOPARM, 0);
992 cmddatalong[0] = test_exec(cmddatalong[0], EXECNOPARM, 0);
995 case 0xD4: // GET REGISTER
996 jtagarm7tdmi_resettap();
997 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
1000 case 0xD5: // SET REGISTER
1001 jtagarm7tdmi_resettap();
1002 cmddatalong[0] = jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
1003 txdata(app,verb,40);
1005 case 0xD6: // SHIFT_DR
1007 cmddatalong[0] = jtagarmtransn(cmddatalong[0], 32, LSB, END, RETIDLE);
1010 case 0xD7: // INSTR_PRIMITIVE
1011 jtagarm7tdmi_resettap();
1013 jtagarm7tdmi_scan_intest(1);
1014 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0], 0);
1017 case 0xD8: // EICE_READ
1018 jtagarm7tdmi_resettap();
1019 cmddatalong[0] = eice_read(cmddatalong[0]);
1022 case 0xD9: // EICE_WRITE
1023 jtagarm7tdmi_resettap();
1024 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
1027 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
1028 jtagarm7tdmi_resettap();
1029 jtagarm7tdmi_scan_intest(0);
1030 cmddatalong[0] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
1031 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
1032 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
1033 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
1034 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, MSB, NOEND, NORETIDLE);
1035 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
1036 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
1037 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
1038 jtagarm7tdmi_resettap();
1039 jtagarm7tdmi_scan_intest(1);
1040 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
1041 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
1042 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
1043 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1044 txdata(app,verb,48);
1046 case 0xDB: // WHATEVER IR, READ 32
1047 jtagarm7tdmi_resettap();
1049 jtagarmtransn(cmddata[0], 4, LSB, END, NORETIDLE);
1051 cmddatalong[0] = jtagarmtransn(cmddatalong[1], 32, LSB, END, RETIDLE);
1056 jtaghandle(app,verb,len);