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

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)