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 // ! Start JTAG, setup pins, reset TAP and return IDCODE
51 void jtagarm7tdmi_start() {
58 u8 shift_ir(u8 ir, u8 flags){
61 retval = jtagtransn(ir, 4, LSB|flags);
65 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST
66 unsigned long jtagarm7tdmi_scan(u8 chain, u8 testmode) { // PROVEN
68 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
69 wise, when in debug state, the core will not be correctly isolated and intrusive
70 commands occur. Therefore, it is recommended to pass directly from the “Update”
71 state” to the “Select DR” state each time the “Update” state is reached.
74 shift_ir(ARM7TDMI_IR_SCAN_N, NORETIDLE);
76 retval = jtagtransn(chain, 4, LSB | NORETIDLE);
77 shift_ir(testmode, NORETIDLE);
82 /************************* EmbeddedICE Primitives ****************************/
83 //! shifter for writing to chain2 (EmbeddedICE).
84 unsigned long eice_write(unsigned char reg, unsigned long data){
85 unsigned long retval, temp;
86 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
88 retval = jtagtransn(data, 32, LSB| NOEND| NORETIDLE); // send in the data - 32-bits lsb
89 temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE); // send in the register address - 5 bits lsb
90 jtagtransn(1, 1, LSB); // send in the WRITE bit
94 //! shifter for reading from chain2 (EmbeddedICE).
95 unsigned long eice_read(unsigned char reg){ // PROVEN
96 unsigned long temp, retval;
97 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
98 jtag_goto_shift_dr(); // send in the register address - 5 bits LSB
99 temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE);
100 jtagtransn(0L, 1, LSB); // clear TDI to select "read only"
101 jtag_goto_shift_dr(); // Now shift out the 32 bits
102 retval = jtagtransn(0L, 32, LSB); // atmel arm jtag docs pp.10-11: LSB first
107 //! push an instruction into the pipeline
108 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ // PROVEN
109 unsigned long retval;
110 jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
113 jtag_goto_shift_dr();
114 // if the next instruction is to run using MCLK (master clock), set TDI
125 // Now shift in the 32 bits
126 retval = jtagtransn(instr, 32, 0); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
130 u32 jtagarm7tdmi_nop(u8 brkpt){
131 // WARNING: current_dbgstate must be up-to-date before calling this function!!!!!
132 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
133 return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, brkpt);
134 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
137 /******************** Complex Commands **************************/
139 //! Retrieve a 32-bit Register value
140 unsigned long jtagarm7_get_reg_prim(unsigned long instr){
141 jtagarm7tdmi_nop( 0);
142 jtagarm7tdmi_instr_primitive(instr, 0);
143 jtagarm7tdmi_nop( 0);
144 jtagarm7tdmi_nop( 0);
145 jtagarm7tdmi_nop( 0);
146 return jtagarm7tdmi_nop( 0); // recover 32-bit word
149 //! Set a 32-bit Register value
150 void jtagarm7_set_reg_prim(unsigned long instr, unsigned long reg, unsigned long val){ // PROVEN - 100827 (non-PC)
151 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
152 jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
153 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
154 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
155 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
156 if (reg == ARM_REG_PC){
157 debugstr("setting pc...");
158 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
159 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
161 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
162 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
165 void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){ // PROVEN - 100827
167 jtagarm7tdmi_nop( 0);
169 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)), 0);
170 debughex32((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)));
172 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)), 0);
173 debughex32((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)));
175 jtagarm7tdmi_nop( 0);
176 jtagarm7tdmi_nop( 0);
177 jtagarm7tdmi_nop( 0);
180 unsigned long jtagarm7tdmi_get_register(unsigned long reg) { // PROVEN - 100827
181 unsigned long retval=0L, instr, r0;
182 current_dbgstate = eice_read(EICE_DBGSTATUS);
183 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
185 debugstr("debug: jtagarm7tdmi_get_register: thumb reg > 15");
187 r0 = jtagarm7_get_reg_prim( THUMB_READ_REG); // save reg0
188 jtagarm7_thumb_swap_reg(THUMB_SWAP_HiLo, reg); // clobber reg0 with hi reg
189 retval = jtagarm7_get_reg_prim( THUMB_READ_REG); // recover 32-bit word
190 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
193 instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
196 instr = (reg<<12L) | ARM_READ_REG; // STR Rx, [R14]
197 return jtagarm7_get_reg_prim(instr);
200 //! Set a 32-bit Register value
201 // 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.
202 // 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
203 // 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
205 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN - 100827
206 unsigned long instr, r0;
207 current_dbgstate = eice_read(EICE_DBGSTATUS);
208 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
211 r0 = jtagarm7_get_reg_prim(THUMB_READ_REG);
212 jtagarm7_set_reg_prim(THUMB_WRITE_REG, 0, 0);
213 instr = (unsigned long)(THUMB_WRITE_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
214 jtagarm7_set_reg_prim(instr, reg, val);
215 jtagarm7_thumb_swap_reg(THUMB_SWAP_LoHi, reg); // place 32-bit word into a high register
216 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
218 instr = THUMB_WRITE_REG | (reg) | ((reg)<<16) | ((reg)<<3) | ((reg)<<19);
220 instr = ARM_WRITE_REG | (reg<<12L) | (reg<<16); // LDR Rx, [R14]
224 // --- first time to clear the register... this ensures the write is not 8-bit offset ---
225 jtagarm7_set_reg_prim(instr, reg, 0);
226 // --- now we actually write to the register ---
227 jtagarm7_set_reg_prim(instr, reg, val);
231 ///////////////////////////////////////////////////////////////////////////////////////////////////
232 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
233 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
239 jtagarm7tdmi_start();
243 cmddataword[0] = shift_ir(cmddata[0], cmddata[1]);
247 jtag_goto_shift_dr();
248 cmddatalong[0] = jtagtransn(cmddatalong[1],cmddata[0],cmddata[1]);
251 case JTAGARM7_CHAIN0:
252 jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
253 jtag_goto_shift_dr();
254 //debughex32(cmddatalong[0]);
255 //debughex(cmddataword[4]);
256 //debughex32(cmddatalong[1]);
257 //debughex32(cmddatalong[3]);
258 cmddatalong[0] = jtagtransn(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
259 cmddatalong[2] = jtagtransn(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
260 cmddatalong[1] = jtagtransn(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
261 cmddatalong[3] = jtagtransn(cmddatalong[3], 32, MSB);
264 case JTAGARM7_SCANCHAIN1:
265 case JTAGARM7_DEBUG_INSTR:
266 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
269 case JTAGARM7_EICE_READ:
270 cmddatalong[0] = eice_read(cmddata[0]);
271 txdata(app,verb,0x4);
273 case JTAGARM7_EICE_WRITE:
274 eice_write(cmddata[4], cmddatalong[0]);
277 case JTAGARM7_GET_REGISTER:
279 cmddatalong[0] = jtagarm7tdmi_get_register(val);
282 case JTAGARM7_SET_REGISTER:
283 jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
286 case JTAG_RESETTARGET:
288 debugstr("RESET TARGET");
290 delay(cmddataword[0]);
296 //case JTAGARM7_STEP_INSTR:
297 /* case JTAGARM7_READ_CODE_MEMORY:
298 case JTAGARM7_WRITE_FLASH_PAGE:
299 case JTAGARM7_READ_FLASH_PAGE:
300 case JTAGARM7_MASS_ERASE_FLASH:
301 case JTAGARM7_PROGRAM_FLASH:
302 case JTAGARM7_LOCKCHIP:
303 case JTAGARM7_CHIP_ERASE:
306 jtaghandle(app,verb,len);