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

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)