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

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)