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 jtagarm7tdmi_get_register(unsigned long reg) { //PROVEN
141 unsigned long retval=0L, instr;
142 current_dbgstate = eice_read(EICE_DBGSTATUS);
143 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
144 instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
146 instr = (unsigned long)(reg<<12L) | (unsigned long)ARM_READ_REG; // STR Rx, [R14]
149 jtagarm7tdmi_nop( 0);
150 jtagarm7tdmi_instr_primitive(instr, 0);
151 jtagarm7tdmi_nop( 0);
152 jtagarm7tdmi_nop( 0);
153 jtagarm7tdmi_nop( 0);
154 retval = jtagarm7tdmi_nop( 0); // recover 32-bit word
158 //! Set a 32-bit Register value
159 // 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.
160 // 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
161 // 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
163 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) { // PROVEN (assuming target reg is word aligned)
165 current_dbgstate = eice_read(EICE_DBGSTATUS);
166 if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
167 instr = THUMB_WRITE_REG | (reg&7) | ((reg&7)<<16) | ((reg&7)<<3) | ((reg&7)<<19);
169 instr = ARM_WRITE_REG | (reg<<12L) | (reg<<16); // LDR Rx, [R14]
173 // --- first time to clear the register... this ensures the write is not 8-bit offset ---
174 jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
175 jtagarm7tdmi_nop( 0); // push nop into pipeline - clean out the pipeline...
176 jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
177 if (reg == ARM_REG_PC){
178 jtagarm7tdmi_instr_primitive(0, 0); // push 32-bit word on data bus
179 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
180 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
182 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
183 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
184 jtagarm7tdmi_instr_primitive(0, 0); // push 32-bit word on data bus
186 // --- now we actually write to the register ---
187 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
188 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
189 jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
190 if (reg == ARM_REG_PC){
191 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
192 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
193 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
195 jtagarm7tdmi_nop( 0); // push nop into pipeline - decode
196 jtagarm7tdmi_nop( 0); // push nop into pipeline - execute
197 jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
199 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
200 jtagarm7tdmi_nop( 0); // push nop into pipeline - executed
201 jtagarm7tdmi_nop( 0);
205 ///////////////////////////////////////////////////////////////////////////////////////////////////
206 //! Handles ARM7TDMI JTAG commands. Forwards others to JTAG.
207 void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len){
213 jtagarm7tdmi_start();
217 cmddataword[0] = shift_ir(cmddata[0], cmddata[1]);
221 jtag_goto_shift_dr();
222 cmddatalong[0] = jtagtransn(cmddatalong[1],cmddata[0],cmddata[1]);
225 case JTAGARM7_CHAIN0:
226 jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
227 jtag_goto_shift_dr();
228 //debughex32(cmddatalong[0]);
229 //debughex(cmddataword[4]);
230 //debughex32(cmddatalong[1]);
231 //debughex32(cmddatalong[3]);
232 cmddatalong[0] = jtagtransn(cmddatalong[0], 32, LSB| NOEND| NORETIDLE);
233 cmddatalong[2] = jtagtransn(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
234 cmddatalong[1] = jtagtransn(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
235 cmddatalong[3] = jtagtransn(cmddatalong[3], 32, MSB);
238 case JTAGARM7_SCANCHAIN1:
239 case JTAGARM7_DEBUG_INSTR:
240 cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
243 case JTAGARM7_EICE_READ:
244 cmddatalong[0] = eice_read(cmddata[0]);
245 txdata(app,verb,0x4);
247 case JTAGARM7_EICE_WRITE:
248 eice_write(cmddata[4], cmddatalong[0]);
251 case JTAGARM7_GET_REGISTER:
253 cmddatalong[0] = jtagarm7tdmi_get_register(val);
256 case JTAGARM7_SET_REGISTER:
257 jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
260 case JTAG_RESETTARGET:
267 //case JTAGARM7_STEP_INSTR:
268 /* case JTAGARM7_READ_CODE_MEMORY:
269 case JTAGARM7_WRITE_FLASH_PAGE:
270 case JTAGARM7_READ_FLASH_PAGE:
271 case JTAGARM7_MASS_ERASE_FLASH:
272 case JTAGARM7_PROGRAM_FLASH:
273 case JTAGARM7_LOCKCHIP:
274 case JTAGARM7_CHIP_ERASE:
277 jtaghandle(app,verb,len);