X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=firmware%2Fapps%2Fjtag%2Fjtagarm7.c;h=89e8c406b2339136ba7586bc5adcd6529fc0d0fd;hp=77e9c38846697dc0cd89fcaffdad745e67bb9e70;hb=5fb51d7210531187ca33cf44f1126de793f94520;hpb=4ba334e74eb758e67539b1b8b679cd3cbccd2433 diff --git a/firmware/apps/jtag/jtagarm7.c b/firmware/apps/jtag/jtagarm7.c index 77e9c38..89e8c40 100644 --- a/firmware/apps/jtag/jtagarm7.c +++ b/firmware/apps/jtag/jtagarm7.c @@ -1,11 +1,10 @@ -/*! \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)**** @@ -34,17 +33,6 @@ GoodFET -> 7TDMI 14-pin connector 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 @@ -59,10 +47,18 @@ void jtagarm7tdmi_start() { * *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; } @@ -75,12 +71,10 @@ commands occur. Therefore, it is recommended to pass directly from the “Update 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); } @@ -115,17 +109,16 @@ unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ 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(); @@ -135,49 +128,101 @@ unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ } 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); } @@ -195,12 +240,10 @@ void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len 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); @@ -208,10 +251,10 @@ void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len 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); @@ -221,7 +264,7 @@ void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len 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]); @@ -240,6 +283,11 @@ void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]); txdata(app,verb,4); break; + case JTAG_RESETTARGET: + CLRTST; + delay(10); + SETTST; + break; //case JTAGARM7_STEP_INSTR: