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 // ! Start JTAG, setup pins, reset TAP and return IDCODE
130 unsigned long jtagarm7tdmi_start() {
132 //Known-good starting position.
133 //Might be unnecessary.
149 jtagarm7tdmi_resettap();
150 return jtagarm7tdmi_idcode();
154 //! Reset TAP State Machine
155 void jtagarm7tdmi_resettap(){ // PROVEN
157 jtag_reset_to_runtest_idle();
161 // NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR THE FUNCTIONAL EQUIVALENT
164 //! 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
165 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
167 unsigned long high = 1;
170 for (bit=(bitcount-1)/16; bit>0; bit--)
172 high <<= ((bitcount-1)%16);
177 for (bit = bitcount; bit > 0; bit--) {
178 /* write MOSI on trailing edge of previous clock */
186 SETTMS;//TMS high on last bit to exit.
190 /* read MISO on trailing edge */
196 for (bit=bitcount; bit>0; bit++) {
197 /* write MOSI on trailing edge of previous clock */
202 word = (word & mask) << 1;
205 SETTMS;//TMS high on last bit to exit.
209 /* read MISO on trailing edge */
231 /************************************************************************
232 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
235 * * Scan Chain Select Register (4 bits_lsb)
236 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
237 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
238 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
239 ************************************************************************/
243 /************************** Basic JTAG Verb Commands *******************************/
244 //! Grab the core ID.
245 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
246 jtagarm7tdmi_resettap();
248 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
250 return jtagarmtransn(0,32, LSB, END, RETIDLE);
253 //! Connect Bypass Register to TDO/TDI
254 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
255 jtagarm7tdmi_resettap();
257 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
259 //! INTEST verb - do internal test
260 unsigned char jtagarm7tdmi_intest() {
261 jtagarm7tdmi_resettap();
263 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
267 unsigned char jtagarm7tdmi_extest() {
268 jtagarm7tdmi_resettap();
270 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
274 //unsigned long jtagarm7tdmi_sample() {
275 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
276 // return jtagtransn(0,32);
280 unsigned char jtagarm7tdmi_restart() {
281 jtagarm7tdmi_resettap();
283 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
286 //! ARM7TDMI_IR_CLAMP 0x5
287 //unsigned long jtagarm7tdmi_clamp() {
288 // jtagarm7tdmi_resettap();
290 // jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
292 // return jtagarmtransn(0, 32, LSB, END, RETIDLE);
295 //! ARM7TDMI_IR_HIGHZ 0x7
296 //unsigned char jtagarm7tdmi_highz() {
297 // jtagarm7tdmi_resettap();
299 // return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
302 //! define ARM7TDMI_IR_CLAMPZ 0x9
303 //unsigned char jtagarm7tdmi_clampz() {
304 // jtagarm7tdmi_resettap();
306 // return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
310 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
311 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
313 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
314 wise, when in debug state, the core will not be correctly isolated and intrusive
315 commands occur. Therefore, it is recommended to pass directly from the “Update”
316 state” to the “Select DR” state each time the “Update” state is reached.
318 unsigned long retval;
319 if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
321 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
323 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
324 current_chain = chain;
326 retval = current_chain;
327 // put in test mode...
329 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
334 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
335 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
336 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
342 //! push an instruction into the pipeline - Assumes scan-chain 1 is already INTEST
343 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
344 unsigned long retval;
345 jtagarm7tdmi_scan_intest(1);
348 // if the next instruction is to run using MCLK (master clock), set TDI
352 count_sysspd_instr_since_debug++;
357 count_dbgspd_instr_since_debug++;
361 // Now shift in the 32 bits
362 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
363 //jtag_arm_tcktock();
369 unsigned long jtagarm7tdmi_nop(char breakpt){
370 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
373 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
374 STR R0, [R0]; Save R0 before use
375 MOV R0, PC ; Copy PC into R0
376 STR R0, [R0]; Now save the PC in R0
377 BX PC ; Jump into ARM state
384 //! 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();
385 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
386 unsigned long retval = 0xff;
387 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
388 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
389 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
390 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
391 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
392 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
393 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
394 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
396 jtagarm7tdmi_resettap(); // seems necessary for some reason. ugh.
404 /************************* EmbeddedICE Primitives ****************************/
405 //! shifter for writing to chain2 (EmbeddedICE).
406 unsigned long eice_write(unsigned char reg, unsigned long data){
407 unsigned long retval, temp;
408 jtagarm7tdmi_scan_intest(2);
409 // Now shift in the 32 bits
411 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
412 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
413 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the WRITE bit
415 //SETTMS; // Last Bit - Exit UPDATE_DR
416 //// is this update a read/write or just read?
418 //jtag_arm_tcktock();
423 //! shifter for reading from chain2 (EmbeddedICE).
424 unsigned long eice_read(unsigned char reg){ // PROVEN
426 jtagarm7tdmi_scan_intest(2);
428 // send in the register address - 5 bits LSB
430 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
432 // clear TDI to select "read only"
433 jtagarmtransn(0, 1, LSB, END, RETIDLE);
436 // Now shift out the 32 bits
437 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
444 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
445 //! Grab debug register
446 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
447 //jtagarm7tdmi_resettap();
448 return eice_read(EICE_DBGSTATUS);
451 //! Grab debug register
452 unsigned long jtagarm7tdmi_get_dbgctrl() {
453 return eice_read(EICE_DBGCTRL);
456 //! Update debug register
457 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
458 return eice_write(EICE_DBGCTRL, bits);
463 //! Set and Enable Watchpoint 0
464 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
465 // store watchpoint info? - not right now
468 eice_write(EICE_WP0ADDR, addr); // write 0 in watchpoint 0 address
469 eice_write(EICE_WP0ADDRMASK, addrmask); // write 0xffffffff in watchpoint 0 address mask
470 eice_write(EICE_WP0DATA, data); // write 0 in watchpoint 0 data
471 eice_write(EICE_WP0DATAMASK, datamask); // write 0xffffffff in watchpoint 0 data mask
472 eice_write(EICE_WP0CTRL, ctrlmask); // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
473 eice_write(EICE_WP0CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
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 eice_write(EICE_WP1ADDR, addr); // write 0 in watchpoint 1 address
482 eice_write(EICE_WP1ADDRMASK, addrmask); // write 0xffffffff in watchpoint 1 address mask
483 eice_write(EICE_WP1DATA, data); // write 0 in watchpoint 1 data
484 eice_write(EICE_WP1DATAMASK, datamask); // write 0xffffffff in watchpoint 1 data mask
485 eice_write(EICE_WP1CTRL, ctrl); // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
486 eice_write(EICE_WP1CTRLMASK, ctrlmask); // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
489 //! Disable Watchpoint 0
490 void jtagarm7tdmi_disable_watchpoint0(){
491 eice_write(EICE_WP0CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
494 //! Disable Watchpoint 1
495 void jtagarm7tdmi_disable_watchpoint1(){
496 eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
501 /******************** Complex Commands **************************/
502 //! Push an instruction into the CPU pipeline
503 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
504 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
505 unsigned long retval;
507 cmddatalong[1] = jtagarm7tdmi_nop( 0);
508 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
509 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
510 cmddatalong[4] = jtagarm7tdmi_nop( 0);
511 cmddatalong[5] = jtagarm7tdmi_nop( 0);
512 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
513 cmddatalong[7] = jtagarm7tdmi_nop( 0);
514 cmddatalong[8] = jtagarm7tdmi_nop( 0);
515 cmddatalong[9] = jtagarm7tdmi_nop( 0);
516 retval = cmddatalong[9];
522 //! Push an instruction into the CPU pipeline
523 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
524 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
525 unsigned long retval;
527 cmddatalong[1] = jtagarm7tdmi_nop( 0);
528 cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
529 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
530 cmddatalong[4] = jtagarm7tdmi_nop( 0);
531 cmddatalong[5] = jtagarm7tdmi_nop( 0);
532 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
533 cmddatalong[7] = jtagarm7tdmi_nop( 0);
534 retval = jtagarm7tdmi_nop( 0);
535 cmddatalong[9] = jtagarm7tdmi_nop( 0);
536 cmddatalong[8] = retval;
541 //! Retrieve a 32-bit Register value
542 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
543 unsigned long retval = 0, instr;
544 // push nop into pipeline - clean out the pipeline...
545 cmddatalong[2] = jtagarm7tdmi_nop( 0);
547 instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
548 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
549 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
550 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
551 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
552 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
553 cmddatalong[5] = retval;
554 cmddatalong[6] = jtagarm7tdmi_nop( 0);
555 cmddatalong[7] = jtagarm7tdmi_nop( 0);
556 cmddatalong[8] = jtagarm7tdmi_nop( 0);
560 //! Set a 32-bit Register value
561 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
562 unsigned long retval = 0, instr;
563 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
565 instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
566 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
567 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
568 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
570 cmddatalong[4] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus - execute state
571 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
573 if (reg == ARM_REG_PC){
574 cmddatalong[6] = jtagarm7tdmi_nop( 0);
575 cmddatalong[7] = jtagarm7tdmi_nop( 0);
577 cmddatalong[8] = jtagarm7tdmi_nop( 0);
579 retval = cmddatalong[5];
585 //! Get all registers. Return an array
586 unsigned long* jtagarm7tdmi_get_registers() {
587 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
588 cmddatalong[2] = jtagarm7tdmi_nop( 0);
589 cmddatalong[3] = jtagarm7tdmi_nop( 0);
590 cmddatalong[4] = jtagarm7tdmi_nop( 0);
591 cmddatalong[5] = jtagarm7tdmi_nop( 0);
592 cmddatalong[6] = jtagarm7tdmi_nop( 0);
593 cmddatalong[7] = jtagarm7tdmi_nop( 0);
594 cmddatalong[8] = jtagarm7tdmi_nop( 0);
595 cmddatalong[9] = jtagarm7tdmi_nop( 0);
596 cmddatalong[10] = jtagarm7tdmi_nop( 0);
597 cmddatalong[11] = jtagarm7tdmi_nop( 0);
598 cmddatalong[12] = jtagarm7tdmi_nop( 0);
599 cmddatalong[13] = jtagarm7tdmi_nop( 0);
600 cmddatalong[14] = jtagarm7tdmi_nop( 0);
601 cmddatalong[15] = jtagarm7tdmi_nop( 0);
602 cmddatalong[16] = jtagarm7tdmi_nop( 0);
603 cmddatalong[17] = jtagarm7tdmi_nop( 0);
604 cmddatalong[18] = jtagarm7tdmi_nop( 0);
605 cmddatalong[19] = jtagarm7tdmi_nop( 0);
606 cmddatalong[20] = jtagarm7tdmi_nop( 0);
610 //! Retrieve the CPSR Register value
611 unsigned long jtagarm7tdmi_get_regCPSR() {
612 unsigned long retval = 0;
614 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
615 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0); // push MRS_R0, CPSR into pipeline
616 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
617 cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
618 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
619 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
620 cmddatalong[6] = retval;
624 //! Retrieve the CPSR Register value
625 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
626 unsigned long retval = 0;
628 cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
629 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0); // push MSR cpsr_cxsf, R0 into pipeline
630 cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
631 cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
633 retval = jtagarm7tdmi_instr_primitive(val, 0);// push 32-bit word on data bus
634 cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
635 cmddatalong[4] = retval;
639 //! Write data to address - Assume TAP in run-test/idle state
640 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
641 unsigned long r0=0, r1=-1;
643 r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
644 r1 = jtagarm7tdmi_get_register(1);
645 jtagarm7tdmi_set_register(0, adr); // write address into R0
646 jtagarm7tdmi_set_register(1, data); // write data in R1
647 jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
648 jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
649 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
650 jtagarm7tdmi_nop( 0); // push nop into pipeline
651 jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
652 jtagarm7tdmi_set_register(0, r0);
659 //! Read data from address
660 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
661 unsigned long retval = 0;
662 unsigned long r0=0, r1=-1;
663 int waitcount = 0xfff;
665 r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
666 r1 = jtagarm7tdmi_get_register(1);
667 jtagarm7tdmi_set_register(0, adr); // write address into R0
668 jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
669 jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
670 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
671 jtagarm7tdmi_nop( 0); // push nop into pipeline
672 jtagarm7tdmi_restart(); // SHIFT_IR with RESTART instruction
674 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
675 while ((jtagarm7tdmi_get_dbgstate() & 9) == 0 && waitcount > 0){
679 if (waitcount == 0xffff){
682 retval = jtagarm7tdmi_get_register(1); // read memory value from R1 register
683 jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
684 jtagarm7tdmi_set_register(0, r0);
690 //! Read Program Counter
691 unsigned long jtagarm7tdmi_getpc(){
692 return jtagarm7tdmi_get_register(ARM_REG_PC);
695 //! Set Program Counter
696 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
697 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
700 //! Halt CPU - returns 0xffff if the operation fails to complete within
701 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
702 int waitcount = 0xfff;
704 // store watchpoint info? - not right now
705 eice_write(EICE_WP1ADDR, 0); // write 0 in watchpoint 1 address
706 eice_write(EICE_WP1ADDRMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 address mask
707 eice_write(EICE_WP1DATA, 0); // write 0 in watchpoint 1 data
708 eice_write(EICE_WP1DATAMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 data mask
709 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!? // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
710 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
712 // poll until debug status says the cpu is in debug mode
713 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount-- > 0){
716 eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
718 // store the debug state
719 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
720 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
721 count_dbgspd_instr_since_debug = 0;
722 count_sysspd_instr_since_debug = 0;
724 // get into ARM mode if the T flag is set (Thumb mode)
725 while (jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT && waitcount-- > 0) {
726 jtagarm7tdmi_setMode_ARM();
731 unsigned long jtagarm7tdmi_releasecpu(){
732 int waitcount = 0xfff;
734 // somehow determine what PC should be (a couple ways possible, calculations required)
735 jtagarm7tdmi_nop(0); // NOP
736 jtagarm7tdmi_nop(1); // NOP/BREAKPT
738 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?
739 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?
740 jtagarm7tdmi_instr_primitive(instr,0);
742 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?
743 jtagarm7tdmi_instr_primitive(instr,0);
747 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE); // VERB_RESTART
749 // wait until restart-bit set in debug state register
750 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
754 last_halt_debug_state = -1;
762 ///////////////////////////////////////////////////////////////////////////////////////////////////
763 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
764 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
765 register char blocks;
770 jtagarm7tdmi_resettap();
775 cmddatalong[0] = jtagarm7tdmi_start();
776 cmddatalong[2] = jtagarm7tdmi_haltcpu();
777 //jtagarm7tdmi_resettap();
778 cmddatalong[1] = jtagarm7tdmi_get_dbgstate();
780 txdata(app,verb,0xc);
782 case JTAGARM7TDMI_READMEM:
784 blocks=(len>4?cmddata[4]:1);
788 txhead(app,verb,len);
792 jtagarm7tdmi_resettap();
795 val=jtagarm7tdmi_readmem(at);
799 serial_tx((val&0xFF00)>>8);
804 case JTAGARM7TDMI_GET_CHIP_ID:
805 jtagarm7tdmi_resettap();
806 cmddatalong[0] = jtagarm7tdmi_idcode();
811 case JTAGARM7TDMI_WRITEMEM:
813 jtagarm7tdmi_resettap();
814 jtagarm7tdmi_writemem(cmddatalong[0],
816 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
820 case JTAGARM7TDMI_HALTCPU:
821 cmddatalong[0] = jtagarm7tdmi_haltcpu();
824 case JTAGARM7TDMI_RELEASECPU:
825 jtagarm7tdmi_resettap();
826 cmddatalong[0] = jtagarm7tdmi_releasecpu();
829 //unimplemented functions
830 //case JTAGARM7TDMI_SETINSTRFETCH:
831 //case JTAGARM7TDMI_WRITEFLASH:
832 //case JTAGARM7TDMI_ERASEFLASH:
833 case JTAGARM7TDMI_SET_PC:
834 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
837 case JTAGARM7TDMI_GET_DEBUG_CTRL:
838 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
841 case JTAGARM7TDMI_SET_DEBUG_CTRL:
842 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
845 case JTAGARM7TDMI_GET_PC:
846 cmddatalong[0] = jtagarm7tdmi_getpc();
849 case JTAGARM7TDMI_GET_DEBUG_STATE:
850 //jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
851 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
854 //case JTAGARM7TDMI_GET_WATCHPOINT:
855 //case JTAGARM7TDMI_SET_WATCHPOINT:
856 case JTAGARM7TDMI_GET_REGISTER:
857 jtagarm7tdmi_resettap();
858 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
861 case JTAGARM7TDMI_SET_REGISTER:
862 jtagarm7tdmi_resettap();
863 cmddatalong[0] = cmddatalong[1];
864 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
867 case JTAGARM7TDMI_GET_REGISTERS:
868 jtagarm7tdmi_resettap();
869 jtagarm7tdmi_get_registers();
872 //case JTAGARM7TDMI_SET_REGISTERS:
873 case JTAGARM7TDMI_DEBUG_INSTR:
874 jtagarm7tdmi_resettap();
875 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
878 case JTAGARM7TDMI_STEP_INSTR:
879 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
880 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
881 case JTAGARM7TDMI_READ_FLASH_PAGE:
882 case JTAGARM7TDMI_MASS_ERASE_FLASH:
883 case JTAGARM7TDMI_PROGRAM_FLASH:
884 case JTAGARM7TDMI_LOCKCHIP:
885 case JTAGARM7TDMI_CHIP_ERASE:
887 // Really ARM specific stuff
888 case JTAGARM7TDMI_GET_CPSR:
889 jtagarm7tdmi_resettap();
890 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
893 case JTAGARM7TDMI_SET_CPSR:
894 jtagarm7tdmi_resettap();
895 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
898 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
899 jtagarm7tdmi_resettap();
900 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
903 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
904 jtagarm7tdmi_resettap();
905 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
908 case JTAGARM7TDMI_SET_MODE_THUMB:
909 case JTAGARM7TDMI_SET_MODE_ARM:
910 jtagarm7tdmi_resettap();
911 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
915 case 0xD0: // loopback test
916 jtagarm7tdmi_resettap();
917 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
920 case 0xD8: // EICE_READ
921 jtagarm7tdmi_resettap();
922 cmddatalong[0] = eice_read(cmddatalong[0]);
925 case 0xD9: // EICE_WRITE
926 jtagarm7tdmi_resettap();
927 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
930 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
931 jtagarm7tdmi_resettap();
932 jtagarm7tdmi_scan_intest(0);
933 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
934 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
935 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
936 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
937 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
938 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
939 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
940 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
941 jtagarm7tdmi_resettap();
942 jtagarm7tdmi_scan_intest(1);
943 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
944 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
945 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
946 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
951 jtaghandle(app,verb,len);