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

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)