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

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)