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();
145 return jtagarm7tdmi_idcode();
149 //! Reset TAP State Machine
150 void jtagarm7tdmi_resettap(){ // PROVEN
151 jtag_reset_to_runtest_idle();
154 //! 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
155 unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
157 unsigned long high = 1;
160 for (bit=(bitcount-1)/16; bit>0; bit--)
162 high <<= ((bitcount-1)%16);
167 for (bit = bitcount; bit > 0; bit--) {
168 /* write MOSI on trailing edge of previous clock */
176 SETTMS;//TMS high on last bit to exit.
180 /* read MISO on trailing edge */
186 for (bit=bitcount; bit>0; bit++) {
187 /* write MOSI on trailing edge of previous clock */
192 word = (word & mask) << 1;
195 SETTMS;//TMS high on last bit to exit.
199 /* read MISO on trailing edge */
218 /************************************************************************
219 * ARM7TDMI core has 6 primary registers to be connected between TDI/TDO
222 * * Scan Chain Select Register (4 bits_lsb)
223 * * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
224 * * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
225 * * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
226 ************************************************************************/
230 /************************** Basic JTAG Verb Commands *******************************/
231 //! Grab the core ID.
232 unsigned long jtagarm7tdmi_idcode(){ // PROVEN
234 jtagarmtransn(ARM7TDMI_IR_IDCODE, 4, LSB, END, RETIDLE);
236 return jtagarmtransn(0,32, LSB, END, RETIDLE);
239 //! Connect Bypass Register to TDO/TDI
240 unsigned char jtagarm7tdmi_bypass(){ // PROVEN
242 return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
244 //! INTEST verb - do internal test
245 unsigned char jtagarm7tdmi_intest() {
247 return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
251 unsigned char jtagarm7tdmi_extest() {
253 return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
257 //unsigned long jtagarm7tdmi_sample() {
258 // jtagarm7tdmi_ir_shift4(ARM7TDMI_IR_SAMPLE); // ???? same here.
259 // return jtagtransn(0,32);
263 unsigned char jtagarm7tdmi_restart() {
265 return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
268 //! ARM7TDMI_IR_CLAMP 0x5
269 unsigned long jtagarm7tdmi_clamp() {
271 jtagarmtransn(ARM7TDMI_IR_CLAMP, 4, LSB, END, NORETIDLE);
273 return jtagarmtransn(0, 32, LSB, END, RETIDLE);
276 //! ARM7TDMI_IR_HIGHZ 0x7
277 unsigned char jtagarm7tdmi_highz() {
279 return jtagarmtransn(ARM7TDMI_IR_HIGHZ, 4, LSB, END, NORETIDLE);
282 //! define ARM7TDMI_IR_CLAMPZ 0x9
283 unsigned char jtagarm7tdmi_clampz() {
285 return jtagarmtransn(ARM7TDMI_IR_CLAMPZ, 4, LSB, END, NORETIDLE);
289 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
290 unsigned long jtagarm7tdmi_scan(int chain, int testmode) { // PROVEN
292 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
293 wise, when in debug state, the core will not be correctly isolated and intrusive
294 commands occur. Therefore, it is recommended to pass directly from the “Update”
295 state” to the “Select DR” state each time the “Update” state is reached.
297 jtagarm7tdmi_resettap(); // assume already sane?
298 unsigned long retval;
299 //if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
301 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
303 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
304 current_chain = chain;
306 // retval = current_chain;
307 // put in test mode...
309 jtagarmtransn(testmode, 4, LSB, END, RETIDLE);
314 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST, ENDS IN SHIFT_DR!!!!!
315 unsigned long jtagarm7tdmi_scan_intest(int chain) { // PROVEN
316 return jtagarm7tdmi_scan(chain, ARM7TDMI_IR_INTEST);
319 /* unsigned long retval;
320 if (current_chain == chain)
321 return current_chain;
322 jtagarm7tdmi_resettap(); // assumed already sane?
324 jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
326 retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
327 current_chain = chain;
328 jtagarm7tdmi_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 // TOTALLY TESTING: FIXME: THIS IS NOT AS IT WANTS TO BE
340 jtagarm7tdmi_scan_intest(1);
341 ////////////////////////////////////////////////////////
343 // if the next instruction is to run using MCLK (master clock), set TDI
347 count_sysspd_instr_since_debug++;
352 count_dbgspd_instr_since_debug++;
357 // Now shift in the 32 bits
358 retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
364 /* stolen from ARM DDI0029G documentation, translated using ARM Architecture Reference Manual (14128.pdf)
365 STR R0, [R0]; Save R0 before use
366 MOV R0, PC ; Copy PC into R0
367 STR R0, [R0]; Now save the PC in R0
368 BX PC ; Jump into ARM state
375 //! 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();
376 unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
377 unsigned long retval = 0xff;
378 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
379 jtagarm7tdmi_scan_intest(1);
380 cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
381 cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
382 cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
383 cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
384 cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
385 cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
394 /************************* EmbeddedICE Primitives ****************************/
395 //! shifter for writing to chain2 (EmbeddedICE).
396 unsigned long eice_write(unsigned char reg, unsigned long data){
397 unsigned long retval, temp;
398 jtagarm7tdmi_scan_intest(2);
399 // Now shift in the 32 bits
401 retval = jtagarmtransn(data, 32, LSB, NOEND, NORETIDLE); // send in the data - 32-bits lsb
402 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
403 jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the register address - 5 bits lsb
405 //SETTMS; // Last Bit - Exit UPDATE_DR
406 //// is this update a read/write or just read?
408 //jtag_arm_tcktock();
413 //! shifter for reading from chain2 (EmbeddedICE).
414 unsigned long eice_read(unsigned char reg){ // PROVEN
416 jtagarm7tdmi_scan_intest(2);
418 // send in the register address - 5 bits LSB
420 temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
422 // clear TDI to select "read only"
423 jtagarmtransn(0, 1, LSB, END, RETIDLE);
426 // Now shift out the 32 bits
427 return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
434 /************************* ICEBreaker/EmbeddedICE Stuff ******************************/
435 //! Grab debug register
436 unsigned long jtagarm7tdmi_get_dbgstate() { // ICE Debug register, *NOT* ARM register DSCR // PROVEN
437 jtagarm7tdmi_resettap();
438 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST); // select ICEBreaker
439 return eice_read(EICE_DBGSTATUS);
442 //! Grab debug register
443 unsigned long jtagarm7tdmi_get_dbgctrl() {
444 jtagarm7tdmi_resettap();
445 jtagarm7tdmi_scan_intest(2); // select ICEBreaker
446 return eice_read(EICE_DBGCTRL);
449 //! Update debug register
450 unsigned long jtagarm7tdmi_set_dbgctrl(unsigned long bits) {
451 jtagarm7tdmi_resettap();
452 jtagarm7tdmi_scan_intest(2); // select ICEBreaker
453 return eice_write(EICE_DBGCTRL, bits);
458 //! Set and Enable Watchpoint 0
459 void jtagarm7tdmi_set_watchpoint0(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
461 jtagarm7tdmi_scan_intest(2);
462 // store watchpoint info? - not right now
463 // write 0 in watchpoint 0 address
464 eice_write(EICE_WP0ADDR, addr);
465 // write 0xffffffff in watchpoint 0 address mask
466 eice_write(EICE_WP0ADDRMASK, addrmask);
467 // write 0 in watchpoint 0 data
468 eice_write(EICE_WP0DATA, data);
469 // write 0xffffffff in watchpoint 0 data mask
470 eice_write(EICE_WP0DATAMASK, datamask);
471 // write 0x00000100 in watchpoint 0 control value register (enables watchpoint)
472 eice_write(EICE_WP0CTRL, ctrlmask);
473 // write 0xfffffff7 in watchpoint 0 control mask - only detect the fetch instruction
474 eice_write(EICE_WP0CTRLMASK, ctrlmask);
477 //! Set and Enable Watchpoint 1
478 void jtagarm7tdmi_set_watchpoint1(unsigned long addr, unsigned long addrmask, unsigned long data, unsigned long datamask, unsigned long ctrl, unsigned long ctrlmask){
480 jtagarm7tdmi_scan_intest(2);
481 // store watchpoint info? - not right now
482 // write 0 in watchpoint 1 address
483 eice_write(EICE_WP1ADDR, addr);
484 // write 0xffffffff in watchpoint 1 address mask
485 eice_write(EICE_WP1ADDRMASK, addrmask);
486 // write 0 in watchpoint 1 data
487 eice_write(EICE_WP1DATA, data);
488 // write 0xffffffff in watchpoint 1 data mask
489 eice_write(EICE_WP1DATAMASK, datamask);
490 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
491 eice_write(EICE_WP1CTRL, ctrl);
492 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
493 eice_write(EICE_WP1CTRLMASK, ctrlmask);
496 //! Disable Watchpoint 0
497 void jtagarm7tdmi_disable_watchpoint0(){
499 jtagarm7tdmi_scan_intest(2);
500 // write 0 in watchpoint 0 control value - disables watchpoint 0
501 eice_write(EICE_WP0CTRL, 0x0);
504 //! Disable Watchpoint 1
505 void jtagarm7tdmi_disable_watchpoint1(){
507 jtagarm7tdmi_scan_intest(2);
508 // write 0 in watchpoint 0 control value - disables watchpoint 0
509 eice_write(EICE_WP1CTRL, 0x0);
514 /******************** Complex Commands **************************/
515 //! Push an instruction into the CPU pipeline
516 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
517 unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
518 unsigned long retval;
520 jtagarm7tdmi_scan_intest(1);
522 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
523 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,systemspeed);
524 // write 32-bit instruction code into DR
525 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
526 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
527 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
529 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
530 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
531 cmddatalong[8] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
532 cmddatalong[9] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
533 retval = cmddatalong[9];
539 //! Push an instruction into the CPU pipeline
540 // NOTE! Must provide EXECNOPARM for parameter if no parm is required.
541 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
542 unsigned long retval;
544 jtagarm7tdmi_scan_intest(1);
546 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
547 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,systemspeed);
548 // write 32-bit instruction code into DR
549 cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0);
550 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
551 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
553 cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0);
554 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
555 retval = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
556 cmddatalong[9] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
557 cmddatalong[8] = retval;
562 //! Retrieve a 32-bit Register value
563 unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
564 unsigned long retval = 0, instr;
565 //JTAGARM7TDMI_RESETTAP();
566 // select chain 1, automatically put in INTEST
567 jtagarm7tdmi_scan_intest(1);
568 instr = ARM_INSTR_STR_Rx_r14 + ((reg<<12)&0xf00);
569 //retval = jtagarm7tdmi_exec(instr, 0);
570 // push STR_Rx, [R14] into pipeline
571 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
572 // push nop into pipeline - fetched
573 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
574 // push nop into pipeline - decoded
575 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
576 // push nop into pipeline - executed
577 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
578 // recover 32-bit word
579 //retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
580 retval = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
581 cmddatalong[5] = retval;
582 cmddatalong[6] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
583 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
584 cmddatalong[8] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
588 //! Set a 32-bit Register value
589 unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
590 unsigned long retval = 0, instr;
591 //jtagarm7tdmi_resettap();
593 jtagarm7tdmi_scan_intest(1);
594 instr = ARM_INSTR_LDR_Rx_r14 + ((reg<<12)&0xf00);
595 //retval = jtagarm7tdmi_exec(instr, 0);
596 // push STR_Rx, [R14] into pipeline
597 cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
598 // push nop into pipeline - fetched
599 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
600 // push nop into pipeline - decoded
601 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
603 // push 32-bit word on data bus - execute state
604 //retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
605 cmddatalong[3] = jtagarm7tdmi_instr_primitive(val, 0);
606 // push nop into pipeline - executed
607 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
608 if (reg == ARM_REG_PC){
609 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
610 cmddatalong[6] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
612 retval = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
613 cmddatalong[7] = retval;
619 //! Get all registers. Return an array
620 unsigned long* jtagarm7tdmi_get_registers() {
621 jtagarm7tdmi_scan_intest(1);
622 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
623 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
624 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
625 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
626 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
627 cmddatalong[6] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
628 cmddatalong[7] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
629 cmddatalong[8] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
630 cmddatalong[9] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
631 cmddatalong[10] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
632 cmddatalong[11] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
633 cmddatalong[12] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
634 cmddatalong[13] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
635 cmddatalong[14] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
636 cmddatalong[15] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
637 cmddatalong[16] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
638 cmddatalong[17] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
639 cmddatalong[18] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
640 cmddatalong[19] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
641 cmddatalong[20] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
645 //! Retrieve the CPSR Register value
646 unsigned long jtagarm7tdmi_get_regCPSR() {
647 unsigned long retval = 0;
649 cmddatalong[1] = jtagarm7tdmi_scan_intest(1);
651 // push STR_Rx, [R14] into pipeline
652 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0);
653 // push nop into pipeline - fetched
654 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
655 // push nop into pipeline - decoded
656 cmddatalong[4] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
657 // push nop into pipeline - executed
658 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
659 // recover 32-bit word
660 retval = jtagarmtransn(0, 32, LSB, END, RETIDLE);
661 cmddatalong[6] = retval;
665 //! Retrieve the CPSR Register value
666 unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
667 unsigned long retval = 0;
669 jtagarm7tdmi_scan_intest(1);
671 // push MSR cpsr_cxsf, R0 into pipeline
672 cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0);
673 // push nop into pipeline - fetched
674 cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
675 // push nop into pipeline - decoded
676 cmddatalong[3] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
678 // push 32-bit word on data bus
679 retval = jtagarmtransn(val, 32, LSB, END, RETIDLE);
680 // push nop into pipeline - executed
681 cmddatalong[5] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
682 cmddatalong[4] = retval;
686 //! Write data to address - Assume TAP in run-test/idle state
687 unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
688 unsigned long r0=0, r1=-1;
690 jtagarm7tdmi_scan_intest(1);
693 r0 = jtagarm7tdmi_get_register(0);
694 r1 = jtagarm7tdmi_get_register(1);
695 // write address into R0
696 jtagarm7tdmi_set_register(0, adr);
698 jtagarm7tdmi_set_register(1, data);
699 //retval = jtagarm7tdmi_exec(ARM_INSTR_LDR_R1_r0_4,1);
700 // push nop into pipeline to "clean" it ???
701 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
702 // push nop into pipeline with BREAKPT set
703 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 1);
704 // push LDR R1, R0, #4 into instruction pipeline
705 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
706 // push nop into pipeline
707 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
709 jtagarm7tdmi_set_register(1, r1);
710 jtagarm7tdmi_set_register(0, r0);
714 //! Read data from address
715 unsigned long jtagarm7tdmi_readmem(unsigned long adr){
716 unsigned long retval = 0;
717 unsigned long r0=0, r1=-1;
718 int waitcount = 0xfff;
720 jtagarm7tdmi_scan_intest(1);
723 // store R0 and R1 - not yet...
724 r0 = jtagarm7tdmi_get_register(0);
725 r1 = jtagarm7tdmi_get_register(1);
726 // write address into R0
727 jtagarm7tdmi_set_register(0, adr);
728 // push nop into pipeline to "clean" it ???
729 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
730 // push nop into pipeline with BREAKPT set
731 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 1);
732 // push LDR R1, R0, #4 into instruction pipeline
733 jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0);
734 // push nop into pipeline
735 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, 0);
736 // SHIFT_IR with RESTART instruction
737 jtagarm7tdmi_restart();
738 // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
739 while ((jtagarm7tdmi_get_dbgstate() & 1) == 0 && waitcount > 0){
743 if (waitcount == 0xffff){
746 retval = jtagarm7tdmi_get_register(1);
747 // read memory value from R1 register
749 jtagarm7tdmi_set_register(1, r1);
750 jtagarm7tdmi_set_register(0, r0);
756 //! Read Program Counter
757 unsigned long jtagarm7tdmi_getpc(){
758 return jtagarm7tdmi_get_register(ARM_REG_PC);
761 //! Set Program Counter
762 unsigned long jtagarm7tdmi_setpc(unsigned long adr){
763 return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
766 //! Halt CPU - returns 0xffff if the operation fails to complete within
767 unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
768 int waitcount = 0xfff;
770 jtagarm7tdmi_scan_intest(2);
771 // store watchpoint info? - not right now
772 // write 0 in watchpoint 1 address
773 eice_write(EICE_WP1ADDR, 0);
774 // write 0xffffffff in watchpoint 1 address mask
775 eice_write(EICE_WP1ADDRMASK, 0xffffffff);
776 // write 0 in watchpoint 1 data
777 eice_write(EICE_WP1DATA, 0);
778 // write 0xffffffff in watchpoint 1 data mask
779 eice_write(EICE_WP1DATAMASK, 0xffffffff);
780 // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
781 eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!?
782 // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
783 eice_write(EICE_WP1CTRLMASK, 0xfffffff7); //!!!!! WTF! THIS IS SUPPOSED TO BE 8 bits wide?!?
784 // poll until debug status says the cpu is in debug mode
785 while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount > 0){
789 // write 0 in watchpoint 0 control value - disables watchpoint 0
790 eice_write(EICE_WP1CTRL, 0x0);
792 // store the debug state
793 last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
794 last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
795 count_dbgspd_instr_since_debug = 0;
796 count_sysspd_instr_since_debug = 0;
797 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){
798 jtagarm7tdmi_setMode_ARM();
803 unsigned long jtagarm7tdmi_releasecpu(){
804 int waitcount = 0xfff;
806 // somehow determine what PC should be (a couple ways possible, calculations required)
807 jtagarm7tdmi_scan_intest(1);
809 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,0);
811 jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,1);
813 if (last_halt_debug_state & JTAG_ARM7TDMI_DBG_TBIT){ // FIXME: FORKED.
814 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?
815 jtagarm7tdmi_instr_primitive(instr,0);
817 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?
818 jtagarm7tdmi_instr_primitive(instr,0);
822 jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE);
824 // wait until restart-bit set in debug state register
825 while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
829 last_halt_debug_state = -1;
848 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
849 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
850 register char blocks;
855 //jtagarm7tdmi_resettap();
860 cmddatalong[0] = jtagarm7tdmi_start();
861 cmddatalong[1] = jtagarm7tdmi_haltcpu();
862 //jtagarm7tdmi_resettap();
863 txdata(app,verb,0x8);
865 case JTAGARM7TDMI_READMEM:
867 blocks=(len>4?cmddata[4]:1);
871 txhead(app,verb,len);
875 jtagarm7tdmi_resettap();
878 val=jtagarm7tdmi_readmem(at);
882 serial_tx((val&0xFF00)>>8);
887 case JTAGARM7TDMI_GET_CHIP_ID:
888 jtagarm7tdmi_resettap();
889 cmddatalong[0] = jtagarm7tdmi_idcode();
894 case JTAGARM7TDMI_WRITEMEM:
896 jtagarm7tdmi_resettap();
897 jtagarm7tdmi_writemem(cmddatalong[0],
899 cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
903 case JTAGARM7TDMI_HALTCPU:
904 cmddatalong[0] = jtagarm7tdmi_haltcpu();
907 case JTAGARM7TDMI_RELEASECPU:
908 jtagarm7tdmi_resettap();
909 cmddatalong[0] = jtagarm7tdmi_releasecpu();
912 //unimplemented functions
913 //case JTAGARM7TDMI_SETINSTRFETCH:
914 //case JTAGARM7TDMI_WRITEFLASH:
915 //case JTAGARM7TDMI_ERASEFLASH:
916 case JTAGARM7TDMI_SET_PC:
917 jtagarm7tdmi_resettap();
918 cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
921 case JTAGARM7TDMI_GET_DEBUG_CTRL:
922 jtagarm7tdmi_resettap();
923 cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
926 case JTAGARM7TDMI_SET_DEBUG_CTRL:
927 jtagarm7tdmi_resettap();
928 cmddatalong[0] = jtagarm7tdmi_set_dbgctrl(cmddata[0]);
931 case JTAGARM7TDMI_GET_PC:
932 jtagarm7tdmi_resettap();
933 cmddatalong[0] = jtagarm7tdmi_getpc();
936 case JTAGARM7TDMI_GET_DEBUG_STATE:
937 jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
938 cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
941 //case JTAGARM7TDMI_GET_WATCHPOINT:
942 //case JTAGARM7TDMI_SET_WATCHPOINT:
943 case JTAGARM7TDMI_GET_REGISTER:
944 jtagarm7tdmi_resettap();
945 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
948 case JTAGARM7TDMI_SET_REGISTER:
949 jtagarm7tdmi_resettap();
950 cmddatalong[0] = cmddatalong[1];
951 jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
954 case JTAGARM7TDMI_GET_REGISTERS:
955 jtagarm7tdmi_resettap();
956 jtagarm7tdmi_get_registers();
959 //case JTAGARM7TDMI_SET_REGISTERS:
960 case JTAGARM7TDMI_DEBUG_INSTR:
961 jtagarm7tdmi_resettap();
962 cmddataword[0] = jtagarm7tdmi_exec(cmddataword[0], cmddataword[1], cmddata[9]);
965 case JTAGARM7TDMI_STEP_INSTR:
966 /* case JTAGARM7TDMI_READ_CODE_MEMORY:
967 case JTAGARM7TDMI_WRITE_FLASH_PAGE:
968 case JTAGARM7TDMI_READ_FLASH_PAGE:
969 case JTAGARM7TDMI_MASS_ERASE_FLASH:
970 case JTAGARM7TDMI_PROGRAM_FLASH:
971 case JTAGARM7TDMI_LOCKCHIP:
972 case JTAGARM7TDMI_CHIP_ERASE:
974 // Really ARM specific stuff
975 case JTAGARM7TDMI_GET_CPSR:
976 jtagarm7tdmi_resettap();
977 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
980 case JTAGARM7TDMI_SET_CPSR:
981 jtagarm7tdmi_resettap();
982 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
985 case JTAGARM7TDMI_GET_SPSR: // FIXME: NOT CORRECT
986 jtagarm7tdmi_resettap();
987 cmddatalong[0] = jtagarm7tdmi_get_regCPSR();
990 case JTAGARM7TDMI_SET_SPSR: // FIXME: NOT CORRECT
991 jtagarm7tdmi_resettap();
992 cmddatalong[0] = jtagarm7tdmi_set_regCPSR(cmddatalong[0]);
995 case JTAGARM7TDMI_SET_MODE_THUMB:
996 case JTAGARM7TDMI_SET_MODE_ARM:
997 jtagarm7tdmi_resettap();
998 cmddataword[0] = jtagarm7tdmi_setMode_ARM();
1002 case 0xD0: // loopback test
1003 jtagarm7tdmi_resettap();
1004 cmddatalong[0] = jtagarm7tdmi_bypass(cmddatalong[0]);
1007 case 0xD1: // Set Scan Chain
1008 jtagarm7tdmi_resettap();
1009 cmddatalong[0] = test_exec(cmddatalong[0], EXECNOPARM, 0);
1010 txdata(app,verb,52);
1012 case 0xD3: // EXECUTE
1013 jtagarm7tdmi_resettap();
1014 //cmddatalong[0] = jtagarm7tdmi_exec(cmddatalong[0], EXECNOPARM, 0);
1015 cmddatalong[0] = test_exec(cmddatalong[0], EXECNOPARM, 0);
1016 txdata(app,verb,52);
1018 case 0xD4: // GET REGISTER
1019 jtagarm7tdmi_resettap();
1020 cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
1021 txdata(app,verb,40);
1023 case 0xD5: // SET REGISTER
1024 jtagarm7tdmi_resettap();
1025 cmddatalong[0] = jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
1026 txdata(app,verb,40);
1028 case 0xD6: // SHIFT_DR
1030 cmddatalong[0] = jtagarmtransn(cmddatalong[0], 32, LSB, END, RETIDLE);
1033 case 0xD7: // INSTR_PRIMITIVE
1034 jtagarm7tdmi_resettap();
1036 jtagarm7tdmi_scan_intest(1);
1037 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0], 0);
1040 case 0xD8: // EICE_READ
1041 jtagarm7tdmi_resettap();
1042 cmddatalong[0] = eice_read(cmddatalong[0]);
1045 case 0xD9: // EICE_WRITE
1046 jtagarm7tdmi_resettap();
1047 cmddatalong[0] = eice_write(cmddatalong[0], cmddatalong[1]);
1050 case 0xDA: // TEST MSB THROUGH CHAIN0 and CHAIN1
1051 jtagarm7tdmi_resettap();
1052 jtagarm7tdmi_scan_intest(0);
1053 cmddatalong[0] = jtagarmtransn(0x41414141, 32, LSB, NOEND, NORETIDLE);
1054 cmddatalong[1] = jtagarmtransn(0x42424242, 32, MSB, NOEND, NORETIDLE);
1055 cmddatalong[2] = jtagarmtransn(0x43434343, 9, MSB, NOEND, NORETIDLE);
1056 cmddatalong[3] = jtagarmtransn(0x44444444, 32, MSB, NOEND, NORETIDLE);
1057 cmddatalong[4] = jtagarmtransn(cmddatalong[0], 32, LSB, NOEND, NORETIDLE);
1058 cmddatalong[5] = jtagarmtransn(cmddatalong[1], 32, MSB, NOEND, NORETIDLE);
1059 cmddatalong[6] = jtagarmtransn(cmddatalong[2], 9, MSB, NOEND, NORETIDLE);
1060 cmddatalong[7] = jtagarmtransn(cmddatalong[3], 32, MSB, END, RETIDLE);
1061 jtagarm7tdmi_resettap();
1062 jtagarm7tdmi_scan_intest(1);
1063 cmddatalong[8] = jtagarmtransn(0x41414141, 32, MSB, NOEND, NORETIDLE);
1064 cmddatalong[9] = jtagarmtransn(0x44444444, 1, MSB, NOEND, NORETIDLE);
1065 cmddatalong[10] = jtagarmtransn(cmddatalong[8], 32, MSB, NOEND, NORETIDLE);
1066 cmddatalong[11] = jtagarmtransn(cmddatalong[9], 1, MSB, END, RETIDLE);
1067 txdata(app,verb,48);
1071 jtaghandle(app,verb,len);