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

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)