-/*! \file jtagarm7tdmi.c
+/*! \file jtagarm7.c
\brief ARM7TDMI JTAG (AT91R40008, AT91SAM7xxx)
*/
#include "platform.h"
#include "command.h"
-#include "jtag.h"
-#include "jtagarm7tdmi.h"
+#include "jtagarm7.h"
/**** 20-pin Connection Information (pin1 is on top-right for both connectors)****
http://hri.sourceforge.net/tools/jtag_faq_org.html
********************************/
-
-// ! Start JTAG, setup pins, reset TAP and return IDCODE
-void jtagarm7tdmi_start() {
- jtagsetup();
- jtag_resettap();
-}
-
-
-//! Reset TAP State Machine
-
-
/* WHAT SHOULD THIS MODULE DO?
* *start
* *shift_ir
* *set_register
*/
-u32 shift_ir(u32 ir){
- u32 retval;
+// ! Start JTAG, setup pins, reset TAP and return IDCODE
+void jtagarm7tdmi_start() {
+ jtagsetup();
+ SETTST;
+ jtag_resettap();
+}
+
+
+u8 shift_ir(u8 ir, u8 flags){
+ u8 retval;
jtag_goto_shift_ir();
- retval = jtagtransn(ir, 4, LSB);
+ retval = jtagtransn(ir, 4, LSB|flags);
return retval;
}
state” to the “Select DR” state each time the “Update” state is reached.
*/
unsigned long retval;
- jtag_goto_shift_ir();
- jtagtransn(ARM7TDMI_IR_SCAN_N, 4, LSB | NORETIDLE);
+ shift_ir(ARM7TDMI_IR_SCAN_N, NORETIDLE);
jtag_goto_shift_dr();
retval = jtagtransn(chain, 4, LSB | NORETIDLE);
- jtag_goto_shift_ir();
- jtagtransn(testmode, 4, LSB);
+ shift_ir(testmode, NORETIDLE);
return(retval);
}
unsigned long retval;
jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
+ //debughex32(instr);
jtag_goto_shift_dr();
// if the next instruction is to run using MCLK (master clock), set TDI
if (breakpt)
{
SETMOSI;
- count_sysspd_instr_since_debug++;
}
else
{
CLRMOSI;
- count_dbgspd_instr_since_debug++;
}
jtag_tcktock();
}
u32 jtagarm7tdmi_nop(u8 brkpt){
+ // WARNING: current_dbgstate must be up-to-date before calling this function!!!!!
+ if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
+ return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, brkpt);
return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
}
/******************** Complex Commands **************************/
//! Retrieve a 32-bit Register value
-unsigned long jtagarm7tdmi_get_register(unsigned long reg) { //PROVEN
- unsigned long retval=0L, instr;
- if (eice_read(EICE_DBGSTATUS)& JTAG_ARM7TDMI_DBG_TBIT)
- instr = THUMB_INSTR_STR_R0_r0 | reg | (reg<<16);
- else
- instr = (unsigned long)(reg<<12L) | (unsigned long)ARM_READ_REG; // STR Rx, [R14]
-
- jtagarm7tdmi_nop( 0);
+unsigned long jtagarm7_get_reg_prim(unsigned long instr){
jtagarm7tdmi_nop( 0);
jtagarm7tdmi_instr_primitive(instr, 0);
jtagarm7tdmi_nop( 0);
jtagarm7tdmi_nop( 0);
jtagarm7tdmi_nop( 0);
- retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
- return retval;
+ return jtagarm7tdmi_nop( 0); // recover 32-bit word
}
//! Set a 32-bit Register value
-void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN (assuming target reg is word aligned)
- unsigned long instr;
- //if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
- //instr = THUMB_WRITE_REG
- instr = (unsigned long)(((unsigned long)reg<<12L) | ARM_WRITE_REG); // LDR Rx, [R14]
-
- jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
- jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
- jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
+void jtagarm7_set_reg_prim(unsigned long instr, unsigned long reg, unsigned long val){ // PROVEN - 100827 (non-PC)
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
+ jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
+ jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
if (reg == ARM_REG_PC){
- jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
- jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
- jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
+ debugstr("setting pc...");
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
+ }
+}
+
+void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){ // PROVEN - 100827
+ reg = reg & 7;
+ jtagarm7tdmi_nop( 0);
+ if (dir){
+ jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)), 0);
+ debughex32((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)));
} else {
- jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
- jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
- jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
+ jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)), 0);
+ debughex32((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)));
}
- jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
+ jtagarm7tdmi_nop( 0);
+ jtagarm7tdmi_nop( 0);
+ jtagarm7tdmi_nop( 0);
+}
+
+unsigned long jtagarm7tdmi_get_register(unsigned long reg) { // PROVEN - 100827
+ unsigned long retval=0L, instr, r0;
+ current_dbgstate = eice_read(EICE_DBGSTATUS);
+ if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
+ if (reg > 7){
+ debugstr("debug: jtagarm7tdmi_get_register: thumb reg > 15");
+ reg = reg & 7;
+ r0 = jtagarm7_get_reg_prim( THUMB_READ_REG); // save reg0
+ jtagarm7_thumb_swap_reg(THUMB_SWAP_HiLo, reg); // clobber reg0 with hi reg
+ retval = jtagarm7_get_reg_prim( THUMB_READ_REG); // recover 32-bit word
+ jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
+ return retval;
+ } else {
+ instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
+ }
+ } else
+ instr = (reg<<12L) | ARM_READ_REG; // STR Rx, [R14]
+ return jtagarm7_get_reg_prim(instr);
+}
+
+//! Set a 32-bit Register value
+// writing to a register is a problem child in ARM, actually. if the register you are using as the indirect offset register is misaligned, your results are misaligned.
+// this set_register implementation normalizes this process at the cost of performance. since we don't know what's in the register, we set it to 0 first
+// we could use r14 and hope all is well, but only for arm, not thumb mode, and not always is all well then either. this is a performance trade-off we may have to revisit later
+//
+void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN - 100827
+ unsigned long instr, r0;
+ current_dbgstate = eice_read(EICE_DBGSTATUS);
+ if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
+ if (reg > 7){
+
+ r0 = jtagarm7_get_reg_prim(THUMB_READ_REG);
+ jtagarm7_set_reg_prim(THUMB_WRITE_REG, 0, 0);
+ instr = (unsigned long)(THUMB_WRITE_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
+ jtagarm7_set_reg_prim(instr, reg, val);
+ jtagarm7_thumb_swap_reg(THUMB_SWAP_LoHi, reg); // place 32-bit word into a high register
+ jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
+ } else
+ instr = THUMB_WRITE_REG | (reg) | ((reg)<<16) | ((reg)<<3) | ((reg)<<19);
+ } else {
+ instr = ARM_WRITE_REG | (reg<<12L) | (reg<<16); // LDR Rx, [R14]
+ }
+
+ //debughex32(instr);
+ // --- first time to clear the register... this ensures the write is not 8-bit offset ---
+ jtagarm7_set_reg_prim(instr, reg, 0);
+ // --- now we actually write to the register ---
+ jtagarm7_set_reg_prim(instr, reg, val);
jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
jtagarm7tdmi_nop( 0);
}
txdata(app,verb,0);
break;
case JTAG_IR_SHIFT:
- jtag_goto_shift_ir();
- cmddataword[0] = jtagtransn(cmddata[0], 4, cmddata[1]);
- txdata(app,verb,2);
+ cmddataword[0] = shift_ir(cmddata[0], cmddata[1]);
+ txdata(app,verb,1);
break;
case JTAG_DR_SHIFT:
- jtag_resettap();
jtag_goto_shift_dr();
cmddatalong[0] = jtagtransn(cmddatalong[1],cmddata[0],cmddata[1]);
txdata(app,verb,4);
case JTAGARM7_CHAIN0:
jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
jtag_goto_shift_dr();
- debughex32(cmddatalong[0]);
- debughex(cmddataword[4]);
- debughex32(cmddatalong[1]);
- debughex32(cmddatalong[3]);
+ //debughex32(cmddatalong[0]);
+ //debughex(cmddataword[4]);
+ //debughex32(cmddatalong[1]);
+ //debughex32(cmddatalong[3]);
cmddatalong[0] = jtagtransn(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
cmddatalong[2] = jtagtransn(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
cmddatalong[1] = jtagtransn(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
case JTAGARM7_SCANCHAIN1:
case JTAGARM7_DEBUG_INSTR:
cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
- txdata(app,verb,8);
+ txdata(app,verb,4);
break;
case JTAGARM7_EICE_READ:
cmddatalong[0] = eice_read(cmddata[0]);
jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
txdata(app,verb,4);
break;
+ case JTAG_RESETTARGET:
+ CLRTST;
+ delay(10);
+ SETTST;
+ break;
//case JTAGARM7_STEP_INSTR: