1 /***************************************************************************
2 * Copyright (C) 2008 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
5 * Copyright (C) 2008 by Hongtao Zheng *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
25 * Marvell Feroceon support, including Orion and Kirkwood SOCs.
27 * The Feroceon core mimics the ARM926 ICE interface with the following
30 * - the MOE (method of entry) reporting is not implemented
32 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
34 * - due to a different pipeline implementation, some injected debug
35 * instruction sequences have to be somewhat different
39 * - asserting DBGRQ doesn't work if target is looping on the undef vector
41 * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
42 * not at the top, and rather meaningless due to existing discrepencies
44 * - the DCC channel is half duplex (only one FIFO for both directions) with
45 * seemingly no proper flow control.
52 #include "arm926ejs.h"
55 int feroceon_examine(struct target_s
*target
);
56 int feroceon_target_create(struct target_s
*target
, Jim_Interp
*interp
);
57 int feroceon_bulk_write_memory(target_t
*target
, u32 address
, u32 count
, u8
*buffer
);
58 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
);
59 int feroceon_quit(void);
61 int feroceon_assert_reset(target_t
*target
)
63 armv4_5_common_t
*armv4_5
= target
->arch_info
;
64 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
65 int ud
= arm7_9
->use_dbgrq
;
67 arm7_9
->use_dbgrq
= 0;
68 if (target
->reset_halt
)
70 arm7_9
->use_dbgrq
= ud
;
71 return arm7_9_assert_reset(target
);
74 target_type_t feroceon_target
=
79 .arch_state
= arm926ejs_arch_state
,
81 .target_request_data
= arm7_9_target_request_data
,
84 .resume
= arm7_9_resume
,
87 .assert_reset
= feroceon_assert_reset
,
88 .deassert_reset
= arm7_9_deassert_reset
,
89 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
91 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
93 .read_memory
= arm7_9_read_memory
,
94 .write_memory
= arm926ejs_write_memory
,
95 .bulk_write_memory
= feroceon_bulk_write_memory
,
96 .checksum_memory
= arm7_9_checksum_memory
,
97 .blank_check_memory
= arm7_9_blank_check_memory
,
99 .run_algorithm
= armv4_5_run_algorithm
,
101 .add_breakpoint
= arm7_9_add_breakpoint
,
102 .remove_breakpoint
= arm7_9_remove_breakpoint
,
103 .add_watchpoint
= arm7_9_add_watchpoint
,
104 .remove_watchpoint
= arm7_9_remove_watchpoint
,
106 .register_commands
= arm926ejs_register_commands
,
107 .target_create
= feroceon_target_create
,
108 .init_target
= feroceon_init_target
,
109 .examine
= feroceon_examine
,
110 .quit
= feroceon_quit
114 int feroceon_dummy_clock_out(arm_jtag_t
*jtag_info
, u32 instr
)
116 scan_field_t fields
[3];
119 u8 sysspeed_buf
= 0x0;
122 buf_set_u32(out_buf
, 0, 32, 0);
124 buf_set_u32(instr_buf
, 0, 32, flip_u32(instr
, 32));
126 jtag_add_end_state(TAP_DRPAUSE
);
127 arm_jtag_scann(jtag_info
, 0x1);
129 arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
);
131 fields
[0].tap
= jtag_info
->tap
;
132 fields
[0].num_bits
= 32;
133 fields
[0].out_value
= out_buf
;
135 fields
[0].in_value
= NULL
;
141 fields
[1].tap
= jtag_info
->tap
;
142 fields
[1].num_bits
= 3;
143 fields
[1].out_value
= &sysspeed_buf
;
145 fields
[1].in_value
= NULL
;
151 fields
[2].tap
= jtag_info
->tap
;
152 fields
[2].num_bits
= 32;
153 fields
[2].out_value
= instr_buf
;
155 fields
[2].in_value
= NULL
;
161 jtag_add_dr_scan(3, fields
, TAP_INVALID
);
163 /* no jtag_add_runtest(0, TAP_INVALID) here */
168 void feroceon_change_to_arm(target_t
*target
, u32
*r0
, u32
*pc
)
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
;
175 * save r0 before using it and put system in ARM state
176 * to allow common handling of ARM and THUMB debugging
179 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
180 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
181 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
183 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 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, NULL
, 0);
190 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
191 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
192 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
193 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
194 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 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, NULL
, 0);
198 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 0, NULL
, 0);
199 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
200 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 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);
204 jtag_execute_queue();
207 * fix program counter:
208 * MOV R0, PC was the 7th instruction (+12)
209 * reading PC in Thumb state gives address of instruction + 4
214 void feroceon_read_core_regs(target_t
*target
, u32 mask
, u32
* core_regs
[16])
217 armv4_5_common_t
*armv4_5
= target
->arch_info
;
218 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
219 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
221 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
222 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
223 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
225 for (i
= 0; i
<= 15; i
++)
227 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
229 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
230 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
233 void feroceon_read_core_regs_target_buffer(target_t
*target
, u32 mask
, void* buffer
, int size
)
236 armv4_5_common_t
*armv4_5
= target
->arch_info
;
237 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
238 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
239 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
240 u32
*buf_u32
= buffer
;
241 u16
*buf_u16
= buffer
;
244 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 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);
248 for (i
= 0; i
<= 15; i
++)
250 if (mask
& (1 << i
)) {
254 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
257 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
260 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
266 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
267 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
270 void feroceon_read_xpsr(target_t
*target
, u32
*xpsr
, int spsr
)
272 armv4_5_common_t
*armv4_5
= target
->arch_info
;
273 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
274 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
276 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 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);
284 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
285 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
286 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
287 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, xpsr
, 0);
289 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
290 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
293 void feroceon_write_xpsr(target_t
*target
, u32 xpsr
, int spsr
)
295 armv4_5_common_t
*armv4_5
= target
->arch_info
;
296 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
297 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
299 LOG_DEBUG("xpsr: %8.8x, spsr: %i", xpsr
, spsr
);
301 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 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 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);
309 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 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 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);
317 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 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 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);
325 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 0, NULL
, 0);
326 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
327 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
334 void feroceon_write_xpsr_im8(target_t
*target
, u8 xpsr_im
, int rot
, int spsr
)
336 armv4_5_common_t
*armv4_5
= target
->arch_info
;
337 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
338 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
340 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
342 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 0, NULL
, 0);
343 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
344 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
351 void feroceon_write_core_regs(target_t
*target
, u32 mask
, u32 core_regs
[16])
354 armv4_5_common_t
*armv4_5
= target
->arch_info
;
355 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
356 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
358 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
359 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
360 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
362 for (i
= 0; i
<= 15; i
++)
364 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], NULL
, 0);
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);
371 void feroceon_branch_resume(target_t
*target
)
373 armv4_5_common_t
*armv4_5
= target
->arch_info
;
374 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
375 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
377 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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_B(0xfffff9, 0), 0, NULL
, 0);
381 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
383 arm7_9
->need_bypass_before_restart
= 1;
386 void feroceon_branch_resume_thumb(target_t
*target
)
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 u32 r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
394 u32 pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
395 (void)(r0
); // use R0...
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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
400 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
402 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); // add r0,pc,#1
403 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
404 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
405 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
407 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
408 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
409 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
411 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, pc
, NULL
, 0);
412 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
413 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
416 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
417 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
419 arm7_9
->need_bypass_before_restart
= 1;
422 int feroceon_read_cp15(target_t
*target
, u32 op1
, u32 op2
, u32 CRn
, u32 CRm
, u32
*value
)
424 armv4_5_common_t
*armv4_5
= target
->arch_info
;
425 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
426 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
429 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
430 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
431 err
= arm7_9_execute_sys_speed(target
);
435 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
436 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
437 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
438 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 0);
439 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
440 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
441 return jtag_execute_queue();
444 int feroceon_write_cp15(target_t
*target
, u32 op1
, u32 op2
, u32 CRn
, u32 CRm
, u32 value
)
446 armv4_5_common_t
*armv4_5
= target
->arch_info
;
447 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
448 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
450 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 0);
451 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
452 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
453 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, NULL
, 0);
454 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
455 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
456 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
458 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
459 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
460 return arm7_9_execute_sys_speed(target
);
463 void feroceon_set_dbgrq(target_t
*target
)
465 armv4_5_common_t
*armv4_5
= target
->arch_info
;
466 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
467 reg_t
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
469 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
470 embeddedice_store_reg(dbg_ctrl
);
473 void feroceon_enable_single_step(target_t
*target
, u32 next_pc
)
475 armv4_5_common_t
*armv4_5
= target
->arch_info
;
476 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
478 /* set a breakpoint there */
479 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
480 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
481 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
482 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
483 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
486 void feroceon_disable_single_step(target_t
*target
)
488 armv4_5_common_t
*armv4_5
= target
->arch_info
;
489 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
491 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
492 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
493 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
494 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
495 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
498 int feroceon_examine_debug_reason(target_t
*target
)
500 /* the MOE is not implemented */
501 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
503 target
->debug_reason
= DBG_REASON_DBGRQ
;
509 int feroceon_bulk_write_memory(target_t
*target
, u32 address
, u32 count
, u8
*buffer
)
512 armv4_5_common_t
*armv4_5
= target
->arch_info
;
513 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
514 enum armv4_5_state core_state
= armv4_5
->core_state
;
515 u32 x
, flip
, shift
, save
[7];
519 * We can't use the dcc flow control bits, so let's transfer data
520 * with 31 bits and flip the MSB each time a new data word is sent.
522 static u32 dcc_code
[] =
524 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
525 0xe3a0301e, /* 1: mov r3, #30 */
526 0xe3a04002, /* mov r4, #2 */
527 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
528 0xe1310005, /* teq r1, r5 */
529 0x0afffffc, /* beq 1b */
530 0xe1a05001, /* mov r5, r1 */
531 0xe1a01081, /* mov r1, r1, lsl #1 */
532 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
533 0xe1320005, /* teq r2, r5 */
534 0x0afffffc, /* beq 3b */
535 0xe1a05002, /* mov r5, r2 */
536 0xe3c22102, /* bic r2, r2, #0x80000000 */
537 0xe1811332, /* orr r1, r1, r2, lsr r3 */
538 0xe2533001, /* subs r3, r3, #1 */
539 0xe4801004, /* str r1, [r0], #4 */
540 0xe1a01412, /* mov r1, r2, lsl r4 */
541 0xe2844001, /* add r4, r4, #1 */
542 0x4affffed, /* bmi 1b */
543 0xeafffff3, /* b 3b */
546 u32 dcc_size
= sizeof(dcc_code
);
548 if (!arm7_9
->dcc_downloads
)
549 return target
->type
->write_memory(target
, address
, 4, count
, buffer
);
551 /* regrab previously allocated working_area, or allocate a new one */
552 if (!arm7_9
->dcc_working_area
)
554 u8 dcc_code_buf
[dcc_size
];
556 /* make sure we have a working area */
557 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
559 LOG_INFO("no working area available, falling back to memory writes");
560 return target
->type
->write_memory(target
, address
, 4, count
, buffer
);
563 /* copy target instructions to target endianness */
564 for (i
= 0; i
< dcc_size
/4; i
++)
565 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
567 /* write DCC code to working area */
568 if((retval
= target
->type
->write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
574 /* backup clobbered processor state */
575 for (i
= 0; i
<= 5; i
++)
576 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
577 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
579 /* set up target address in r0 */
580 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
581 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
582 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
583 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
585 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
586 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
592 for (i
= 0; i
< count
; i
++)
594 u32 y
= target_buffer_get_u32(target
, buffer
);
595 u32 z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
596 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
597 x
= y
<< (32 - shift
);
598 if (++shift
>= 32 || i
+ 1 >= count
)
600 z
= (x
>> 1) | (flip
^= 0x80000000);
601 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
609 while (target
->state
!= TARGET_HALTED
)
612 /* restore target state */
613 for (i
= 0; i
<= 5; i
++)
615 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
616 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
617 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
619 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
620 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
621 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
622 armv4_5
->core_state
= core_state
;
627 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
)
629 arm9tdmi_init_target(cmd_ctx
, target
);
633 int feroceon_quit(void)
638 int feroceon_target_create(struct target_s
*target
, Jim_Interp
*interp
)
640 armv4_5_common_t
*armv4_5
;
641 arm7_9_common_t
*arm7_9
;
642 arm926ejs_common_t
*arm926ejs
= calloc(1,sizeof(arm926ejs_common_t
));
644 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
646 armv4_5
= target
->arch_info
;
647 arm7_9
= armv4_5
->arch_info
;
649 /* override some insn sequence functions */
650 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
651 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
652 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
653 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
654 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
655 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
656 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
657 arm7_9
->branch_resume
= feroceon_branch_resume
;
658 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
660 /* must be implemented with only one comparator */
661 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
662 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
664 /* MOE is not implemented */
665 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
667 /* the standard ARM926 methods don't always work (don't ask...) */
668 arm926ejs
->read_cp15
= feroceon_read_cp15
;
669 arm926ejs
->write_cp15
= feroceon_write_cp15
;
671 /* Note: asserting DBGRQ might not win over the undef exception.
672 If that happens then just use "arm7_9 dbgrq disable". */
673 arm7_9
->use_dbgrq
= 1;
674 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
676 /* only one working comparator */
677 arm7_9
->wp_available_max
= 1;
678 arm7_9
->wp1_used_default
= -1;
683 int feroceon_examine(struct target_s
*target
)
685 armv4_5_common_t
*armv4_5
;
686 arm7_9_common_t
*arm7_9
;
689 retval
= arm9tdmi_examine(target
);
690 if (retval
!=ERROR_OK
)
693 armv4_5
= target
->arch_info
;
694 arm7_9
= armv4_5
->arch_info
;
696 /* the COMMS_CTRL bits are all contiguous */
697 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
698 LOG_ERROR("unexpected Feroceon EICE version signature");
700 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
701 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
702 arm7_9
->has_monitor_mode
= 1;
704 /* vector catch reg is not initialized on reset */
705 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
707 /* clear monitor mode, enable comparators */
708 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
709 jtag_execute_queue();
710 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
711 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
712 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
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)