jtag: retire jtag_get/set_end_state()
[openocd.git] / src / target / feroceon.c
1 /***************************************************************************
2 * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
4 * *
5 * Copyright (C) 2008 by Hongtao Zheng *
6 * hontor@126.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23
24 /*
25 * Marvell Feroceon/Dragonite support.
26 *
27 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
28 * mimics the ARM926 ICE interface with the following differences:
29 *
30 * - the MOE (method of entry) reporting is not implemented
31 *
32 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
33 *
34 * - due to a different pipeline implementation, some injected debug
35 * instruction sequences have to be somewhat different
36 *
37 * Other issues:
38 *
39 * - asserting DBGRQ doesn't work if target is looping on the undef vector
40 *
41 * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
42 * not at the top, and rather meaningless due to existing discrepencies
43 *
44 * - the DCC channel is half duplex (only one FIFO for both directions) with
45 * seemingly no proper flow control.
46 *
47 * The Dragonite core is the non-mmu version based on the ARM966 model, and
48 * it shares the above issues as well.
49 */
50
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #include "arm926ejs.h"
56 #include "arm966e.h"
57 #include "target_type.h"
58 #include "register.h"
59 #include "arm_opcodes.h"
60
61
62 int feroceon_assert_reset(struct target *target)
63 {
64 struct arm *armv4_5 = target->arch_info;
65 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
66 int ud = arm7_9->use_dbgrq;
67
68 arm7_9->use_dbgrq = 0;
69 if (target->reset_halt)
70 arm7_9_halt(target);
71 arm7_9->use_dbgrq = ud;
72 return arm7_9_assert_reset(target);
73 }
74
75 int feroceon_dummy_clock_out(struct arm_jtag *jtag_info, uint32_t instr)
76 {
77 struct scan_field fields[3];
78 uint8_t out_buf[4];
79 uint8_t instr_buf[4];
80 uint8_t sysspeed_buf = 0x0;
81
82 /* prepare buffer */
83 buf_set_u32(out_buf, 0, 32, 0);
84
85 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
86
87 arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
88
89 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
90
91 fields[0].num_bits = 32;
92 fields[0].out_value = out_buf;
93 fields[0].in_value = NULL;
94
95 fields[1].num_bits = 3;
96 fields[1].out_value = &sysspeed_buf;
97 fields[1].in_value = NULL;
98
99 fields[2].num_bits = 32;
100 fields[2].out_value = instr_buf;
101 fields[2].in_value = NULL;
102
103 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
104
105 /* no jtag_add_runtest(0, TAP_DRPAUSE) here */
106
107 return ERROR_OK;
108 }
109
110 void feroceon_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc)
111 {
112 struct arm *armv4_5 = target->arch_info;
113 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
114 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
115
116 /*
117 * save r0 before using it and put system in ARM state
118 * to allow common handling of ARM and THUMB debugging
119 */
120
121 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
122 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
123 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
124
125 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
126 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
127 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
128 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
129 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
130 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
131
132 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
133 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
134 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
135 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
136 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
137 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
138 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
139
140 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 0);
141 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
142 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
143 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
144 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
145
146 jtag_execute_queue();
147
148 /*
149 * fix program counter:
150 * MOV R0, PC was the 7th instruction (+12)
151 * reading PC in Thumb state gives address of instruction + 4
152 */
153 *pc -= (12 + 4);
154 }
155
156 void feroceon_read_core_regs(struct target *target, uint32_t mask, uint32_t* core_regs[16])
157 {
158 int i;
159 struct arm *armv4_5 = target->arch_info;
160 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
161 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
162
163 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
164 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
165 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
166
167 for (i = 0; i <= 15; i++)
168 if (mask & (1 << i))
169 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
170
171 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
172 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
173 }
174
175 void feroceon_read_core_regs_target_buffer(struct target *target, uint32_t mask, void* buffer, int size)
176 {
177 int i;
178 struct arm *armv4_5 = target->arch_info;
179 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
180 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
181 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
182 uint32_t *buf_u32 = buffer;
183 uint16_t *buf_u16 = buffer;
184 uint8_t *buf_u8 = buffer;
185
186 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
187 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
188 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
189
190 for (i = 0; i <= 15; i++)
191 {
192 if (mask & (1 << i)) {
193 switch (size)
194 {
195 case 4:
196 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
197 break;
198 case 2:
199 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
200 break;
201 case 1:
202 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
203 break;
204 }
205 }
206 }
207
208 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
209 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
210 }
211
212 void feroceon_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
213 {
214 struct arm *armv4_5 = target->arch_info;
215 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
216 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
217
218 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
219 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
220 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
221 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
222 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
223 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
224 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
225
226 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
227 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
228 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
229 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
230
231 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
232 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
233 }
234
235 void feroceon_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
236 {
237 struct arm *armv4_5 = target->arch_info;
238 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
239 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
240
241 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
242
243 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
244 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
245 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
246 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
247 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
248 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
249 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
250
251 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
252 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
253 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
254 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
255 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
256 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
257 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
258
259 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
260 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
261 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
262 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
263 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
264 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
265 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
266
267 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
268 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
269 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
270 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
271 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
272 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
273 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
274 }
275
276 void feroceon_write_xpsr_im8(struct target *target, uint8_t xpsr_im, int rot, int spsr)
277 {
278 struct arm *armv4_5 = target->arch_info;
279 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
280 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
281
282 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
283
284 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
285 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
286 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
287 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
288 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
289 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
290 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
291 }
292
293 void feroceon_write_core_regs(struct target *target, uint32_t mask, uint32_t core_regs[16])
294 {
295 int i;
296 struct arm *armv4_5 = target->arch_info;
297 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
298 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
299
300 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
301 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
302 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
303
304 for (i = 0; i <= 15; i++)
305 if (mask & (1 << i))
306 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
307
308 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
309 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
310 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
311 }
312
313 void feroceon_branch_resume(struct target *target)
314 {
315 struct arm *armv4_5 = target->arch_info;
316 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
317 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
318
319 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
320 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
321 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
322 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
323 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
324
325 arm7_9->need_bypass_before_restart = 1;
326 }
327
328 void feroceon_branch_resume_thumb(struct target *target)
329 {
330 LOG_DEBUG("-");
331
332 struct arm *armv4_5 = target->arch_info;
333 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
334 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
335 uint32_t r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
336 uint32_t pc = buf_get_u32(armv4_5->pc->value, 0, 32);
337
338 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
339 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
340 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
341 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
342
343 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); // add r0,pc,#1
344 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
345 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
346 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
347
348 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0);
349 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
350 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
351
352 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, NULL, 0);
353 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
354 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
355
356 pc = (pc & 2) >> 1;
357 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
358 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
359
360 arm7_9->need_bypass_before_restart = 1;
361 }
362
363 int feroceon_read_cp15(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
364 {
365 struct arm *armv4_5 = target->arch_info;
366 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
367 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
368 int err;
369
370 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
371 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
372 err = arm7_9_execute_sys_speed(target);
373 if (err != ERROR_OK)
374 return err;
375
376 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
377 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
378 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
379 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0);
380 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
381 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
382 return jtag_execute_queue();
383 }
384
385 int feroceon_write_cp15(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
386 {
387 struct arm *armv4_5 = target->arch_info;
388 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
389 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
390
391 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
392 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
393 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
394 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0);
395 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
396 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
397 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
398
399 arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
400 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
401 return arm7_9_execute_sys_speed(target);
402 }
403
404 void feroceon_set_dbgrq(struct target *target)
405 {
406 struct arm *armv4_5 = target->arch_info;
407 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
408 struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
409
410 buf_set_u32(dbg_ctrl->value, 0, 8, 2);
411 embeddedice_store_reg(dbg_ctrl);
412 }
413
414 void feroceon_enable_single_step(struct target *target, uint32_t next_pc)
415 {
416 struct arm *armv4_5 = target->arch_info;
417 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
418
419 /* set a breakpoint there */
420 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
421 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
422 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
423 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
424 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
425 }
426
427 void feroceon_disable_single_step(struct target *target)
428 {
429 struct arm *armv4_5 = target->arch_info;
430 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
431
432 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
433 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
434 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
435 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
436 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
437 }
438
439 int feroceon_examine_debug_reason(struct target *target)
440 {
441 /* the MOE is not implemented */
442 if (target->debug_reason != DBG_REASON_SINGLESTEP)
443 {
444 target->debug_reason = DBG_REASON_DBGRQ;
445 }
446
447 return ERROR_OK;
448 }
449
450 int feroceon_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer)
451 {
452 int retval;
453 struct arm *armv4_5 = target->arch_info;
454 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
455 enum arm_state core_state = armv4_5->core_state;
456 uint32_t x, flip, shift, save[7];
457 uint32_t i;
458
459 /*
460 * We can't use the dcc flow control bits, so let's transfer data
461 * with 31 bits and flip the MSB each time a new data word is sent.
462 */
463 static uint32_t dcc_code[] =
464 {
465 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
466 0xe3a0301e, /* 1: mov r3, #30 */
467 0xe3a04002, /* mov r4, #2 */
468 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
469 0xe1310005, /* teq r1, r5 */
470 0x0afffffc, /* beq 1b */
471 0xe1a05001, /* mov r5, r1 */
472 0xe1a01081, /* mov r1, r1, lsl #1 */
473 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
474 0xe1320005, /* teq r2, r5 */
475 0x0afffffc, /* beq 3b */
476 0xe1a05002, /* mov r5, r2 */
477 0xe3c22102, /* bic r2, r2, #0x80000000 */
478 0xe1811332, /* orr r1, r1, r2, lsr r3 */
479 0xe2533001, /* subs r3, r3, #1 */
480 0xe4801004, /* str r1, [r0], #4 */
481 0xe1a01412, /* mov r1, r2, lsl r4 */
482 0xe2844001, /* add r4, r4, #1 */
483 0x4affffed, /* bmi 1b */
484 0xeafffff3, /* b 3b */
485 };
486
487 uint32_t dcc_size = sizeof(dcc_code);
488
489 if (!arm7_9->dcc_downloads)
490 return target_write_memory(target, address, 4, count, buffer);
491
492 /* regrab previously allocated working_area, or allocate a new one */
493 if (!arm7_9->dcc_working_area)
494 {
495 uint8_t dcc_code_buf[dcc_size];
496
497 /* make sure we have a working area */
498 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
499 {
500 LOG_INFO("no working area available, falling back to memory writes");
501 return target_write_memory(target, address, 4, count, buffer);
502 }
503
504 /* copy target instructions to target endianness */
505 for (i = 0; i < dcc_size/4; i++)
506 target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
507
508 /* write DCC code to working area */
509 if ((retval = target_write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf)) != ERROR_OK)
510 {
511 return retval;
512 }
513 }
514
515 /* backup clobbered processor state */
516 for (i = 0; i <= 5; i++)
517 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32);
518 save[i] = buf_get_u32(armv4_5->pc->value, 0, 32);
519
520 /* set up target address in r0 */
521 buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
522 armv4_5->core_cache->reg_list[0].valid = 1;
523 armv4_5->core_cache->reg_list[0].dirty = 1;
524 armv4_5->core_state = ARM_STATE_ARM;
525
526 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
527 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
528
529 /* send data over */
530 x = 0;
531 flip = 0;
532 shift = 1;
533 for (i = 0; i < count; i++)
534 {
535 uint32_t y = target_buffer_get_u32(target, buffer);
536 uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
537 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
538 x = y << (32 - shift);
539 if (++shift >= 32 || i + 1 >= count)
540 {
541 z = (x >> 1) | (flip ^= 0x80000000);
542 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
543 x = 0;
544 shift = 1;
545 }
546 buffer += 4;
547 }
548
549 retval = target_halt(target);
550 if (retval == ERROR_OK)
551 retval = target_wait_state(target, TARGET_HALTED, 500);
552 if (retval == ERROR_OK) {
553 uint32_t endaddress =
554 buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
555 if (endaddress != address + count*4) {
556 LOG_ERROR("DCC write failed,"
557 " expected end address 0x%08" PRIx32
558 " got 0x%0" PRIx32 "",
559 address + count*4, endaddress);
560 retval = ERROR_FAIL;
561 }
562 }
563
564 /* restore target state */
565 for (i = 0; i <= 5; i++)
566 {
567 buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, save[i]);
568 armv4_5->core_cache->reg_list[i].valid = 1;
569 armv4_5->core_cache->reg_list[i].dirty = 1;
570 }
571 buf_set_u32(armv4_5->pc->value, 0, 32, save[i]);
572 armv4_5->pc->valid = 1;
573 armv4_5->pc->dirty = 1;
574 armv4_5->core_state = core_state;
575
576 return retval;
577 }
578
579 int feroceon_init_target(struct command_context *cmd_ctx, struct target *target)
580 {
581 arm9tdmi_init_target(cmd_ctx, target);
582 return ERROR_OK;
583 }
584
585 void feroceon_common_setup(struct target *target)
586 {
587 struct arm *armv4_5 = target->arch_info;
588 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
589
590 /* override some insn sequence functions */
591 arm7_9->change_to_arm = feroceon_change_to_arm;
592 arm7_9->read_core_regs = feroceon_read_core_regs;
593 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
594 arm7_9->read_xpsr = feroceon_read_xpsr;
595 arm7_9->write_xpsr = feroceon_write_xpsr;
596 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
597 arm7_9->write_core_regs = feroceon_write_core_regs;
598 arm7_9->branch_resume = feroceon_branch_resume;
599 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
600
601 /* must be implemented with only one comparator */
602 arm7_9->enable_single_step = feroceon_enable_single_step;
603 arm7_9->disable_single_step = feroceon_disable_single_step;
604
605 /* MOE is not implemented */
606 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
607
608 /* Note: asserting DBGRQ might not win over the undef exception.
609 If that happens then just use "arm7_9 dbgrq disable". */
610 arm7_9->use_dbgrq = 1;
611 arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
612
613 /* only one working comparator */
614 arm7_9->wp_available_max = 1;
615 arm7_9->wp1_used_default = -1;
616 }
617
618 int feroceon_target_create(struct target *target, Jim_Interp *interp)
619 {
620 struct arm926ejs_common *arm926ejs = calloc(1,sizeof(struct arm926ejs_common));
621
622 arm926ejs_init_arch_info(target, arm926ejs, target->tap);
623 feroceon_common_setup(target);
624
625 /* the standard ARM926 methods don't always work (don't ask...) */
626 arm926ejs->read_cp15 = feroceon_read_cp15;
627 arm926ejs->write_cp15 = feroceon_write_cp15;
628
629 return ERROR_OK;
630 }
631
632 int dragonite_target_create(struct target *target, Jim_Interp *interp)
633 {
634 struct arm966e_common *arm966e = calloc(1,sizeof(struct arm966e_common));
635
636 arm966e_init_arch_info(target, arm966e, target->tap);
637 feroceon_common_setup(target);
638
639 return ERROR_OK;
640 }
641
642 int feroceon_examine(struct target *target)
643 {
644 struct arm *armv4_5;
645 struct arm7_9_common *arm7_9;
646 int retval;
647
648 retval = arm7_9_examine(target);
649 if (retval != ERROR_OK)
650 return retval;
651
652 armv4_5 = target->arch_info;
653 arm7_9 = armv4_5->arch_info;
654
655 /* the COMMS_CTRL bits are all contiguous */
656 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
657 LOG_ERROR("unexpected Feroceon EICE version signature");
658
659 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
660 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
661 arm7_9->has_monitor_mode = 1;
662
663 /* vector catch reg is not initialized on reset */
664 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
665
666 /* clear monitor mode, enable comparators */
667 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
668 jtag_execute_queue();
669 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
670 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
671 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
672
673 return ERROR_OK;
674 }
675
676 struct target_type feroceon_target =
677 {
678 .name = "feroceon",
679
680 .poll = arm7_9_poll,
681 .arch_state = arm926ejs_arch_state,
682
683 .target_request_data = arm7_9_target_request_data,
684
685 .halt = arm7_9_halt,
686 .resume = arm7_9_resume,
687 .step = arm7_9_step,
688
689 .assert_reset = feroceon_assert_reset,
690 .deassert_reset = arm7_9_deassert_reset,
691 .soft_reset_halt = arm926ejs_soft_reset_halt,
692
693 .get_gdb_reg_list = arm_get_gdb_reg_list,
694
695 .read_memory = arm7_9_read_memory,
696 .write_memory = arm926ejs_write_memory,
697 .bulk_write_memory = feroceon_bulk_write_memory,
698
699 .checksum_memory = arm_checksum_memory,
700 .blank_check_memory = arm_blank_check_memory,
701
702 .run_algorithm = armv4_5_run_algorithm,
703
704 .add_breakpoint = arm7_9_add_breakpoint,
705 .remove_breakpoint = arm7_9_remove_breakpoint,
706 .add_watchpoint = arm7_9_add_watchpoint,
707 .remove_watchpoint = arm7_9_remove_watchpoint,
708
709 .commands = arm926ejs_command_handlers,
710 .target_create = feroceon_target_create,
711 .init_target = feroceon_init_target,
712 .examine = feroceon_examine,
713 };
714
715 struct target_type dragonite_target =
716 {
717 .name = "dragonite",
718
719 .poll = arm7_9_poll,
720 .arch_state = arm_arch_state,
721
722 .target_request_data = arm7_9_target_request_data,
723
724 .halt = arm7_9_halt,
725 .resume = arm7_9_resume,
726 .step = arm7_9_step,
727
728 .assert_reset = feroceon_assert_reset,
729 .deassert_reset = arm7_9_deassert_reset,
730 .soft_reset_halt = arm7_9_soft_reset_halt,
731
732 .get_gdb_reg_list = arm_get_gdb_reg_list,
733
734 .read_memory = arm7_9_read_memory,
735 .write_memory = arm7_9_write_memory,
736 .bulk_write_memory = feroceon_bulk_write_memory,
737
738 .checksum_memory = arm_checksum_memory,
739 .blank_check_memory = arm_blank_check_memory,
740
741 .run_algorithm = armv4_5_run_algorithm,
742
743 .add_breakpoint = arm7_9_add_breakpoint,
744 .remove_breakpoint = arm7_9_remove_breakpoint,
745 .add_watchpoint = arm7_9_add_watchpoint,
746 .remove_watchpoint = arm7_9_remove_watchpoint,
747
748 .commands = arm966e_command_handlers,
749 .target_create = dragonite_target_create,
750 .init_target = feroceon_init_target,
751 .examine = feroceon_examine,
752 };
753

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)