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

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)