- added myself to copyright on files i remember adding large contributions for over...
[openocd.git] / src / target / feroceon.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 /*
22 * Marvell Feroceon (88F5182, 88F5281) support.
23 *
24 * The Feroceon core mimics the ARM926 ICE interface with the following
25 * differences:
26 *
27 * - the MOE (method of entry) reporting is not implemented
28 *
29 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
30 *
31 * - due to a different pipeline implementation, some injected debug
32 * instruction sequences have to be somewhat different
33 *
34 * Other issues:
35 *
36 * - asserting DBGRQ doesn't work if target is looping on the undef vector
37 *
38 * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
39 * not at the top, and rather meaningless due to existing discrepencies
40 *
41 * - the DCC channel is half duplex (only one FIFO for both directions) with
42 * seemingly no proper flow control.
43 */
44
45 #ifdef HAVE_CONFIG_H
46 #include "config.h"
47 #endif
48
49 #include "arm926ejs.h"
50 #include "jtag.h"
51 #include "log.h"
52 #include "arm_simulator.h"
53
54 #include <stdlib.h>
55 #include <string.h>
56
57 int feroceon_examine(struct target_s *target);
58 int feroceon_target_create(struct target_s *target, Jim_Interp *interp);
59 int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
60 int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
61 int feroceon_quit(void);
62
63 int feroceon_assert_reset(target_t *target)
64 {
65 armv4_5_common_t *armv4_5 = target->arch_info;
66 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
67 int ud = arm7_9->use_dbgrq;
68
69 arm7_9->use_dbgrq = 0;
70 if (target->reset_halt)
71 arm7_9_halt(target);
72 arm7_9->use_dbgrq = ud;
73 return arm7_9_assert_reset(target);
74 }
75
76 target_type_t feroceon_target =
77 {
78 .name = "feroceon",
79
80 .poll = arm7_9_poll,
81 .arch_state = arm926ejs_arch_state,
82
83 .target_request_data = arm7_9_target_request_data,
84
85 .halt = arm7_9_halt,
86 .resume = arm7_9_resume,
87 .step = arm7_9_step,
88
89 .assert_reset = feroceon_assert_reset,
90 .deassert_reset = arm7_9_deassert_reset,
91 .soft_reset_halt = arm926ejs_soft_reset_halt,
92
93 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
94
95 .read_memory = arm7_9_read_memory,
96 .write_memory = arm926ejs_write_memory,
97 .bulk_write_memory = feroceon_bulk_write_memory,
98 .checksum_memory = arm7_9_checksum_memory,
99 .blank_check_memory = arm7_9_blank_check_memory,
100
101 .run_algorithm = armv4_5_run_algorithm,
102
103 .add_breakpoint = arm7_9_add_breakpoint,
104 .remove_breakpoint = arm7_9_remove_breakpoint,
105 .add_watchpoint = arm7_9_add_watchpoint,
106 .remove_watchpoint = arm7_9_remove_watchpoint,
107
108 .register_commands = arm926ejs_register_commands,
109 .target_create = feroceon_target_create,
110 .init_target = feroceon_init_target,
111 .examine = feroceon_examine,
112 .quit = feroceon_quit
113 };
114
115
116 int feroceon_dummy_clock_out(arm_jtag_t *jtag_info, u32 instr)
117 {
118 scan_field_t fields[3];
119 u8 out_buf[4];
120 u8 instr_buf[4];
121 u8 sysspeed_buf = 0x0;
122
123 /* prepare buffer */
124 buf_set_u32(out_buf, 0, 32, 0);
125
126 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
127
128 jtag_add_end_state(TAP_PD);
129 arm_jtag_scann(jtag_info, 0x1);
130
131 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
132
133 fields[0].device = jtag_info->chain_pos;
134 fields[0].num_bits = 32;
135 fields[0].out_value = out_buf;
136 fields[0].out_mask = NULL;
137 fields[0].in_value = NULL;
138 fields[0].in_handler = NULL;
139 fields[0].in_handler_priv = NULL;
140 fields[0].in_check_value = NULL;
141 fields[0].in_check_mask = NULL;
142
143 fields[1].device = jtag_info->chain_pos;
144 fields[1].num_bits = 3;
145 fields[1].out_value = &sysspeed_buf;
146 fields[1].out_mask = NULL;
147 fields[1].in_value = NULL;
148 fields[1].in_check_value = NULL;
149 fields[1].in_check_mask = NULL;
150 fields[1].in_handler = NULL;
151 fields[1].in_handler_priv = NULL;
152
153 fields[2].device = jtag_info->chain_pos;
154 fields[2].num_bits = 32;
155 fields[2].out_value = instr_buf;
156 fields[2].out_mask = NULL;
157 fields[2].in_value = NULL;
158 fields[2].in_check_value = NULL;
159 fields[2].in_check_mask = NULL;
160 fields[2].in_handler = NULL;
161 fields[2].in_handler_priv = NULL;
162
163 jtag_add_dr_scan(3, fields, -1);
164
165 /* no jtag_add_runtest(0, -1) here */
166
167 return ERROR_OK;
168 }
169
170 void feroceon_change_to_arm(target_t *target, u32 *r0, u32 *pc)
171 {
172 armv4_5_common_t *armv4_5 = target->arch_info;
173 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
174 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
175
176 /*
177 * save r0 before using it and put system in ARM state
178 * to allow common handling of ARM and THUMB debugging
179 */
180
181 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
182 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
183 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
184
185 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
186 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
187 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
188 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
189 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
190 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
191
192 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
193 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
194 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
195 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
196 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
197 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
198 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
199
200 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 0);
201 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
202 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
203 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
204 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
205
206 jtag_execute_queue();
207
208 /*
209 * fix program counter:
210 * MOV R0, PC was the 7th instruction (+12)
211 * reading PC in Thumb state gives address of instruction + 4
212 */
213 *pc -= (12 + 4);
214 }
215
216 void feroceon_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
217 {
218 int i;
219 armv4_5_common_t *armv4_5 = target->arch_info;
220 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
221 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
222
223 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 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
227 for (i = 0; i <= 15; i++)
228 if (mask & (1 << i))
229 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
230
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
235 void feroceon_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
236 {
237 int i;
238 armv4_5_common_t *armv4_5 = target->arch_info;
239 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
240 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
241 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
242 u32 *buf_u32 = buffer;
243 u16 *buf_u16 = buffer;
244 u8 *buf_u8 = buffer;
245
246 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
247 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
248 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
249
250 for (i = 0; i <= 15; i++)
251 {
252 if (mask & (1 << i)) {
253 switch (size)
254 {
255 case 4:
256 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
257 break;
258 case 2:
259 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
260 break;
261 case 1:
262 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
263 break;
264 }
265 }
266 }
267
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
272 void feroceon_read_xpsr(target_t *target, u32 *xpsr, int spsr)
273 {
274 armv4_5_common_t *armv4_5 = target->arch_info;
275 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
276 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
277
278 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
283 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
284 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
285
286 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
287 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
288 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
289 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
290
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 }
294
295 void feroceon_write_xpsr(target_t *target, u32 xpsr, int spsr)
296 {
297 armv4_5_common_t *armv4_5 = target->arch_info;
298 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
299 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
300
301 LOG_DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
302
303 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
304 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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 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
311 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
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
319 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
320 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
321 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
322 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
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
327 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 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_NOP, 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 }
335
336 void feroceon_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
337 {
338 armv4_5_common_t *armv4_5 = target->arch_info;
339 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
340 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
341
342 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
343
344 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
345 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
346 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
347 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 }
352
353 void feroceon_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
354 {
355 int i;
356 armv4_5_common_t *armv4_5 = target->arch_info;
357 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
358 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
359
360 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
361 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
362 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
363
364 for (i = 0; i <= 15; i++)
365 if (mask & (1 << i))
366 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
367
368 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
369 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
370 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
371 }
372
373 void feroceon_branch_resume(target_t *target)
374 {
375 armv4_5_common_t *armv4_5 = target->arch_info;
376 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
377 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
378
379 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
380 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
381 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
382 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
383 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
384
385 arm7_9->need_bypass_before_restart = 1;
386 }
387
388 void feroceon_branch_resume_thumb(target_t *target)
389 {
390 LOG_DEBUG("-");
391
392 armv4_5_common_t *armv4_5 = target->arch_info;
393 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
394 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
395 u32 r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
396 u32 pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
397 (void)(r0); // use R0...
398
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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
403
404 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); // add r0,pc,#1
405 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 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_T_LDMIA(0, 0x1), 0, NULL, 0);
410 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
411 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
412
413 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, pc, NULL, 0);
414 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
415 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
416
417 pc = (pc & 2) >> 1;
418 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
419 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
420
421 arm7_9->need_bypass_before_restart = 1;
422 }
423
424 int feroceon_read_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)
425 {
426 armv4_5_common_t *armv4_5 = target->arch_info;
427 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
428 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
429 int err;
430
431 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
432 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
433 err = arm7_9_execute_sys_speed(target);
434 if (err != ERROR_OK)
435 return err;
436
437 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
438 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
439 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
440 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0);
441 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
442 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
443 return jtag_execute_queue();
444 }
445
446 int feroceon_write_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)
447 {
448 armv4_5_common_t *armv4_5 = target->arch_info;
449 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
450 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
451
452 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
453 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
454 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
455 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0);
456 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
457 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
458 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
459
460 arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
461 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
462 return arm7_9_execute_sys_speed(target);
463 }
464
465 void feroceon_set_dbgrq(target_t *target)
466 {
467 armv4_5_common_t *armv4_5 = target->arch_info;
468 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
469 reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
470
471 buf_set_u32(dbg_ctrl->value, 0, 8, 2);
472 embeddedice_store_reg(dbg_ctrl);
473 }
474
475 void feroceon_enable_single_step(target_t *target)
476 {
477 armv4_5_common_t *armv4_5 = target->arch_info;
478 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
479 u32 next_pc;
480
481 /* calculate PC of next instruction */
482 if (arm_simulate_step(target, &next_pc) != ERROR_OK)
483 {
484 u32 current_pc, current_opcode;
485 current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
486 target_read_u32(target, current_pc, &current_opcode);
487 LOG_ERROR("BUG: couldn't calculate PC of next instruction, "
488 "current opcode is 0x%8.8x", current_opcode);
489 next_pc = current_pc;
490 }
491 arm7_9_restore_context(target);
492
493 /* set a breakpoint there */
494 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
495 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
496 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
497 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
498 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
499 }
500
501 void feroceon_disable_single_step(target_t *target)
502 {
503 armv4_5_common_t *armv4_5 = target->arch_info;
504 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
505
506 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
507 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
508 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
509 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
510 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
511 }
512
513 int feroceon_examine_debug_reason(target_t *target)
514 {
515 /* the MOE is not implemented */
516 if (target->debug_reason != DBG_REASON_SINGLESTEP)
517 {
518 target->debug_reason = DBG_REASON_DBGRQ;
519 }
520
521 return ERROR_OK;
522 }
523
524 int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
525 {
526 armv4_5_common_t *armv4_5 = target->arch_info;
527 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
528 enum armv4_5_state core_state = armv4_5->core_state;
529 u32 x, flip, shift, save[7];
530 int i;
531
532 /*
533 * We can't use the dcc flow control bits, so let's transfer data
534 * with 31 bits and flip the MSB each time a new data word is sent.
535 */
536 static u32 dcc_code[] =
537 {
538 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
539 0xe3a0301e, /* 1: mov r3, #30 */
540 0xe3a04002, /* mov r4, #2 */
541 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
542 0xe1310005, /* teq r1, r5 */
543 0x0afffffc, /* beq 1b */
544 0xe1a05001, /* mov r5, r1 */
545 0xe1a01081, /* mov r1, r1, lsl #1 */
546 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
547 0xe1320005, /* teq r2, r5 */
548 0x0afffffc, /* beq 3b */
549 0xe1a05002, /* mov r5, r2 */
550 0xe3c22102, /* bic r2, r2, #0x80000000 */
551 0xe1811332, /* orr r1, r1, r2, lsr r3 */
552 0xe2533001, /* subs r3, r3, #1 */
553 0xe4801004, /* str r1, [r0], #4 */
554 0xe1a01412, /* mov r1, r2, lsl r4 */
555 0xe2844001, /* add r4, r4, #1 */
556 0x4affffed, /* bmi 1b */
557 0xeafffff3, /* b 3b */
558 };
559
560 int dcc_size = sizeof(dcc_code);
561
562 if (!arm7_9->dcc_downloads)
563 return target->type->write_memory(target, address, 4, count, buffer);
564
565 /* regrab previously allocated working_area, or allocate a new one */
566 if (!arm7_9->dcc_working_area)
567 {
568 u8 dcc_code_buf[dcc_size];
569
570 /* make sure we have a working area */
571 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
572 {
573 LOG_INFO("no working area available, falling back to memory writes");
574 return target->type->write_memory(target, address, 4, count, buffer);
575 }
576
577 /* copy target instructions to target endianness */
578 for (i = 0; i < dcc_size/4; i++)
579 target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
580
581 /* write DCC code to working area */
582 target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size, dcc_code_buf);
583 }
584
585 /* backup clobbered processor state */
586 for (i = 0; i <= 5; i++)
587 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32);
588 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
589
590 /* set up target address in r0 */
591 buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
592 armv4_5->core_cache->reg_list[0].valid = 1;
593 armv4_5->core_cache->reg_list[0].dirty = 1;
594 armv4_5->core_state = ARMV4_5_STATE_ARM;
595
596 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
597 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
598
599 /* send data over */
600 x = 0;
601 flip = 0;
602 shift = 1;
603 for (i = 0; i < count; i++)
604 {
605 u32 y = target_buffer_get_u32(target, buffer);
606 u32 z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
607 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
608 x = y << (32 - shift);
609 if (++shift >= 32 || i + 1 >= count)
610 {
611 z = (x >> 1) | (flip ^= 0x80000000);
612 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
613 x = 0;
614 shift = 1;
615 }
616 buffer += 4;
617 }
618
619 target_halt(target);
620 while (target->state != TARGET_HALTED)
621 target_poll(target);
622
623 /* restore target state */
624 for (i = 0; i <= 5; i++)
625 {
626 buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, save[i]);
627 armv4_5->core_cache->reg_list[i].valid = 1;
628 armv4_5->core_cache->reg_list[i].dirty = 1;
629 }
630 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, save[i]);
631 armv4_5->core_cache->reg_list[15].valid = 1;
632 armv4_5->core_cache->reg_list[15].dirty = 1;
633 armv4_5->core_state = core_state;
634
635 return ERROR_OK;
636 }
637
638 int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
639 {
640 arm9tdmi_init_target(cmd_ctx, target);
641 return ERROR_OK;
642 }
643
644 int feroceon_quit(void)
645 {
646 return ERROR_OK;
647 }
648
649 int feroceon_target_create(struct target_s *target, Jim_Interp *interp)
650 {
651 armv4_5_common_t *armv4_5;
652 arm7_9_common_t *arm7_9;
653 arm926ejs_common_t *arm926ejs = calloc(1,sizeof(arm926ejs_common_t));
654
655 arm926ejs_init_arch_info(target, arm926ejs, target->chain_position, target->variant);
656
657 armv4_5 = target->arch_info;
658 arm7_9 = armv4_5->arch_info;
659
660 /* override some insn sequence functions */
661 arm7_9->change_to_arm = feroceon_change_to_arm;
662 arm7_9->read_core_regs = feroceon_read_core_regs;
663 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
664 arm7_9->read_xpsr = feroceon_read_xpsr;
665 arm7_9->write_xpsr = feroceon_write_xpsr;
666 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
667 arm7_9->write_core_regs = feroceon_write_core_regs;
668 arm7_9->branch_resume = feroceon_branch_resume;
669 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
670
671 /* must be implemented with only one comparator */
672 arm7_9->enable_single_step = feroceon_enable_single_step;
673 arm7_9->disable_single_step = feroceon_disable_single_step;
674
675 /* MOE is not implemented */
676 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
677
678 /* the standard ARM926 methods don't always work (don't ask...) */
679 arm926ejs->read_cp15 = feroceon_read_cp15;
680 arm926ejs->write_cp15 = feroceon_write_cp15;
681
682 /* Note: asserting DBGRQ might not win over the undef exception.
683 If that happens then just use "arm7_9 dbgrq disable". */
684 arm7_9->use_dbgrq = 1;
685 arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
686
687 /* only one working comparator */
688 arm7_9->wp_available_max = 1;
689 arm7_9->wp1_used_default = -1;
690
691 return ERROR_OK;
692 }
693
694
695 int feroceon_examine(struct target_s *target)
696 {
697 armv4_5_common_t *armv4_5;
698 arm7_9_common_t *arm7_9;
699 int retval;
700
701 retval = arm9tdmi_examine(target);
702 if (retval!=ERROR_OK)
703 return retval;
704
705 armv4_5 = target->arch_info;
706 arm7_9 = armv4_5->arch_info;
707
708 /* the COMMS_CTRL bits are all contiguous */
709 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
710 LOG_ERROR("unexpected Feroceon EICE version signature");
711
712 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
713 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
714 arm7_9->has_monitor_mode = 1;
715
716 /* vector catch reg is not initialized on reset */
717 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
718
719 /* clear monitor mode, enable comparators */
720 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
721 jtag_execute_queue();
722 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
723 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
724 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
725
726 return ERROR_OK;
727 }

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)