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