- moved flash erase_check target code to target.c
[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 command_context_s *cmd_ctx, struct target_s *target);
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
80 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
81
82 .read_memory = arm7_9_read_memory,
83 .write_memory = arm926ejs_write_memory,
84 .bulk_write_memory = feroceon_bulk_write_memory,
85 .checksum_memory = arm7_9_checksum_memory,
86 .blank_check_memory = arm7_9_blank_check_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 .examine = feroceon_examine,
99 .quit = feroceon_quit
100 };
101
102
103 void feroceon_change_to_arm(target_t *target, u32 *r0, u32 *pc)
104 {
105 armv4_5_common_t *armv4_5 = target->arch_info;
106 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
107 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
108
109 /*
110 * save r0 before using it and put system in ARM state
111 * to allow common handling of ARM and THUMB debugging
112 */
113
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_NOP, 0, NULL, 0);
117 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 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, NULL, 0);
120 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
121 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
122 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
123
124 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
125 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 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, NULL, 0);
128 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
129 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
130 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
131
132 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
137
138 jtag_execute_queue();
139
140 /*
141 * fix program counter:
142 * MOV R0, PC was the 10th instruction (+18)
143 * reading PC in Thumb state gives address of instruction + 4
144 */
145 *pc -= 22;
146 }
147
148 void feroceon_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
149 {
150 int i;
151 armv4_5_common_t *armv4_5 = target->arch_info;
152 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
153 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
154
155 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
156 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
157 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
158
159 for (i = 0; i <= 15; i++)
160 if (mask & (1 << i))
161 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
162
163 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
164 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
165 }
166
167 void feroceon_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
168 {
169 int i;
170 armv4_5_common_t *armv4_5 = target->arch_info;
171 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
172 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
173 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
174 u32 *buf_u32 = buffer;
175 u16 *buf_u16 = buffer;
176 u8 *buf_u8 = buffer;
177
178 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
179 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
180 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
181
182 for (i = 0; i <= 15; i++)
183 {
184 if (mask & (1 << i)) {
185 switch (size)
186 {
187 case 4:
188 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
189 break;
190 case 2:
191 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
192 break;
193 case 1:
194 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
195 break;
196 }
197 }
198 }
199
200 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
201 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
202 }
203
204 void feroceon_read_xpsr(target_t *target, u32 *xpsr, int spsr)
205 {
206 armv4_5_common_t *armv4_5 = target->arch_info;
207 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
208 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
209
210 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
217
218 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 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, NULL, 0);
221 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
222
223 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
224 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
225 }
226
227 void feroceon_write_xpsr(target_t *target, u32 xpsr, int spsr)
228 {
229 armv4_5_common_t *armv4_5 = target->arch_info;
230 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
231 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
232
233 LOG_DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
234
235 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
242
243 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
250
251 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
258
259 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
266 }
267
268 void feroceon_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
269 {
270 armv4_5_common_t *armv4_5 = target->arch_info;
271 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
272 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
273
274 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
275
276 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
283 }
284
285 void feroceon_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
286 {
287 int i;
288 armv4_5_common_t *armv4_5 = target->arch_info;
289 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
290 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
291
292 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
293 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
294 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
295
296 for (i = 0; i <= 15; i++)
297 if (mask & (1 << i))
298 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
299
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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
303 }
304
305 void feroceon_branch_resume(target_t *target)
306 {
307 armv4_5_common_t *armv4_5 = target->arch_info;
308 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
309 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
310
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_NOP, 0, NULL, 0);
314 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
315 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
316
317 /* need BYPASS before RESTART */
318 jtag_add_end_state(TAP_RTI);
319 arm_jtag_set_instr(jtag_info, 0xf, NULL);
320 }
321
322 void feroceon_branch_resume_thumb(target_t *target)
323 {
324 LOG_DEBUG("-");
325
326 armv4_5_common_t *armv4_5 = target->arch_info;
327 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
328 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
329 u32 r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
330 u32 pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
331
332 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 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, pc & ~3, 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
339
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
345 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); /* add r0,r15,#1 */
346 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 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
350 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 1), 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, 0, NULL, 0);
353 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, NULL, 0);
354 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
355 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
356
357 pc = (pc & 2) >> 1;
358 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
359 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
360
361 /* need BYPASS before RESTART */
362 jtag_add_end_state(TAP_RTI);
363 arm_jtag_set_instr(jtag_info, 0xf, NULL);
364 }
365
366 int feroceon_read_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)
367 {
368 armv4_5_common_t *armv4_5 = target->arch_info;
369 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
370 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
371 int err;
372
373 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
374 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
375 err = arm7_9_execute_sys_speed(target);
376 if (err != ERROR_OK)
377 return err;
378
379 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 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_NOP, 0, value, 0);
383 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
384 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
385 return jtag_execute_queue();
386 }
387
388 int feroceon_write_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)
389 {
390 armv4_5_common_t *armv4_5 = target->arch_info;
391 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
392 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
393
394 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
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, value, NULL, 0);
398 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
399 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
400 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
401
402 arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
403 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
404 return arm7_9_execute_sys_speed(target);
405 }
406
407 void feroceon_enable_single_step(target_t *target)
408 {
409 armv4_5_common_t *armv4_5 = target->arch_info;
410 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
411 u32 next_pc;
412
413 /* calculate PC of next instruction */
414 if (arm_simulate_step(target, &next_pc) != ERROR_OK)
415 {
416 u32 current_pc, current_opcode;
417 current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
418 target_read_u32(target, current_pc, &current_opcode);
419 LOG_ERROR("BUG: couldn't calculate PC of next instruction, "
420 "current opcode is 0x%8.8x", current_opcode);
421 next_pc = current_pc;
422 }
423 arm7_9_restore_context(target);
424
425 /* set a breakpoint there */
426 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
427 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
428 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
429 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
430 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
431 }
432
433 void feroceon_disable_single_step(target_t *target)
434 {
435 armv4_5_common_t *armv4_5 = target->arch_info;
436 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
437
438 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
439 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
440 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
441 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
442 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
443 }
444
445 int feroceon_examine_debug_reason(target_t *target)
446 {
447 /* the MOE is not implemented */
448 if (target->debug_reason != DBG_REASON_SINGLESTEP)
449 {
450 target->debug_reason = DBG_REASON_DBGRQ;
451 }
452
453 return ERROR_OK;
454 }
455
456 int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
457 {
458 armv4_5_common_t *armv4_5 = target->arch_info;
459 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
460 enum armv4_5_state core_state = armv4_5->core_state;
461 u32 x, flip, shift, save[7];
462 int i;
463
464 /*
465 * We can't use the dcc flow control bits, so let's transfer data
466 * with 31 bits and flip the MSB each time a new data word is sent.
467 */
468 static u32 dcc_code[] =
469 {
470 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
471 0xe3a0301e, /* 1: mov r3, #30 */
472 0xe3a04002, /* mov r4, #2 */
473 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
474 0xe1310005, /* teq r1, r5 */
475 0x0afffffc, /* beq 1b */
476 0xe1a05001, /* mov r5, r1 */
477 0xe1a01081, /* mov r1, r1, lsl #1 */
478 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
479 0xe1320005, /* teq r2, r5 */
480 0x0afffffc, /* beq 3b */
481 0xe1a05002, /* mov r5, r2 */
482 0xe3c22102, /* bic r2, r2, #0x80000000 */
483 0xe1811332, /* orr r1, r1, r2, lsr r3 */
484 0xe2533001, /* subs r3, r3, #1 */
485 0xe4801004, /* str r1, [r0], #4 */
486 0xe1a01412, /* mov r1, r2, lsl r4 */
487 0xe2844001, /* add r4, r4, #1 */
488 0x4affffed, /* bmi 1b */
489 0xeafffff3, /* b 3b */
490 };
491
492 int dcc_size = sizeof(dcc_code);
493
494 if (!arm7_9->dcc_downloads)
495 return target->type->write_memory(target, address, 4, count, buffer);
496
497 /* regrab previously allocated working_area, or allocate a new one */
498 if (!arm7_9->dcc_working_area)
499 {
500 u8 dcc_code_buf[dcc_size];
501
502 /* make sure we have a working area */
503 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
504 {
505 LOG_INFO("no working area available, falling back to memory writes");
506 return target->type->write_memory(target, address, 4, count, buffer);
507 }
508
509 /* copy target instructions to target endianness */
510 for (i = 0; i < dcc_size/4; i++)
511 target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
512
513 /* write DCC code to working area */
514 target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size, dcc_code_buf);
515 }
516
517 /* backup clobbered processor state */
518 for (i = 0; i <= 5; i++)
519 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32);
520 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
521
522 /* set up target address in r0 */
523 buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
524 armv4_5->core_cache->reg_list[0].valid = 1;
525 armv4_5->core_cache->reg_list[0].dirty = 1;
526 armv4_5->core_state = ARMV4_5_STATE_ARM;
527
528 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
529 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
530
531 /* send data over */
532 x = 0;
533 flip = 0;
534 shift = 1;
535 for (i = 0; i < count; i++)
536 {
537 u32 y = target_buffer_get_u32(target, buffer);
538 u32 z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
539 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
540 x = y << (32 - shift);
541 if (++shift >= 32 || i + 1 >= count)
542 {
543 z = (x >> 1) | (flip ^= 0x80000000);
544 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
545 x = 0;
546 shift = 1;
547 }
548 buffer += 4;
549 }
550
551 target_halt(target);
552 while (target->state != TARGET_HALTED)
553 target_poll(target);
554
555 /* restore target state */
556 for (i = 0; i <= 5; i++)
557 {
558 buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, save[i]);
559 armv4_5->core_cache->reg_list[i].valid = 1;
560 armv4_5->core_cache->reg_list[i].dirty = 1;
561 }
562 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, save[i]);
563 armv4_5->core_cache->reg_list[15].valid = 1;
564 armv4_5->core_cache->reg_list[15].dirty = 1;
565 armv4_5->core_state = core_state;
566
567 return ERROR_OK;
568 }
569
570 int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
571 {
572 arm9tdmi_init_target(cmd_ctx, target);
573 return ERROR_OK;
574 }
575
576 int feroceon_quit()
577 {
578 return ERROR_OK;
579 }
580
581 int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
582 {
583 int chain_pos;
584 char *variant = NULL;
585 armv4_5_common_t *armv4_5;
586 arm7_9_common_t *arm7_9;
587 arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));
588 memset(arm926ejs, 0, sizeof(*arm926ejs));
589
590 if (argc < 4)
591 {
592 LOG_ERROR("'target arm926ejs' requires at least one additional argument");
593 exit(-1);
594 }
595
596 chain_pos = strtoul(args[3], NULL, 0);
597
598 if (argc >= 5)
599 variant = args[4];
600
601 LOG_DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
602
603 arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);
604
605 armv4_5 = target->arch_info;
606 arm7_9 = armv4_5->arch_info;
607
608 /* override some insn sequence functions */
609 arm7_9->change_to_arm = feroceon_change_to_arm;
610 arm7_9->read_core_regs = feroceon_read_core_regs;
611 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
612 arm7_9->read_xpsr = feroceon_read_xpsr;
613 arm7_9->write_xpsr = feroceon_write_xpsr;
614 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
615 arm7_9->write_core_regs = feroceon_write_core_regs;
616 arm7_9->branch_resume = feroceon_branch_resume;
617 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
618
619 /* must be implemented with only one comparator */
620 arm7_9->enable_single_step = feroceon_enable_single_step;
621 arm7_9->disable_single_step = feroceon_disable_single_step;
622
623 /* MOE is not implemented */
624 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
625
626 /* the standard ARM926 methods don't always work (don't ask...) */
627 arm926ejs->read_cp15 = feroceon_read_cp15;
628 arm926ejs->write_cp15 = feroceon_write_cp15;
629
630 /* asserting DBGRQ won't win over the undef exception */
631 arm7_9->use_dbgrq = 0;
632
633 /* only one working comparator */
634 arm7_9->wp_available = 1;
635 arm7_9->wp1_used = -1;
636
637 return ERROR_OK;
638 }
639
640
641 int feroceon_examine(struct command_context_s *cmd_ctx, struct target_s *target)
642 {
643 armv4_5_common_t *armv4_5;
644 arm7_9_common_t *arm7_9;
645 int retval;
646
647 retval = arm9tdmi_examine(cmd_ctx, target);
648 if (retval!=ERROR_OK)
649 return retval;
650
651 armv4_5 = target->arch_info;
652 arm7_9 = armv4_5->arch_info;
653
654 /* the COMMS_CTRL bits are all contiguous */
655 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
656 LOG_ERROR("unexpected Feroceon EICE version signature");
657
658 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
659 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
660 arm7_9->has_monitor_mode = 1;
661
662 /* vector catch reg is not initialized on reset */
663 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
664
665 /* clear monitor mode, enable comparators */
666 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
667 jtag_execute_queue();
668 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
669 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
670 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
671
672 return ERROR_OK;
673 }

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)