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

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)