X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=firmware%2Fapps%2Fjtag%2Fjtagarm7.c;h=f195679527e16006ae6daa0f9883f4e6dd278fbb;hp=63ab7469850bec9e0b9890933a04b1e10cb8d7a6;hb=d20a94438bdb6f1e14374b2ec3c08529316714e9;hpb=373f6c85cd1a08942b56aa62ead944638c804af0 diff --git a/firmware/apps/jtag/jtagarm7.c b/firmware/apps/jtag/jtagarm7.c index 63ab746..f195679 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 @@ -58,6 +46,16 @@ void jtagarm7tdmi_start() { * *get_register * *set_register */ +// TODO: +// * fix set_register to handle pc again. apparently it got broken when i fixed the dclk timing issue. +// +// ! 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; @@ -113,6 +111,7 @@ 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) @@ -131,49 +130,103 @@ 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 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_instr_primitive(val, 0); // push 32-bit word on data bus + jtagarm7tdmi_nop( 0); // push nop into pipeline - decode + jtagarm7tdmi_nop( 0); // push nop into pipeline - execute } 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_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_nop( 0); // push nop into pipeline - executed +} + +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_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); + 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); } @@ -215,7 +268,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]); @@ -234,6 +287,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: