- add support for Marvell Feroceon (thanks to Nicolas Pitre for this patch)
[openocd.git] / src / target / feroceon.c
1 /*
2 * Marvell Feroceon (88F5182, 88F5281) support.
3 *
4 * Copyright (C) 2008 Marvell Semiconductors, Inc.
5 * Written by Nicolas Pitre <nico@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the
19 * Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
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
58 int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
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();
62
63 target_type_t feroceon_target =
64 {
65 .name = "feroceon",
66
67 .poll = arm7_9_poll,
68 .arch_state = arm926ejs_arch_state,
69
70 .target_request_data = arm7_9_target_request_data,
71
72 .halt = arm7_9_halt,
73 .resume = arm7_9_resume,
74 .step = arm7_9_step,
75
76 .assert_reset = arm7_9_assert_reset,
77 .deassert_reset = arm7_9_deassert_reset,
78 .soft_reset_halt = arm926ejs_soft_reset_halt,
79 .prepare_reset_halt = arm7_9_prepare_reset_halt,
80
81 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
82
83 .read_memory = arm7_9_read_memory,
84 .write_memory = arm926ejs_write_memory,
85 .bulk_write_memory = feroceon_bulk_write_memory,
86 .checksum_memory = arm7_9_checksum_memory,
87
88 .run_algorithm = armv4_5_run_algorithm,
89
90 .add_breakpoint = arm7_9_add_breakpoint,
91 .remove_breakpoint = arm7_9_remove_breakpoint,
92 .add_watchpoint = arm7_9_add_watchpoint,
93 .remove_watchpoint = arm7_9_remove_watchpoint,
94
95 .register_commands = arm926ejs_register_commands,
96 .target_command = feroceon_target_command,
97 .init_target = feroceon_init_target,
98 .quit = feroceon_quit
99 };
100
101
102 void feroceon_change_to_arm(target_t *target, u32 *r0, u32 *pc)
103 {
104 armv4_5_common_t *armv4_5 = target->arch_info;
105 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
106 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
107
108 /*
109 * save r0 before using it and put system in ARM state
110 * to allow common handling of ARM and THUMB debugging
111 */
112
113 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
114 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
115 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
116 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
117 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
118 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
119 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
120 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
121 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
122
123 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
124 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
125 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
126 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
127 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
128 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
129 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
130
131 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 0);
132 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
136
137 jtag_execute_queue();
138
139 /*
140 * fix program counter:
141 * MOV R0, PC was the 10th instruction (+18)
142 * reading PC in Thumb state gives address of instruction + 4
143 */
144 *pc -= 22;
145 }
146
147 void feroceon_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
148 {
149 int i;
150 armv4_5_common_t *armv4_5 = target->arch_info;
151 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
152 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
153
154 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
155 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
156 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
157
158 for (i = 0; i <= 15; i++)
159 if (mask & (1 << i))
160 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
161
162 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
163 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
164 }
165
166 void feroceon_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
167 {
168 int i;
169 armv4_5_common_t *armv4_5 = target->arch_info;
170 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
171 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
172 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
173 u32 *buf_u32 = buffer;
174 u16 *buf_u16 = buffer;
175 u8 *buf_u8 = buffer;
176
177 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
178 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
179 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
180
181 for (i = 0; i <= 15; i++)
182 {
183 if (mask & (1 << i)) {
184 switch (size)
185 {
186 case 4:
187 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
188 break;
189 case 2:
190 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
191 break;
192 case 1:
193 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
194 break;
195 }
196 }
197 }
198
199 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
200 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
201 }
202
203 void feroceon_read_xpsr(target_t *target, u32 *xpsr, int spsr)
204 {
205 armv4_5_common_t *armv4_5 = target->arch_info;
206 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
207 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
208
209 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
210 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
211 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
215 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
216
217 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
218 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
219 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
220 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
221
222 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
223 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
224 }
225
226 void feroceon_write_xpsr(target_t *target, u32 xpsr, int spsr)
227 {
228 armv4_5_common_t *armv4_5 = target->arch_info;
229 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
230 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
231
232 DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
233
234 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
238 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
239 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
240 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
241
242 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
243 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
244 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
245 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
246 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
251 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
252 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
253 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
254 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
255 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
256 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
257
258 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
259 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
260 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
261 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
262 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
263 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
264 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
265 }
266
267 void feroceon_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
268 {
269 armv4_5_common_t *armv4_5 = target->arch_info;
270 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
271 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
272
273 DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
274
275 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
276 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
277 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
278 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
279 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
280 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
281 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
282 }
283
284 void feroceon_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
285 {
286 int i;
287 armv4_5_common_t *armv4_5 = target->arch_info;
288 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
289 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
290
291 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 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
295 for (i = 0; i <= 15; i++)
296 if (mask & (1 << i))
297 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
298
299 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
300 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
301 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
302 }
303
304 void feroceon_branch_resume(target_t *target)
305 {
306 armv4_5_common_t *armv4_5 = target->arch_info;
307 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
308 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
309
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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
313 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
314 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
315
316 /* need BYPASS before RESTART */
317 jtag_add_end_state(TAP_RTI);
318 arm_jtag_set_instr(jtag_info, 0xf, NULL);
319 }
320
321 void feroceon_branch_resume_thumb(target_t *target)
322 {
323 DEBUG("-");
324
325 armv4_5_common_t *armv4_5 = target->arch_info;
326 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
327 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
328 u32 r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
329 u32 pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
330
331 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 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, pc & ~3, 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
338
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
344 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); /* add r0,r15,#1 */
345 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 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
349 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 1), 0, NULL, 0);
350 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
351 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
352 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, 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 pc = (pc & 2) >> 1;
357 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
358 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
359
360 /* need BYPASS before RESTART */
361 jtag_add_end_state(TAP_RTI);
362 arm_jtag_set_instr(jtag_info, 0xf, NULL);
363 }
364
365 void feroceon_enable_single_step(target_t *target)
366 {
367 armv4_5_common_t *armv4_5 = target->arch_info;
368 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
369 u32 next_pc;
370
371 /* calculate PC of next instruction */
372 if (arm_simulate_step(target, &next_pc) != ERROR_OK)
373 {
374 u32 current_pc, current_opcode;
375 current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
376 target_read_u32(target, current_pc, &current_opcode);
377 ERROR("BUG: couldn't calculate PC of next instruction, "
378 "current opcode is 0x%8.8x", current_opcode);
379 next_pc = current_pc;
380 }
381 arm7_9_restore_context(target);
382
383 /* set a breakpoint there */
384 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
385 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
386 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
387 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
388 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
389 }
390
391 void feroceon_disable_single_step(target_t *target)
392 {
393 armv4_5_common_t *armv4_5 = target->arch_info;
394 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
395
396 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
397 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
398 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
399 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
400 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
401 }
402
403
404 int feroceon_examine_debug_reason(target_t *target)
405 {
406 /* the MOE is not implemented */
407 if (target->debug_reason != DBG_REASON_SINGLESTEP)
408 {
409 target->debug_reason = DBG_REASON_DBGRQ;
410 }
411
412 return ERROR_OK;
413 }
414
415 int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
416 {
417 armv4_5_common_t *armv4_5 = target->arch_info;
418 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
419 enum armv4_5_state core_state = armv4_5->core_state;
420 u32 x, flip, shift, save[7];
421 int i;
422
423 /*
424 * We can't use the dcc flow control bits, so let's transfer data
425 * with 31 bits and flip the MSB each time a new data word is sent.
426 */
427 static u32 dcc_code[] =
428 {
429 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
430 0xe3a0301e, /* 1: mov r3, #30 */
431 0xe3a04002, /* mov r4, #2 */
432 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
433 0xe1310005, /* teq r1, r5 */
434 0x0afffffc, /* beq 1b */
435 0xe1a05001, /* mov r5, r1 */
436 0xe1a01081, /* mov r1, r1, lsl #1 */
437 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
438 0xe1320005, /* teq r2, r5 */
439 0x0afffffc, /* beq 3b */
440 0xe1a05002, /* mov r5, r2 */
441 0xe3c22102, /* bic r2, r2, #0x80000000 */
442 0xe1811332, /* orr r1, r1, r2, lsr r3 */
443 0xe2533001, /* subs r3, r3, #1 */
444 0xe4801004, /* str r1, [r0], #4 */
445 0xe1a01412, /* mov r1, r2, lsl r4 */
446 0xe2844001, /* add r4, r4, #1 */
447 0x4affffed, /* bmi 1b */
448 0xeafffff3, /* b 3b */
449 };
450
451 int dcc_size = sizeof(dcc_code);
452
453 if (!arm7_9->dcc_downloads)
454 return target->type->write_memory(target, address, 4, count, buffer);
455
456 /* regrab previously allocated working_area, or allocate a new one */
457 if (!arm7_9->dcc_working_area)
458 {
459 u8 dcc_code_buf[dcc_size];
460
461 /* make sure we have a working area */
462 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
463 {
464 INFO("no working area available, falling back to memory writes");
465 return target->type->write_memory(target, address, 4, count, buffer);
466 }
467
468 /* copy target instructions to target endianness */
469 for (i = 0; i < dcc_size/4; i++)
470 target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
471
472 /* write DCC code to working area */
473 target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size, dcc_code_buf);
474 }
475
476 /* backup clobbered processor state */
477 for (i = 0; i <= 5; i++)
478 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32);
479 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
480
481 /* set up target address in r0 */
482 buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
483 armv4_5->core_cache->reg_list[0].valid = 1;
484 armv4_5->core_cache->reg_list[0].dirty = 1;
485 armv4_5->core_state = ARMV4_5_STATE_ARM;
486
487 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
488 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
489
490 /* send data over */
491 x = 0;
492 flip = 0;
493 shift = 1;
494 for (i = 0; i < count; i++)
495 {
496 u32 y = target_buffer_get_u32(target, buffer);
497 u32 z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
498 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
499 x = y << (32 - shift);
500 if (++shift >= 32 || i + 1 >= count)
501 {
502 z = (x >> 1) | (flip ^= 0x80000000);
503 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
504 x = 0;
505 shift = 1;
506 }
507 buffer += 4;
508 }
509
510 target->type->halt(target);
511 while (target->state != TARGET_HALTED)
512 target->type->poll(target);
513
514 /* restore target state */
515 for (i = 0; i <= 5; i++)
516 {
517 buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, save[i]);
518 armv4_5->core_cache->reg_list[i].valid = 1;
519 armv4_5->core_cache->reg_list[i].dirty = 1;
520 }
521 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, save[i]);
522 armv4_5->core_cache->reg_list[15].valid = 1;
523 armv4_5->core_cache->reg_list[15].dirty = 1;
524 armv4_5->core_state = core_state;
525
526 return ERROR_OK;
527 }
528
529 int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
530 {
531 armv4_5_common_t *armv4_5;
532 arm7_9_common_t *arm7_9;
533
534 arm9tdmi_init_target(cmd_ctx, target);
535
536 armv4_5 = target->arch_info;
537 arm7_9 = armv4_5->arch_info;
538
539 /* the COMMS_CTRL bits are all contiguous */
540 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
541 ERROR("unexpected Feroceon EICE version signature");
542
543 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
544 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
545 arm7_9->has_monitor_mode = 1;
546
547 /* vector catch reg is not initialized on reset */
548 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
549
550 /* clear monitor mode, enable comparators */
551 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
552 jtag_execute_queue();
553 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
554 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
555 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
556
557 return ERROR_OK;
558 }
559
560 int feroceon_quit()
561 {
562 return ERROR_OK;
563 }
564
565 int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
566 {
567 int chain_pos;
568 char *variant = NULL;
569 armv4_5_common_t *armv4_5;
570 arm7_9_common_t *arm7_9;
571 arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));
572
573 if (argc < 4)
574 {
575 ERROR("'target arm926ejs' requires at least one additional argument");
576 exit(-1);
577 }
578
579 chain_pos = strtoul(args[3], NULL, 0);
580
581 if (argc >= 5)
582 variant = args[4];
583
584 DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
585
586 arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);
587
588 armv4_5 = target->arch_info;
589 arm7_9 = armv4_5->arch_info;
590
591 /* override some insn sequence functions */
592 arm7_9->change_to_arm = feroceon_change_to_arm;
593 arm7_9->read_core_regs = feroceon_read_core_regs;
594 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
595 arm7_9->read_xpsr = feroceon_read_xpsr;
596 arm7_9->write_xpsr = feroceon_write_xpsr;
597 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
598 arm7_9->write_core_regs = feroceon_write_core_regs;
599 arm7_9->branch_resume = feroceon_branch_resume;
600 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
601
602 /* must be implemented with only one comparator */
603 arm7_9->enable_single_step = feroceon_enable_single_step;
604 arm7_9->disable_single_step = feroceon_disable_single_step;
605
606 /* MOE is not implemented */
607 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
608
609 /* asserting DBGRQ won't win over the undef exception */
610 arm7_9->use_dbgrq = 0;
611
612 /* only one working comparator */
613 arm7_9->wp_available = 1;
614 arm7_9->wp1_used = -1;
615
616 return ERROR_OK;
617 }

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)