/*! \file jtagarm7tdmi.c
- \brief ARM7TDMI JTAG (AT91R40008)
+ \brief ARM7TDMI JTAG (AT91R40008, AT91SAM7xxx)
*/
#include "platform.h"
/************************** JTAGARM7TDMI Primitives ****************************/
-void jtag_goto_shift_ir() {
+/*void jtag_goto_shift_ir() {
SETTMS;
jtag_arm_tcktock();
jtag_arm_tcktock();
jtag_arm_tcktock();
}
-
void jtag_goto_shift_dr() {
SETTMS;
jtag_arm_tcktock();
jtag_arm_tcktock();
jtag_arm_tcktock();
}
+*/
void jtag_reset_to_runtest_idle() {
SETTMS;
jtag_arm_tcktock();
jtag_arm_tcktock();
jtag_arm_tcktock();
- jtag_arm_tcktock();
- jtag_arm_tcktock();
- jtag_arm_tcktock();
jtag_arm_tcktock(); // now in Reset state
CLRTMS;
jtag_arm_tcktock(); // now in Run-Test/Idle state
}
void jtag_arm_tcktock() {
+ delay(1); // FIXME: Should never wait this long...
CLRTCK;
PLEDOUT^=PLEDPIN;
+ delay(1); // FIXME: Should never wait this long...
SETTCK;
PLEDOUT^=PLEDPIN;
}
// ! Start JTAG, setup pins, reset TAP and return IDCODE
unsigned long jtagarm7tdmi_start() {
jtagsetup();
- //Known-good starting position.
- //Might be unnecessary.
- SETTST;
- SETRST;
-
- delay(0x2);
-
- CLRRST;
- delay(2);
- CLRTST;
-
- msdelay(10);
- SETRST;
- /*
- P5DIR &=~RST;
- */
- delay(0x2);
jtagarm7tdmi_resettap();
return jtagarm7tdmi_idcode();
}
//! 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
unsigned long jtagarmtransn(unsigned long word, unsigned char bitcount, unsigned char lsb, unsigned char end, unsigned char retidle){ // PROVEN
- unsigned int bit;
- unsigned long high = 1;
+ unsigned char bit;
+ unsigned long high = 1L;
unsigned long mask;
- for (bit=(bitcount-1)/8; bit>0; bit--)
- high <<= 8;
- high <<= ((bitcount-1)%8);
+ //for (bit=(bitcount-1)/8; bit>0; bit--)
+ // high <<= 8;
+ //high <<= ((bitcount-1)%8);
+ high <<= (bitcount-1);
mask = high-1;
* * Bypass Register
* * ID Code Register
* * Scan Chain Select Register (4 bits_lsb)
-* * Scan Chain 0 (64+* bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
+* * Scan Chain 0 (105 bits: 32_databits_lsb + ctrlbits + 32_addrbits_msb)
* * Scan Chain 1 (33 bits: 32_bits + BREAKPT)
* * Scan Chain 2 (38 bits: rw + 5_regbits_msb + 32_databits_msb)
************************************************************************/
//! Connect Bypass Register to TDO/TDI
unsigned char jtagarm7tdmi_bypass(){ // PROVEN
- //jtagarm7tdmi_resettap();
+ jtagarm7tdmi_resettap();
SHIFT_IR;
return jtagarmtransn(ARM7TDMI_IR_BYPASS, 4, LSB, END, NORETIDLE);
}
//! INTEST verb - do internal test
unsigned char jtagarm7tdmi_intest() {
- //jtagarm7tdmi_resettap();
SHIFT_IR;
return jtagarmtransn(ARM7TDMI_IR_INTEST, 4, LSB, END, NORETIDLE);
}
-//! EXTEST verb
+//! EXTEST verb - act like the processor to external components
unsigned char jtagarm7tdmi_extest() {
- //jtagarm7tdmi_resettap();
SHIFT_IR;
return jtagarmtransn(ARM7TDMI_IR_EXTEST, 4, LSB, END, NORETIDLE);
}
//! RESTART verb
unsigned char jtagarm7tdmi_restart() {
- //jtagarm7tdmi_resettap();
+ jtagarm7tdmi_resettap();
SHIFT_IR;
return jtagarmtransn(ARM7TDMI_IR_RESTART, 4, LSB, END, RETIDLE);
}
state” to the “Select DR” state each time the “Update” state is reached.
*/
unsigned long retval;
- if (current_chain != chain) { // breaks shit when going from idcode back to scan chain
+ if (current_chain != chain) {
+ //debugstr("===change chains===");
SHIFT_IR;
jtagarmtransn(ARM7TDMI_IR_SCAN_N, 4, LSB, END, NORETIDLE);
SHIFT_DR;
retval = jtagarmtransn(chain, 4, LSB, END, NORETIDLE);
current_chain = chain;
} else
+ //debugstr("===NOT change chains===");
retval = current_chain;
// put in test mode...
SHIFT_IR;
//! push an instruction into the pipeline
-unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
+unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ // PROVEN
unsigned long retval;
- //jtagarm7tdmi_resettap(); // FIXME: DEBUG: seems necessary for some reason. ugh.
jtagarm7tdmi_scan_intest(1);
SHIFT_DR;
// Now shift in the 32 bits
retval = jtagarmtransn(instr, 32, MSB, END, RETIDLE); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
- //jtag_arm_tcktock();
return(retval);
}
-
-unsigned long jtagarm7tdmi_nop(char breakpt){
+//! push NOP into the instruction pipeline
+unsigned long jtagarm7tdmi_nop(char breakpt){ // PROVEN
+ if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
+ return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, breakpt);
return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, breakpt);
}
NOP
*/
+
//! 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();
-unsigned long jtagarm7tdmi_setMode_ARM(){ // PROVEN
- unsigned long retval = 0xff;
- while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
- cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
+unsigned long jtagarm7tdmi_setMode_ARM(unsigned char restart){ // PROVEN BUT FUGLY! FIXME: clean up and store and replace clobbered r0
+ debugstr("=== Switching to ARM mode ===");
+ unsigned long retval = 0xffL;
+ while ((current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
+ cmddataword[9] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
cmddataword[1] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
cmddataword[2] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_MOV_R0_PC,0);
cmddataword[3] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_STR_R0_r0,0);
cmddataword[4] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_BX_PC,0);
cmddataword[5] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
cmddataword[6] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
+ cmddataword[7] = jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP,0);
jtagarm7tdmi_resettap(); // seems necessary for some reason. ugh.
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
+ jtagarm7tdmi_set_register(0,cmddataword[4]);
+ debugstr("PC:");
+ debughex32(cmddataword[6]);
+ debughex32(cmddataword[7]);
+ debughex32(cmddataword[9]);
+ }
+ return(retval);
+}
+
+
+//! 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();
+unsigned long jtagarm7tdmi_setMode_THUMB(unsigned char restart){ // PROVEN
+ debugstr("=== Switching to THUMB mode ===");
+ unsigned long retval = 0xffL;
+ while (!(current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)&& retval-- > 0){
+ last_halt_pc |= 1;
+ cmddataword[9] = jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,0);
+ jtagarm7tdmi_set_register(0, last_halt_pc);
+ cmddataword[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_BX_R0,0);
+ if (restart) {
+ jtagarm7tdmi_restart();
+ } else {
+ jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,0);
+ jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP,0);
+ jtagarm7tdmi_resettap(); // seems necessary for some reason.
+ }
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
}
return(retval);
}
temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE); // send in the register address - 5 bits lsb
jtagarmtransn(1, 1, LSB, END, RETIDLE); // send in the WRITE bit
- //SETTMS; // Last Bit - Exit UPDATE_DR
- //// is this update a read/write or just read?
- //SETMOSI;
- //jtag_arm_tcktock();
-
return(retval);
}
//! shifter for reading from chain2 (EmbeddedICE).
unsigned long eice_read(unsigned char reg){ // PROVEN
- unsigned long temp;
+ unsigned long temp, retval;
+ //debugstr("eice_read");
+ //debughex(reg);
jtagarm7tdmi_scan_intest(2);
// send in the register address - 5 bits LSB
temp = jtagarmtransn(reg, 5, LSB, NOEND, NORETIDLE);
// clear TDI to select "read only"
- jtagarmtransn(0, 1, LSB, END, RETIDLE);
+ jtagarmtransn(0L, 1, LSB, END, RETIDLE);
SHIFT_DR;
// Now shift out the 32 bits
- return(jtagarmtransn(0, 32, LSB, END, RETIDLE)); // atmel arm jtag docs pp.10-11: LSB first
+ retval = jtagarmtransn(0L, 32, LSB, END, RETIDLE); // atmel arm jtag docs pp.10-11: LSB first
+ //debughex32(retval);
+ return(retval); // atmel arm jtag docs pp.10-11: LSB first
}
//! Disable Watchpoint 0
void jtagarm7tdmi_disable_watchpoint0(){
- eice_write(EICE_WP0CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
+ eice_write(EICE_WP0CTRL, 0x0L); // write 0 in watchpoint 0 control value - disables watchpoint 0
}
//! Disable Watchpoint 1
void jtagarm7tdmi_disable_watchpoint1(){
- eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
+ eice_write(EICE_WP1CTRL, 0x0L); // write 0 in watchpoint 0 control value - disables watchpoint 0
}
/******************** Complex Commands **************************/
-//! Push an instruction into the CPU pipeline
-// NOTE! Must provide EXECNOPARM for parameter if no parm is required.
-unsigned long test_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
- unsigned long retval;
-
- cmddatalong[1] = jtagarm7tdmi_nop( 0);
- cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
- cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
- cmddatalong[4] = jtagarm7tdmi_nop( 0);
- cmddatalong[5] = jtagarm7tdmi_nop( 0);
- cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
- cmddatalong[7] = jtagarm7tdmi_nop( 0);
- cmddatalong[8] = jtagarm7tdmi_nop( 0);
- cmddatalong[9] = jtagarm7tdmi_nop( 0);
- retval = cmddatalong[9];
-
- return(retval);
-}
-
//! Push an instruction into the CPU pipeline
// NOTE! Must provide EXECNOPARM for parameter if no parm is required.
unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
- unsigned long retval;
-
- cmddatalong[1] = jtagarm7tdmi_nop( 0);
- cmddatalong[2] = jtagarm7tdmi_nop(systemspeed);
- cmddatalong[3] = jtagarm7tdmi_instr_primitive(instr, 0); // write 32-bit instruction code into DR
- cmddatalong[4] = jtagarm7tdmi_nop( 0);
- cmddatalong[5] = jtagarm7tdmi_nop( 0);
- cmddatalong[6] = jtagarm7tdmi_instr_primitive(parameter, 0); // inject long
- cmddatalong[7] = jtagarm7tdmi_nop( 0);
- retval = jtagarm7tdmi_nop( 0);
- cmddatalong[9] = jtagarm7tdmi_nop( 0);
- cmddatalong[8] = retval;
-
+ unsigned long retval,waitcount=0xff;
+
+ debughex32(jtagarm7tdmi_nop( 0));
+ debughex32(jtagarm7tdmi_nop(systemspeed));
+ debughex32(jtagarm7tdmi_instr_primitive(instr, 0)); // write 32-bit instruction code into DR
+ debughex32(jtagarm7tdmi_nop( 0));
+ if (systemspeed){
+ jtagarm7tdmi_restart(); // SHIFT_IR with RESTART instruction
+
+ // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
+ while ((jtagarm7tdmi_get_dbgstate() & 9L) == 0 && waitcount > 0){
+ delay(1);
+ waitcount --;
+ }
+ if (waitcount == 0)
+ return (-1);
+ retval = 0x12345678;
+ } else {
+ debughex32(jtagarm7tdmi_nop( 0));
+ debughex32(jtagarm7tdmi_instr_primitive(parameter, 0)); // inject long
+ retval = jtagarm7tdmi_nop( 0);
+ debughex32(retval);
+ debughex32(jtagarm7tdmi_nop( 0));
+ debughex32(jtagarm7tdmi_nop( 0));
+ }
return(retval);
}
//! Retrieve a 32-bit Register value
-unsigned long jtagarm7tdmi_get_register(unsigned char reg) {
- unsigned long retval = 0, instr;
- // push nop into pipeline - clean out the pipeline...
- cmddatalong[2] = jtagarm7tdmi_nop( 0);
-
- instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
- cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0);
- cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
- cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
- cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
+unsigned long jtagarm7tdmi_get_register(unsigned long reg) {
+ unsigned long retval=0L, instr;
+ if (current_dbgstate & 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);
+ 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
- cmddatalong[5] = retval;
- cmddatalong[6] = jtagarm7tdmi_nop( 0);
- cmddatalong[7] = jtagarm7tdmi_nop( 0);
- cmddatalong[8] = jtagarm7tdmi_nop( 0);
- return retval;
-}
-
-//! Retrieve a 32-bit Register value
-unsigned long test_get_register(unsigned char reg) {
- unsigned long retval = 0, instr;
- // push nop into pipeline - clean out the pipeline...
- cmddatalong[2] = jtagarm7tdmi_nop( 0);
-
- instr = ARM_READ_REG | (reg<<12); // push STR Rx, [R14] into pipeline
- cmddatalong[1] = jtagarm7tdmi_instr_primitive(instr, 0); // fetch
- cmddatalong[2] = jtagarm7tdmi_nop( 0); // decode
- cmddatalong[3] = jtagarm7tdmi_nop( 0); // execute
- cmddatalong[4] = jtagarm7tdmi_nop( 0); // ??? what happens here ???
- retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
- cmddatalong[5] = retval;
- cmddatalong[6] = jtagarm7tdmi_nop( 0);
- cmddatalong[7] = jtagarm7tdmi_nop( 0);
- cmddatalong[8] = jtagarm7tdmi_nop( 0);
return retval;
}
//! Set a 32-bit Register value
-unsigned long jtagarm7tdmi_set_register(unsigned char reg, unsigned long val) {
- unsigned long retval = 0, instr;
- cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
-
- instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
- cmddatalong[2] = jtagarm7tdmi_instr_primitive(instr, 0); // push nop into pipeline - fetch
- cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
- cmddatalong[4] = jtagarm7tdmi_instr_primitive(val-16, 0); // push 32-bit word on data bus
- //cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
-
- cmddatalong[5] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
- cmddatalong[6] = jtagarm7tdmi_instr_primitive(val+16, 0); // push 32-bit word on data bus
- //cmddatalong[6] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
-
- if (reg == ARM_REG_PC){
- cmddatalong[7] = jtagarm7tdmi_nop( 0);
- cmddatalong[8] = jtagarm7tdmi_nop( 0);
- }
- cmddatalong[9] = jtagarm7tdmi_nop( 0);
-
- retval = cmddatalong[5];
- return(retval);
-}
-
-//! Set a 32-bit Register value
-unsigned long test_set_register(unsigned char reg, unsigned long val) {
- unsigned long retval = 0, instr;
- cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
-
- instr = ARM_WRITE_REG | (reg<<12); // push LDR Rx, [R14] into pipeline
- cmddatalong[2] = jtagarm7tdmi_instr_primitive(instr, 0);
+void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) {
+ unsigned long instr;
+ instr = (unsigned long)(((unsigned long)reg<<12L) | ARM_WRITE_REG); // LDR Rx, [R14]
- cmddatalong[3] = jtagarm7tdmi_instr_primitive(val+32, 0); // push 32-bit word on data bus - execute state
- cmddatalong[4] = jtagarm7tdmi_instr_primitive(val+16, 0); // push 32-bit word on data bus - execute state
- cmddatalong[5] = jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus - execute state
- cmddatalong[6] = jtagarm7tdmi_instr_primitive(val-16, 0); // push 32-bit word on data bus - execute state
-
+ 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
if (reg == ARM_REG_PC){
- cmddatalong[7] = jtagarm7tdmi_nop( 0);
- cmddatalong[8] = jtagarm7tdmi_nop( 0);
+ 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
+ } 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
}
- cmddatalong[9] = jtagarm7tdmi_instr_primitive(val-32, 0); // push 32-bit word on data bus - execute state
-
- retval = cmddatalong[5];
- return(retval);
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
+ jtagarm7tdmi_nop( 0);
}
-
-//! Get all registers. Return an array
-unsigned long* jtagarm7tdmi_get_registers() {
- cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
- cmddatalong[2] = jtagarm7tdmi_nop( 0);
- cmddatalong[3] = jtagarm7tdmi_nop( 0);
- cmddatalong[4] = jtagarm7tdmi_nop( 0);
- cmddatalong[5] = jtagarm7tdmi_nop( 0);
- cmddatalong[6] = jtagarm7tdmi_nop( 0);
- cmddatalong[7] = jtagarm7tdmi_nop( 0);
- cmddatalong[8] = jtagarm7tdmi_nop( 0);
- cmddatalong[9] = jtagarm7tdmi_nop( 0);
+//! Get all registers, placing them into cmddatalong[0-14]
+void jtagarm7tdmi_get_registers() {
+ jtagarm7tdmi_nop( 0);
+ jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
+ jtagarm7tdmi_nop( 0);
+ jtagarm7tdmi_nop( 0);
+ cmddatalong[ 0] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 1] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 2] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 3] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 4] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 5] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 6] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 7] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 8] = jtagarm7tdmi_nop( 0);
+ cmddatalong[ 9] = jtagarm7tdmi_nop( 0);
cmddatalong[10] = jtagarm7tdmi_nop( 0);
cmddatalong[11] = jtagarm7tdmi_nop( 0);
cmddatalong[12] = jtagarm7tdmi_nop( 0);
cmddatalong[13] = jtagarm7tdmi_nop( 0);
cmddatalong[14] = jtagarm7tdmi_nop( 0);
cmddatalong[15] = jtagarm7tdmi_nop( 0);
- cmddatalong[16] = jtagarm7tdmi_nop( 0);
- cmddatalong[17] = jtagarm7tdmi_nop( 0);
- cmddatalong[18] = jtagarm7tdmi_nop( 0);
- cmddatalong[19] = jtagarm7tdmi_nop( 0);
- cmddatalong[20] = jtagarm7tdmi_nop( 0);
- return registers;
+ jtagarm7tdmi_nop( 0);
}
-//! Get all registers. Return an array
-unsigned long* jtagarm7tdmi_set_registers() {
- cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_SKANKREGS,0);
- cmddatalong[2] = jtagarm7tdmi_nop( 0);
- cmddatalong[3] = jtagarm7tdmi_nop( 0);
- cmddatalong[4] = jtagarm7tdmi_instr_primitive(0x40,0);
- cmddatalong[5] = jtagarm7tdmi_instr_primitive(0x41,0);
- cmddatalong[6] = jtagarm7tdmi_instr_primitive(0x42,0);
- cmddatalong[7] = jtagarm7tdmi_instr_primitive(0x43,0);
- cmddatalong[8] = jtagarm7tdmi_instr_primitive(0x44,0);
- cmddatalong[9] = jtagarm7tdmi_instr_primitive(0x45,0);
- cmddatalong[10] = jtagarm7tdmi_instr_primitive(0x46,0);
- cmddatalong[11] = jtagarm7tdmi_instr_primitive(0x47,0);
- cmddatalong[12] = jtagarm7tdmi_instr_primitive(0x48,0);
- cmddatalong[13] = jtagarm7tdmi_instr_primitive(0x49,0);
- cmddatalong[14] = jtagarm7tdmi_instr_primitive(0x4a,0);
- cmddatalong[15] = jtagarm7tdmi_instr_primitive(0x4b,0);
- cmddatalong[16] = jtagarm7tdmi_instr_primitive(0x4c,0);
- cmddatalong[17] = jtagarm7tdmi_instr_primitive(0x4d,0);
- cmddatalong[18] = jtagarm7tdmi_instr_primitive(0x4e,0);
- cmddatalong[19] = jtagarm7tdmi_instr_primitive(0x4f,0);
- return registers;
+//! Set all registers from cmddatalong[0-14]
+void jtagarm7tdmi_set_registers() { // using r15 to write through. not including it. use set_pc
+ jtagarm7tdmi_nop( 0);
+ debughex32(jtagarm7tdmi_instr_primitive(ARM_INSTR_CLOBBEREGS,0));
+ jtagarm7tdmi_nop( 0);
+ jtagarm7tdmi_nop( 0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[0],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[1],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[2],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[3],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[4],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[5],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[6],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[7],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[8],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[9],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[10],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[11],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[12],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[13],0);
+ jtagarm7tdmi_instr_primitive(cmddatalong[14],0);
+ jtagarm7tdmi_nop( 0);
}
//! Retrieve the CPSR Register value
unsigned long jtagarm7tdmi_get_regCPSR() {
- unsigned long retval = 0;
-
- cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
- cmddatalong[2] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0); // push MRS_R0, CPSR into pipeline
- cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
- cmddatalong[4] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
- cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
- retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
- cmddatalong[6] = retval;
+ unsigned long retval = 0L, r0;
+
+ r0 = jtagarm7tdmi_get_register(0);
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
+ jtagarm7tdmi_instr_primitive(ARM_INSTR_MRS_R0_CPSR, 0); // push MRS_R0, CPSR into pipeline - fetch
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
+ jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
+ retval = jtagarm7tdmi_get_register(0);
+ jtagarm7tdmi_set_register(0, r0);
return retval;
}
//! Retrieve the CPSR Register value
unsigned long jtagarm7tdmi_set_regCPSR(unsigned long val) {
- unsigned long retval = 0;
-
- cmddatalong[1] = jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
- cmddatalong[1] = jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0); // push MSR cpsr_cxsf, R0 into pipeline
- cmddatalong[2] = jtagarm7tdmi_nop( 0); // push nop into pipeline - fetched
- cmddatalong[3] = jtagarm7tdmi_nop( 0); // push nop into pipeline - decoded
-
- retval = jtagarm7tdmi_instr_primitive(val, 0);// push 32-bit word on data bus
- cmddatalong[5] = jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
- cmddatalong[4] = retval;
- return(retval);
+ unsigned long r0;
+
+ r0 = jtagarm7tdmi_get_register(0);
+ jtagarm7tdmi_set_register(0, val);
+ debughex32(jtagarm7tdmi_nop( 0)); // push nop into pipeline - clean out the pipeline...
+ debughex32(jtagarm7tdmi_instr_primitive(ARM_INSTR_MSR_cpsr_cxsf_R0, 0)); // push MSR cpsr_cxsf, R0 into pipeline - fetch
+ debughex32(jtagarm7tdmi_nop( 0)); // push nop into pipeline - decoded
+ debughex32(jtagarm7tdmi_nop( 0)); // push nop into pipeline - execute
+ jtagarm7tdmi_set_register(0, r0);
+ return(val);
}
//! Write data to address - Assume TAP in run-test/idle state
unsigned long jtagarm7tdmi_writemem(unsigned long adr, unsigned long data){
- unsigned long r0=0, r1=-1;
+ unsigned long retval = 0xffL;
+ unsigned long r0=0L, r1=-1L;
r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
r1 = jtagarm7tdmi_get_register(1);
jtagarm7tdmi_set_register(0, adr); // write address into R0
jtagarm7tdmi_set_register(1, data); // write data in R1
+ debughex32(jtagarm7tdmi_get_register(0));
+ debughex32(jtagarm7tdmi_get_register(1));
jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
- jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
+ jtagarm7tdmi_instr_primitive(ARM_INSTR_STR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
jtagarm7tdmi_nop( 0); // push nop into pipeline
- jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
- jtagarm7tdmi_set_register(0, r0);
- return(-1);
+ jtagarm7tdmi_restart(); // SHIFT_IR with RESTART instruction
+
+ // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
+ while ((!(current_dbgstate & 9L) == 9) && retval > 0){
+ delay(1);
+ retval --;
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
+ }
+ if (retval == 0){
+ debugstr("FAILED TO WRITE MEMORY/RE-ENTER DEBUG MODE");
+ return (-1);
+ } else {
+ retval = jtagarm7tdmi_get_register(1); // read memory value from R1 register
+ jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
+ jtagarm7tdmi_set_register(0, r0);
+ }
+ return retval;
}
//! Read data from address
unsigned long jtagarm7tdmi_readmem(unsigned long adr){
- unsigned long retval = 0;
- unsigned long r0=0, r1=-1;
- int waitcount = 0xfff;
+ unsigned long retval = 0xffL;
+ unsigned long r0=0L, r1=-1L;
r0 = jtagarm7tdmi_get_register(0); // store R0 and R1
r1 = jtagarm7tdmi_get_register(1);
jtagarm7tdmi_set_register(0, adr); // write address into R0
jtagarm7tdmi_nop( 0); // push nop into pipeline to "clean" it ???
jtagarm7tdmi_nop( 1); // push nop into pipeline with BREAKPT set
- jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, R0, #4 into instruction pipeline
+ jtagarm7tdmi_instr_primitive(ARM_INSTR_LDR_R1_r0_4, 0); // push LDR R1, [R0], #4 into instruction pipeline (autoincrements for consecutive reads)
jtagarm7tdmi_nop( 0); // push nop into pipeline
jtagarm7tdmi_restart(); // SHIFT_IR with RESTART instruction
// Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
- while ((jtagarm7tdmi_get_dbgstate() & 9) == 0 && waitcount > 0){
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
+ debughex(current_dbgstate);
+ while ((!(current_dbgstate & 9L) == 9) && retval > 0){
delay(1);
- waitcount --;
+ retval --;
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
}
- if (waitcount == 0){
+ // FIXME: this may end up changing te current debug-state. should we compare to current_dbgstate?
+ if (retval == 0){
+ debugstr("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE");
return (-1);
} else {
retval = jtagarm7tdmi_get_register(1); // read memory value from R1 register
- jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
- jtagarm7tdmi_set_register(0, r0);
+ //jtagarm7tdmi_set_register(1, r1); // restore R0 and R1
+ //jtagarm7tdmi_set_register(0, r0);
}
return retval;
}
//! Read Program Counter
unsigned long jtagarm7tdmi_getpc(){
- return jtagarm7tdmi_get_register(ARM_REG_PC);
+ unsigned long val;
+ val = jtagarm7tdmi_get_register(ARM_REG_PC);
+ if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
+ val -= (4*2); // thumb uses 2 bytes per instruction.
+ else
+ val -= (6*4); // assume 6 instructions at 4 bytes a piece.
+ return val;
}
-//! Set Program Counter
-unsigned long jtagarm7tdmi_setpc(unsigned long adr){
- return jtagarm7tdmi_set_register(ARM_REG_PC, adr);
+//! Set Program Counter - if setting it to non-word-aligned anything, crap may not like you. you've been warned
+void jtagarm7tdmi_setpc(unsigned long adr){
+ jtagarm7tdmi_set_register(ARM_REG_PC, adr);
}
//! Halt CPU - returns 0xffff if the operation fails to complete within
unsigned long jtagarm7tdmi_haltcpu(){ // PROVEN
- int waitcount = 0xfff;
+ int waitcount = 0xfffL;
+ // store the debug state
+ last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
// store watchpoint info? - not right now
- eice_write(EICE_WP1ADDR, 0); // write 0 in watchpoint 1 address
+ eice_write(EICE_WP1ADDR, 0L); // write 0 in watchpoint 1 address
eice_write(EICE_WP1ADDRMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 address mask
- eice_write(EICE_WP1DATA, 0); // write 0 in watchpoint 1 data
+ eice_write(EICE_WP1DATA, 0L); // write 0 in watchpoint 1 data
eice_write(EICE_WP1DATAMASK, 0xffffffff); // write 0xffffffff in watchpoint 1 data mask
- eice_write(EICE_WP1CTRL, 0x100); //!!!!! WTF! THIS IS SUPPOSED TO BE 9 bits wide?!? // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
- 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
+ eice_write(EICE_WP1CTRL, 0x100L); // write 0x00000100 in watchpoint 1 control value register (enables watchpoint)
+ eice_write(EICE_WP1CTRLMASK, 0xfffffff7); // write 0xfffffff7 in watchpoint 1 control mask - only detect the fetch instruction
// poll until debug status says the cpu is in debug mode
- while (!(jtagarm7tdmi_get_dbgstate() & 0x1) && waitcount-- > 0){
+ while (!(current_dbgstate & 0x1L) && waitcount-- > 0){
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
delay(1);
}
- eice_write(EICE_WP1CTRL, 0x0); // write 0 in watchpoint 0 control value - disables watchpoint 0
- // store the debug state
- last_halt_debug_state = jtagarm7tdmi_get_dbgstate();
- last_halt_pc = jtagarm7tdmi_getpc() - 4; // assume -4 for entering debug mode via watchpoint.
- count_dbgspd_instr_since_debug = 0;
- count_sysspd_instr_since_debug = 0;
+ eice_write(EICE_WP1CTRL, 0x0L); // write 0 in watchpoint 0 control value - disables watchpoint 0
+ // store the debug state program counter.
+ last_halt_pc = jtagarm7tdmi_getpc();
+ count_dbgspd_instr_since_debug = 0L; // should be able to clean this up and remove all this tracking nonsense.
+ count_sysspd_instr_since_debug = 0L; // should be able to clean this up and remove all this tracking nonsense.
+
+ //FIXME: is this necessary? for now, yes... but perhaps make the rest of the module arm/thumb impervious.
// get into ARM mode if the T flag is set (Thumb mode)
- while (jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_TBIT && waitcount-- > 0) {
- jtagarm7tdmi_setMode_ARM();
+ while (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT && waitcount-- > 0) {
+ jtagarm7tdmi_setMode_ARM(0);
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
}
jtagarm7tdmi_resettap();
+ jtagarm7tdmi_set_register(ARM_REG_PC, last_halt_pc & 0xfffffffc); // make sure PC is word-aligned. otherwise all other register accesses get all wonky.
return waitcount;
}
jtagarm7tdmi_nop(0); // NOP
jtagarm7tdmi_nop(1); // NOP/BREAKPT
+
+ // four possible states. arm mode needing arm mode, arm mode needing thumb mode, thumb mode needing arm mode, and thumb mode needing thumb mode
+ // FIXME: BX is bs. it requires the clobbering of at least one register.... this is not acceptable.
+ // FIXME: so we either switch modes, then correct the register before restarting with bx, or find the way to use SPSR
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?
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?
jtagarm7tdmi_instr_primitive(instr,0);
jtagarm7tdmi_instr_primitive(instr,0);
}
- SHIFT_IR;
- jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE); // VERB_RESTART
+ jtagarm7tdmi_restart();
+ //SHIFT_IR;
+ //jtagarmtransn(ARM7TDMI_IR_RESTART,4,LSB,END,RETIDLE); // VERB_RESTART
// wait until restart-bit set in debug state register
- while ((jtagarm7tdmi_get_dbgstate() & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
+ while ((current_dbgstate & JTAG_ARM7TDMI_DBG_DBGACK) && waitcount > 0){
msdelay(1);
waitcount --;
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
}
last_halt_debug_state = -1;
last_halt_pc = -1;
void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
register char blocks;
- unsigned int i,val,mlop;
+ unsigned int i,val;
unsigned long at;
+ current_dbgstate = jtagarm7tdmi_get_dbgstate();
jtagarm7tdmi_resettap();
switch(verb){
case START:
//Enter JTAG mode.
- cmddatalong[0] = jtagarm7tdmi_start();
- cmddatalong[2] = jtagarm7tdmi_haltcpu();
+ debughex32(jtagarm7tdmi_start());
+ debughex32(jtagarm7tdmi_haltcpu());
//jtagarm7tdmi_resettap();
- cmddatalong[1] = jtagarm7tdmi_get_dbgstate();
-
- // DEBUG: FIXME: NOT PART OF OPERATIONAL CODE
- //for (mlop=2;mlop<4;mlop++){
- // jtagarm7tdmi_set_register(mlop, 0x43424140);
- //}
- /////////////////////////////////////////////
- txdata(app,verb,0xc);
+ cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
+ txdata(app,verb,0x36);
break;
case JTAGARM7TDMI_READMEM:
- case PEEK:
- blocks=(len>4?cmddata[4]:1);
- at=cmddatalong[0];
+ at = cmddatalong[0];
+ blocks = cmddatalong[1];
- len=0x80;
txhead(app,verb,len);
- while(blocks--){
- for(i=0;i<len;i+=2){
jtagarm7tdmi_resettap();
- delay(10);
+ delay(1);
- val=jtagarm7tdmi_readmem(at);
+ for(i=0;i<blocks;i++){
+ val=jtagarm7tdmi_readmem(at);
- at+=2;
- serial_tx(val&0xFF);
- serial_tx((val&0xFF00)>>8);
+ serial_tx(val&0xFFL);
+ serial_tx((val&0xFF00L)>>8);
+ serial_tx((val&0xFF0000L)>>8);
+ serial_tx((val&0xFF000000L)>>8);
+ at+=4;
}
- }
+
+ break;
+ case PEEK:
+ jtagarm7tdmi_resettap();
+ delay(1);
+ cmddatalong[0] = jtagarm7tdmi_readmem(cmddatalong[0]);
+ txdata(app,verb,4);
break;
case JTAGARM7TDMI_GET_CHIP_ID:
jtagarm7tdmi_resettap();
jtagarm7tdmi_writemem(cmddatalong[0],
cmddataword[2]);
cmddataword[0]=jtagarm7tdmi_readmem(cmddatalong[0]);
- txdata(app,verb,2);
+ txdata(app,verb,4);
break;
case JTAGARM7TDMI_HALTCPU:
//case JTAGARM7TDMI_WRITEFLASH:
//case JTAGARM7TDMI_ERASEFLASH:
case JTAGARM7TDMI_SET_PC:
- cmddatalong[0] = jtagarm7tdmi_setpc(cmddatalong[0]);
- txdata(app,verb,4);
+ jtagarm7tdmi_setpc(cmddatalong[0]);
+ txdata(app,verb,0);
break;
case JTAGARM7TDMI_GET_DEBUG_CTRL:
cmddatalong[0] = jtagarm7tdmi_get_dbgctrl();
break;
case JTAGARM7TDMI_GET_DEBUG_STATE:
//jtagarm7tdmi_resettap(); // Shouldn't need this, but currently do. FIXME!
- cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
+ cmddatalong[0] = current_dbgstate;
txdata(app,verb,4);
break;
//case JTAGARM7TDMI_GET_WATCHPOINT:
//case JTAGARM7TDMI_SET_WATCHPOINT:
case JTAGARM7TDMI_GET_REGISTER:
jtagarm7tdmi_resettap();
- cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
- //cmddatalong[0] = test_get_register(cmddata[0]);
- txdata(app,verb,96);
+ val = cmddata[0];
+ cmddatalong[0] = jtagarm7tdmi_get_register(val);
+ txdata(app,verb,4);
break;
- case JTAGARM7TDMI_SET_REGISTER: // FIXME: NOT AT ALL CORRECT, THIS IS TESTING CODE ONLY
+ case JTAGARM7TDMI_SET_REGISTER:
jtagarm7tdmi_resettap();
- cmddatalong[0] = cmddatalong[1];
- jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
- //test_set_register(cmddata[0], cmddatalong[1]);
- txdata(app,verb,96);
+ jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
+ txdata(app,verb,4);
break;
case JTAGARM7TDMI_GET_REGISTERS:
jtagarm7tdmi_resettap();
jtagarm7tdmi_get_registers();
- txdata(app,verb,200);
+ txdata(app,verb,64);
break;
case JTAGARM7TDMI_SET_REGISTERS:
jtagarm7tdmi_resettap();
jtagarm7tdmi_set_registers();
- txdata(app,verb,200);
+ txdata(app,verb,64);
break;
case JTAGARM7TDMI_DEBUG_INSTR:
jtagarm7tdmi_resettap();
case JTAGARM7TDMI_SET_MODE_THUMB:
case JTAGARM7TDMI_SET_MODE_ARM:
jtagarm7tdmi_resettap();
- cmddataword[0] = jtagarm7tdmi_setMode_ARM();
+ cmddataword[0] = jtagarm7tdmi_setMode_ARM(0);
txdata(app,verb,4);
break;
Undefined instruction mode shadow registers
sp_und: 00000000 lr_und: 00000000 spsr_und: 300000df
>
-
+*/