2 \brief ARM7TDMI JTAG (AT91R40008, AT91SAM7xxx)
10 /**** 20-pin Connection Information (pin1 is on top-right for both connectors)****
11 GoodFET -> 7TDMI 20-pin connector (HE-10 connector)
18 9 4,6,8,10,12,14,16,18,20 (GND)
19 11 17/3 (nTRST) (different sources suggest 17 or 3 alternately)
20 ********************************/
22 /**** 14-pin Connection Information (pin1 is on top-right for both connectors)****
23 GoodFET -> 7TDMI 14-pin connector
33 http://hri.sourceforge.net/tools/jtag_faq_org.html
34 ********************************/
36 /* WHAT SHOULD THIS MODULE DO?
42 * *scanchain1 (instr_primitive)
43 * *scanchain2 (hmmmm... perhaps we'll need to keep the debug calls)
50 // * fix set_register to handle pc again. apparently it got broken when i fixed the dclk timing issue.
52 // ! Start JTAG, setup pins, reset TAP and return IDCODE
53 void jtagarm7tdmi_start() {
60 u8 shift_ir(u8 ir, u8 flags){
63 retval = jtagtransn(ir, 4, LSB|flags);
67 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST
68 unsigned long jtagarm7tdmi_scan(u8 chain, u8 testmode) { // PROVEN
70 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
71 wise, when in debug state, the core will not be correctly isolated and intrusive
72 commands occur. Therefore, it is recommended to pass directly from the “Update”
73 state” to the “Select DR” state each time the “Update” state is reached.
76 shift_ir(ARM7TDMI_IR_SCAN_N, NORETIDLE);
78 retval = jtagtransn(chain, 4, LSB | NORETIDLE);
79 shift_ir(testmode, NORETIDLE);
84 /************************* EmbeddedICE Primitives ****************************/
85 //! shifter for writing to chain2 (EmbeddedICE).
86 unsigned long eice_write(unsigned char reg, unsigned long data){
87 unsigned long retval, temp;
88 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
90 retval = jtagtransn(data, 32, LSB| NOEND| NORETIDLE); // send in the data - 32-bits lsb
91 temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE); // send in the register address - 5 bits lsb
92 jtagtransn(1, 1, LSB); // send in the WRITE bit
96 //! shifter for reading from chain2 (EmbeddedICE).
97 unsigned long eice_read(unsigned char reg){ // PROVEN
98 unsigned long temp, retval;
99 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
100 jtag_goto_shift_dr(); // send in the register address - 5 bits LSB
101 temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE);
102 jtagtransn(0L, 1, LSB); // clear TDI to select "read only"
103 jtag_goto_shift_dr(); // Now shift out the 32 bits
104 retval = jtagtransn(0L, 32, LSB); // atmel arm jtag docs pp.10-11: LSB first
109 //! push an instruction into the pipeline
110 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ // PROVEN
111 unsigned long retval;
112 jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
115 jtag_goto_shift_dr();
116 // if the next instruction is to run using MCLK (master clock), set TDI
127 // Now shift in the 32 bits
128 retval = jtagtransn(instr, 32, 0); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
132 u32 jtagarm7tdmi_nop(u8 brkpt){
133 // WARNING: current_dbgstate must be up-to-date before calling this function!!!!!
134 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
135 return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, brkpt);
136 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
139 /******************** Complex Commands **************************/
141 //! Retrieve a 32-bit Register value
142 unsigned long jtagarm7_get_reg_prim(unsigned long instr){
143 jtagarm7tdmi_nop( 0);
144 jtagarm7tdmi_instr_primitive(instr, 0);
145 jtagarm7tdmi_nop( 0);
146 jtagarm7tdmi_nop( 0);
147 jtagarm7tdmi_nop( 0);
148 return jtagarm7tdmi_nop( 0); // recover 32-bit word
151 //! Set a 32-bit Register value
152 void jtagarm7_set_reg_prim(unsigned long instr, unsigned long reg, unsigned long val){ // PROVEN - 100827 (non-PC)
153 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
154 jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
155 if (reg == ARM_REG_PC){
156 debugstr("setting pc...");
157 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
158 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
159 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
161 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
162 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
163 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
167 void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){ // PROVEN - 100827
169 jtagarm7tdmi_nop( 0);
171 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)), 0);
172 debughex32((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)));
174 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)), 0);
175 debughex32((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)));
177 jtagarm7tdmi_nop( 0);
178 jtagarm7tdmi_nop( 0);
179 jtagarm7tdmi_nop( 0);
182 unsigned long jtagarm7tdmi_get_register(unsigned long reg) { // PROVEN - 100827
183 unsigned long retval=0L, instr, r0;
184 current_dbgstate = eice_read(EICE_DBGSTATUS);
185 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
187 debugstr("debug: jtagarm7tdmi_get_register: thumb reg > 15");
189 r0 = jtagarm7_get_reg_prim( THUMB_READ_REG); // save reg0
190 jtagarm7_thumb_swap_reg(THUMB_SWAP_HiLo, reg); // clobber reg0 with hi reg
191 retval = jtagarm7_get_reg_prim( THUMB_READ_REG); // recover 32-bit word
192 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
195 instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
198 instr = (reg<<12L) | ARM_READ_REG; // STR Rx, [R14]
199 return jtagarm7_get_reg_prim(instr);
202 //! Set a 32-bit Register value
203 // 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.
204 // 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
205 // 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
207 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN - 100827
208 unsigned long instr, r0;
209 current_dbgstate = eice_read(EICE_DBGSTATUS);
210 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
213 r0 = jtagarm7_get_reg_prim(THUMB_READ_REG);
214 jtagarm7_set_reg_prim(THUMB_WRITE_REG, 0, 0);
215 instr = (unsigned long)(THUMB_WRITE_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
216 jtagarm7_set_reg_prim(instr, reg, val);
217 jtagarm7_thumb_swap_reg(THUMB_SWAP_LoHi, reg); // place 32-bit word into a high register
218 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
220 instr = THUMB_WRITE_REG | (reg) | ((reg)<<16) | ((reg)<<3) | ((reg)<<19);
222 instr = ARM_WRITE_REG | (reg<<12L) | (reg<<16); // LDR Rx, [R14]
226 // --- first time to clear the register... this ensures the write is not 8-bit offset ---
227 jtagarm7_set_reg_prim(instr, reg, 0);
228 // --- now we actually write to the register ---
229 jtagarm7_set_reg_prim(instr, reg, val);
230 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
231 jtagarm7tdmi_nop( 0);
235 ///////////////////////////////////////////////////////////////////////////////////////////////////
236 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
237 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
243 jtagarm7tdmi_start();
247 cmddataword[0] = shift_ir(cmddata[0], cmddata[1]);
251 jtag_goto_shift_dr();
252 cmddatalong[0] = jtagtransn(cmddatalong[1],cmddata[0],cmddata[1]);
255 case JTAGARM7_CHAIN0:
256 jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
257 jtag_goto_shift_dr();
258 //debughex32(cmddatalong[0]);
259 //debughex(cmddataword[4]);
260 //debughex32(cmddatalong[1]);
261 //debughex32(cmddatalong[3]);
262 cmddatalong[0] = jtagtransn(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
263 cmddatalong[2] = jtagtransn(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
264 cmddatalong[1] = jtagtransn(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
265 cmddatalong[3] = jtagtransn(cmddatalong[3], 32, MSB);
268 case JTAGARM7_SCANCHAIN1:
269 case JTAGARM7_DEBUG_INSTR:
270 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
273 case JTAGARM7_EICE_READ:
274 cmddatalong[0] = eice_read(cmddata[0]);
275 txdata(app,verb,0x4);
277 case JTAGARM7_EICE_WRITE:
278 eice_write(cmddata[4], cmddatalong[0]);
281 case JTAGARM7_GET_REGISTER:
283 cmddatalong[0] = jtagarm7tdmi_get_register(val);
286 case JTAGARM7_SET_REGISTER:
287 jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
290 case JTAG_RESETTARGET:
297 //case JTAGARM7_STEP_INSTR:
298 /* case JTAGARM7_READ_CODE_MEMORY:
299 case JTAGARM7_WRITE_FLASH_PAGE:
300 case JTAGARM7_READ_FLASH_PAGE:
301 case JTAGARM7_MASS_ERASE_FLASH:
302 case JTAGARM7_PROGRAM_FLASH:
303 case JTAGARM7_LOCKCHIP:
304 case JTAGARM7_CHIP_ERASE:
307 jtaghandle(app,verb,len);