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 jtagarm_shift_ir(u8 ir, u8 flags){
62 retval = jtagtransn(ir, 4, LSB|flags);
63 tapstate = RunTest_Idle;
69 //! Connect the appropriate scan chain to TDO/TDI. SCAN_N, INTEST
70 unsigned long jtagarm7tdmi_scan(u8 chain, u8 testmode) { // PROVEN
72 When selecting a scan chain the “Run Test/Idle” state should never be reached, other-
73 wise, when in debug state, the core will not be correctly isolated and intrusive
74 commands occur. Therefore, it is recommended to pass directly from the “Update”
75 state” to the “Select DR” state each time the “Update” state is reached.
77 unsigned long retval = 0;
78 if (last_scanchain != chain){
79 jtagarm_shift_ir(ARM7TDMI_IR_SCAN_N, NORETIDLE);
80 last_scanchain = chain;
82 retval = jtagtransn(chain, 4, LSB | NORETIDLE);
85 jtagarm_shift_ir(testmode, NORETIDLE);
90 /************************* EmbeddedICE Primitives ****************************/
91 //! shifter for writing to chain2 (EmbeddedICE).
92 unsigned long eice_write(unsigned char reg, unsigned long data){
93 unsigned long retval, temp;
94 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
96 retval = jtagtransn(data, 32, LSB| NOEND| NORETIDLE); // send in the data - 32-bits lsb
97 temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE); // send in the register address - 5 bits lsb
98 jtagtransn(1, 1, LSB); // send in the WRITE bit
99 tapstate = RunTest_Idle;
103 //! shifter for reading from chain2 (EmbeddedICE).
104 unsigned long eice_read(unsigned char reg){ // PROVEN
105 unsigned long temp, retval;
106 jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
107 jtag_goto_shift_dr(); // send in the register address - 5 bits LSB
108 temp = jtagtransn(reg, 5, LSB| NOEND| NORETIDLE);
109 jtagtransn(0L, 1, LSB); // clear TDI to select "read only"
110 jtag_goto_shift_dr(); // Now shift out the 32 bits
111 retval = jtagtransn(0L, 32, LSB); // atmel arm jtag docs pp.10-11: LSB first
112 tapstate = RunTest_Idle;
117 //! push an instruction into the pipeline
118 unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){ // PROVEN
119 unsigned long retval = 0;
120 jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
123 if (last_instr != instr && last_sysstate != breakpt){
124 jtag_goto_shift_dr();
125 // if the next instruction is to run using MCLK (master clock), set TDI
136 // Now shift in the 32 bits
137 retval = jtagtransn(instr, 32, 0); // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
138 tapstate = RunTest_Idle;
140 last_sysstate = breakpt;
146 u32 jtagarm7tdmi_nop(u8 brkpt){
147 // WARNING: current_dbgstate must be up-to-date before calling this function!!!!!
148 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
149 return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, brkpt);
150 return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
153 /******************** Complex Commands **************************/
155 //! Retrieve a 32-bit Register value
156 unsigned long jtagarm7_get_reg_prim(unsigned long instr){
157 jtagarm7tdmi_nop( 0);
158 jtagarm7tdmi_instr_primitive(instr, 0);
159 jtagarm7tdmi_nop( 0);
160 jtagarm7tdmi_nop( 0);
161 jtagarm7tdmi_nop( 0);
162 return jtagarm7tdmi_nop( 0); // recover 32-bit word
165 //! Set a 32-bit Register value
166 void jtagarm7_set_reg_prim(unsigned long instr, unsigned long reg, unsigned long val){ // PROVEN - 100827 (non-PC)
167 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
168 jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
169 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
170 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
171 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
172 if (reg == ARM_REG_PC){
173 //debugstr("setting pc...");
174 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
175 jtagarm7tdmi_nop( 0); // push nop into pipeline - refill
177 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
178 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
181 void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){ // PROVEN - 100827
183 jtagarm7tdmi_nop( 0);
185 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)), 0);
186 //debughex32((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)));
188 jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)), 0);
189 //debughex32((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)));
191 jtagarm7tdmi_nop( 0);
192 jtagarm7tdmi_nop( 0);
193 jtagarm7tdmi_nop( 0);
196 unsigned long jtagarm7tdmi_get_register(unsigned long reg) { // PROVEN - 100827
197 unsigned long retval=0L, instr, r0;
198 current_dbgstate = eice_read(EICE_DBGSTATUS);
199 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
201 //debugstr("debug: jtagarm7tdmi_get_register: thumb reg > 15");
203 r0 = jtagarm7_get_reg_prim( THUMB_READ_REG); // save reg0
204 jtagarm7_thumb_swap_reg(THUMB_SWAP_HiLo, reg); // clobber reg0 with hi reg
205 retval = jtagarm7_get_reg_prim( THUMB_READ_REG); // recover 32-bit word
206 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
209 instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
212 instr = (reg<<12L) | ARM_READ_REG; // STR Rx, [R14]
213 return jtagarm7_get_reg_prim(instr);
216 //! Set a 32-bit Register value
217 // 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.
218 // 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
219 // 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
221 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN - 100827
222 unsigned long instr, r0;
223 current_dbgstate = eice_read(EICE_DBGSTATUS);
224 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
227 r0 = jtagarm7_get_reg_prim(THUMB_READ_REG);
228 jtagarm7_set_reg_prim(THUMB_WRITE_REG, 0, 0);
229 instr = (unsigned long)(THUMB_WRITE_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
230 jtagarm7_set_reg_prim(instr, reg, val);
231 jtagarm7_thumb_swap_reg(THUMB_SWAP_LoHi, reg); // place 32-bit word into a high register
232 jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0); // restore r0
234 instr = THUMB_WRITE_REG | (reg) | ((reg)<<16) | ((reg)<<3) | ((reg)<<19);
236 instr = ARM_WRITE_REG | (reg<<12L) | (reg<<16); // LDR Rx, [R14]
240 // --- first time to clear the register... this ensures the write is not 8-bit offset ---
241 jtagarm7_set_reg_prim(instr, reg, 0);
242 // --- now we actually write to the register ---
243 jtagarm7_set_reg_prim(instr, reg, val);
247 ///////////////////////////////////////////////////////////////////////////////////////////////////
248 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
249 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
255 jtagarm7tdmi_start();
259 cmddataword[0] = jtagarm_shift_ir(cmddata[0], cmddata[1]);
263 jtag_goto_shift_dr();
264 cmddatalong[0] = jtagtransn(cmddatalong[1],cmddata[0],cmddata[1]);
265 tapstate = (cmddata[1]&NORETIDLE)>0?Update_DR:RunTest_Idle;
268 case JTAGARM7_CHAIN0:
269 jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
270 jtag_goto_shift_dr();
271 //debughex32(cmddatalong[0]);
272 //debughex(cmddataword[4]);
273 //debughex32(cmddatalong[1]);
274 //debughex32(cmddatalong[3]);
275 cmddatalong[0] = jtagtransn(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
276 cmddatalong[2] = jtagtransn(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
277 cmddatalong[1] = jtagtransn(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
278 cmddatalong[3] = jtagtransn(cmddatalong[3], 32, MSB);
279 tapstate = RunTest_Idle;
282 case JTAGARM7_SCANCHAIN1:
283 case JTAGARM7_DEBUG_INSTR:
284 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
287 case JTAGARM7_EICE_READ:
288 cmddatalong[0] = eice_read(cmddata[0]);
289 txdata(app,verb,0x4);
291 case JTAGARM7_EICE_WRITE:
292 eice_write(cmddata[4], cmddatalong[0]);
295 case JTAGARM7_GET_REGISTER:
297 cmddatalong[0] = jtagarm7tdmi_get_register(val);
300 case JTAGARM7_SET_REGISTER:
301 jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
304 case JTAG_RESETTARGET:
306 debugstr("RESET TARGET");
308 delay(cmddataword[0]);
314 //case JTAGARM7_STEP_INSTR:
315 /* case JTAGARM7_READ_CODE_MEMORY:
316 case JTAGARM7_WRITE_FLASH_PAGE:
317 case JTAGARM7_READ_FLASH_PAGE:
318 case JTAGARM7_MASS_ERASE_FLASH:
319 case JTAGARM7_PROGRAM_FLASH:
320 case JTAGARM7_LOCKCHIP:
321 case JTAGARM7_CHIP_ERASE:
324 jtaghandle(app,verb,len);