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

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)