1 /***************************************************************************
2 * Copyright (C) 2008-2009 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/Dragonite support.
27 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
28 * mimics the ARM926 ICE interface with the following differences:
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.
47 * The Dragonite core is the non-mmu version based on the ARM966 model, and
48 * it shares the above issues as well.
55 #include "arm926ejs.h"
57 #include "target_type.h"
60 int feroceon_examine(struct target_s
*target
);
61 int feroceon_target_create(struct target_s
*target
, Jim_Interp
*interp
);
62 int dragonite_target_create(struct target_s
*target
, Jim_Interp
*interp
);
63 int feroceon_bulk_write_memory(target_t
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
);
64 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
);
65 int feroceon_quit(void);
67 int feroceon_assert_reset(target_t
*target
)
69 armv4_5_common_t
*armv4_5
= target
->arch_info
;
70 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
71 int ud
= arm7_9
->use_dbgrq
;
73 arm7_9
->use_dbgrq
= 0;
74 if (target
->reset_halt
)
76 arm7_9
->use_dbgrq
= ud
;
77 return arm7_9_assert_reset(target
);
80 target_type_t feroceon_target
=
85 .arch_state
= arm926ejs_arch_state
,
87 .target_request_data
= arm7_9_target_request_data
,
90 .resume
= arm7_9_resume
,
93 .assert_reset
= feroceon_assert_reset
,
94 .deassert_reset
= arm7_9_deassert_reset
,
95 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
97 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
99 .read_memory
= arm7_9_read_memory
,
100 .write_memory
= arm926ejs_write_memory
,
101 .bulk_write_memory
= feroceon_bulk_write_memory
,
102 .checksum_memory
= arm7_9_checksum_memory
,
103 .blank_check_memory
= arm7_9_blank_check_memory
,
105 .run_algorithm
= armv4_5_run_algorithm
,
107 .add_breakpoint
= arm7_9_add_breakpoint
,
108 .remove_breakpoint
= arm7_9_remove_breakpoint
,
109 .add_watchpoint
= arm7_9_add_watchpoint
,
110 .remove_watchpoint
= arm7_9_remove_watchpoint
,
112 .register_commands
= arm926ejs_register_commands
,
113 .target_create
= feroceon_target_create
,
114 .init_target
= feroceon_init_target
,
115 .examine
= feroceon_examine
,
116 .quit
= feroceon_quit
119 target_type_t dragonite_target
=
124 .arch_state
= armv4_5_arch_state
,
126 .target_request_data
= arm7_9_target_request_data
,
129 .resume
= arm7_9_resume
,
132 .assert_reset
= feroceon_assert_reset
,
133 .deassert_reset
= arm7_9_deassert_reset
,
134 .soft_reset_halt
= arm7_9_soft_reset_halt
,
136 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
138 .read_memory
= arm7_9_read_memory
,
139 .write_memory
= arm7_9_write_memory
,
140 .bulk_write_memory
= feroceon_bulk_write_memory
,
141 .checksum_memory
= arm7_9_checksum_memory
,
142 .blank_check_memory
= arm7_9_blank_check_memory
,
144 .run_algorithm
= armv4_5_run_algorithm
,
146 .add_breakpoint
= arm7_9_add_breakpoint
,
147 .remove_breakpoint
= arm7_9_remove_breakpoint
,
148 .add_watchpoint
= arm7_9_add_watchpoint
,
149 .remove_watchpoint
= arm7_9_remove_watchpoint
,
151 .register_commands
= arm966e_register_commands
,
152 .target_create
= dragonite_target_create
,
153 .init_target
= feroceon_init_target
,
154 .examine
= feroceon_examine
,
155 .quit
= feroceon_quit
158 int feroceon_dummy_clock_out(arm_jtag_t
*jtag_info
, uint32_t instr
)
160 scan_field_t fields
[3];
162 uint8_t instr_buf
[4];
163 uint8_t sysspeed_buf
= 0x0;
166 buf_set_u32(out_buf
, 0, 32, 0);
168 buf_set_u32(instr_buf
, 0, 32, flip_u32(instr
, 32));
170 jtag_set_end_state(TAP_DRPAUSE
);
171 arm_jtag_scann(jtag_info
, 0x1);
173 arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
);
175 fields
[0].tap
= jtag_info
->tap
;
176 fields
[0].num_bits
= 32;
177 fields
[0].out_value
= out_buf
;
178 fields
[0].in_value
= NULL
;
180 fields
[1].tap
= jtag_info
->tap
;
181 fields
[1].num_bits
= 3;
182 fields
[1].out_value
= &sysspeed_buf
;
183 fields
[1].in_value
= NULL
;
185 fields
[2].tap
= jtag_info
->tap
;
186 fields
[2].num_bits
= 32;
187 fields
[2].out_value
= instr_buf
;
188 fields
[2].in_value
= NULL
;
190 jtag_add_dr_scan(3, fields
, jtag_get_end_state());
192 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
197 void feroceon_change_to_arm(target_t
*target
, uint32_t *r0
, uint32_t *pc
)
199 armv4_5_common_t
*armv4_5
= target
->arch_info
;
200 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
201 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
204 * save r0 before using it and put system in ARM state
205 * to allow common handling of ARM and THUMB debugging
208 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
209 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
210 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
212 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
213 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
214 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
215 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
216 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
217 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
219 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
220 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
221 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
222 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
223 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
224 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
225 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
227 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 0, NULL
, 0);
228 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
229 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
230 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
231 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
233 jtag_execute_queue();
236 * fix program counter:
237 * MOV R0, PC was the 7th instruction (+12)
238 * reading PC in Thumb state gives address of instruction + 4
243 void feroceon_read_core_regs(target_t
*target
, uint32_t mask
, uint32_t* core_regs
[16])
246 armv4_5_common_t
*armv4_5
= target
->arch_info
;
247 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
248 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
250 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 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);
254 for (i
= 0; i
<= 15; i
++)
256 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
258 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
259 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
262 void feroceon_read_core_regs_target_buffer(target_t
*target
, uint32_t mask
, void* buffer
, int size
)
265 armv4_5_common_t
*armv4_5
= target
->arch_info
;
266 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
267 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
268 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
269 uint32_t *buf_u32
= buffer
;
270 uint16_t *buf_u16
= buffer
;
271 uint8_t *buf_u8
= buffer
;
273 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 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);
277 for (i
= 0; i
<= 15; i
++)
279 if (mask
& (1 << i
)) {
283 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
286 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
289 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
295 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
296 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
299 void feroceon_read_xpsr(target_t
*target
, uint32_t *xpsr
, int spsr
)
301 armv4_5_common_t
*armv4_5
= target
->arch_info
;
302 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
303 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
305 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
311 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
313 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 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, xpsr
, 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);
322 void feroceon_write_xpsr(target_t
*target
, uint32_t xpsr
, int spsr
)
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
;
328 LOG_DEBUG("xpsr: %8.8" PRIx32
", spsr: %i", xpsr
, spsr
);
330 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 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 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);
338 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
346 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
352 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
354 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 0, NULL
, 0);
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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
363 void feroceon_write_xpsr_im8(target_t
*target
, uint8_t xpsr_im
, int rot
, int spsr
)
365 armv4_5_common_t
*armv4_5
= target
->arch_info
;
366 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
367 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
369 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
371 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 0, NULL
, 0);
372 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
373 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
374 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
375 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
376 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
377 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
380 void feroceon_write_core_regs(target_t
*target
, uint32_t mask
, uint32_t core_regs
[16])
383 armv4_5_common_t
*armv4_5
= target
->arch_info
;
384 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
385 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
387 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 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);
391 for (i
= 0; i
<= 15; i
++)
393 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], NULL
, 0);
395 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
396 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
397 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
400 void feroceon_branch_resume(target_t
*target
)
402 armv4_5_common_t
*armv4_5
= target
->arch_info
;
403 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
404 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
409 arm9tdmi_clock_out(jtag_info
, ARMV4_5_B(0xfffff9, 0), 0, NULL
, 0);
410 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
412 arm7_9
->need_bypass_before_restart
= 1;
415 void feroceon_branch_resume_thumb(target_t
*target
)
419 armv4_5_common_t
*armv4_5
= target
->arch_info
;
420 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
421 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
422 uint32_t r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
423 uint32_t pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
424 (void)(r0
); // use R0...
426 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
427 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 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);
431 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); // add r0,pc,#1
432 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
433 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
434 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
436 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
437 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
438 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
440 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, pc
, NULL
, 0);
441 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
442 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
445 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
446 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
448 arm7_9
->need_bypass_before_restart
= 1;
451 int feroceon_read_cp15(target_t
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
453 armv4_5_common_t
*armv4_5
= target
->arch_info
;
454 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
455 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
458 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
459 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
460 err
= arm7_9_execute_sys_speed(target
);
464 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
465 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
466 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
467 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 0);
468 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
469 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
470 return jtag_execute_queue();
473 int feroceon_write_cp15(target_t
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
475 armv4_5_common_t
*armv4_5
= target
->arch_info
;
476 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
477 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
479 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 0);
480 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
481 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
482 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, NULL
, 0);
483 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
484 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
485 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
487 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
488 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
489 return arm7_9_execute_sys_speed(target
);
492 void feroceon_set_dbgrq(target_t
*target
)
494 armv4_5_common_t
*armv4_5
= target
->arch_info
;
495 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
496 reg_t
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
498 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
499 embeddedice_store_reg(dbg_ctrl
);
502 void feroceon_enable_single_step(target_t
*target
, uint32_t next_pc
)
504 armv4_5_common_t
*armv4_5
= target
->arch_info
;
505 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
507 /* set a breakpoint there */
508 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
509 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
510 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
511 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
512 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
515 void feroceon_disable_single_step(target_t
*target
)
517 armv4_5_common_t
*armv4_5
= target
->arch_info
;
518 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
520 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
521 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
522 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
523 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
524 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
527 int feroceon_examine_debug_reason(target_t
*target
)
529 /* the MOE is not implemented */
530 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
532 target
->debug_reason
= DBG_REASON_DBGRQ
;
538 int feroceon_bulk_write_memory(target_t
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
)
541 armv4_5_common_t
*armv4_5
= target
->arch_info
;
542 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
543 enum armv4_5_state core_state
= armv4_5
->core_state
;
544 uint32_t x
, flip
, shift
, save
[7];
548 * We can't use the dcc flow control bits, so let's transfer data
549 * with 31 bits and flip the MSB each time a new data word is sent.
551 static uint32_t dcc_code
[] =
553 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
554 0xe3a0301e, /* 1: mov r3, #30 */
555 0xe3a04002, /* mov r4, #2 */
556 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
557 0xe1310005, /* teq r1, r5 */
558 0x0afffffc, /* beq 1b */
559 0xe1a05001, /* mov r5, r1 */
560 0xe1a01081, /* mov r1, r1, lsl #1 */
561 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
562 0xe1320005, /* teq r2, r5 */
563 0x0afffffc, /* beq 3b */
564 0xe1a05002, /* mov r5, r2 */
565 0xe3c22102, /* bic r2, r2, #0x80000000 */
566 0xe1811332, /* orr r1, r1, r2, lsr r3 */
567 0xe2533001, /* subs r3, r3, #1 */
568 0xe4801004, /* str r1, [r0], #4 */
569 0xe1a01412, /* mov r1, r2, lsl r4 */
570 0xe2844001, /* add r4, r4, #1 */
571 0x4affffed, /* bmi 1b */
572 0xeafffff3, /* b 3b */
575 uint32_t dcc_size
= sizeof(dcc_code
);
577 if (!arm7_9
->dcc_downloads
)
578 return target_write_memory(target
, address
, 4, count
, buffer
);
580 /* regrab previously allocated working_area, or allocate a new one */
581 if (!arm7_9
->dcc_working_area
)
583 uint8_t dcc_code_buf
[dcc_size
];
585 /* make sure we have a working area */
586 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
588 LOG_INFO("no working area available, falling back to memory writes");
589 return target_write_memory(target
, address
, 4, count
, buffer
);
592 /* copy target instructions to target endianness */
593 for (i
= 0; i
< dcc_size
/4; i
++)
594 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
596 /* write DCC code to working area */
597 if ((retval
= target_write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
603 /* backup clobbered processor state */
604 for (i
= 0; i
<= 5; i
++)
605 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
606 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
608 /* set up target address in r0 */
609 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
610 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
611 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
612 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
614 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
615 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
621 for (i
= 0; i
< count
; i
++)
623 uint32_t y
= target_buffer_get_u32(target
, buffer
);
624 uint32_t z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
625 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
626 x
= y
<< (32 - shift
);
627 if (++shift
>= 32 || i
+ 1 >= count
)
629 z
= (x
>> 1) | (flip
^= 0x80000000);
630 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
637 retval
= target_halt(target
);
638 if (retval
== ERROR_OK
)
639 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
640 if (retval
== ERROR_OK
) {
641 uint32_t endaddress
=
642 buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
643 if (endaddress
!= address
+ count
*4) {
644 LOG_ERROR("DCC write failed,"
645 " expected end address 0x%08" PRIx32
646 " got 0x%0" PRIx32
"",
647 address
+ count
*4, endaddress
);
652 /* restore target state */
653 for (i
= 0; i
<= 5; i
++)
655 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
656 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
657 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
659 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
660 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
661 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
662 armv4_5
->core_state
= core_state
;
667 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
)
669 arm9tdmi_init_target(cmd_ctx
, target
);
673 int feroceon_quit(void)
678 void feroceon_common_setup(struct target_s
*target
)
680 armv4_5_common_t
*armv4_5
= target
->arch_info
;
681 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
683 /* override some insn sequence functions */
684 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
685 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
686 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
687 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
688 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
689 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
690 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
691 arm7_9
->branch_resume
= feroceon_branch_resume
;
692 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
694 /* must be implemented with only one comparator */
695 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
696 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
698 /* MOE is not implemented */
699 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
701 /* Note: asserting DBGRQ might not win over the undef exception.
702 If that happens then just use "arm7_9 dbgrq disable". */
703 arm7_9
->use_dbgrq
= 1;
704 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
706 /* only one working comparator */
707 arm7_9
->wp_available_max
= 1;
708 arm7_9
->wp1_used_default
= -1;
711 int feroceon_target_create(struct target_s
*target
, Jim_Interp
*interp
)
713 arm926ejs_common_t
*arm926ejs
= calloc(1,sizeof(arm926ejs_common_t
));
715 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
716 feroceon_common_setup(target
);
718 /* the standard ARM926 methods don't always work (don't ask...) */
719 arm926ejs
->read_cp15
= feroceon_read_cp15
;
720 arm926ejs
->write_cp15
= feroceon_write_cp15
;
725 int dragonite_target_create(struct target_s
*target
, Jim_Interp
*interp
)
727 arm966e_common_t
*arm966e
= calloc(1,sizeof(arm966e_common_t
));
729 arm966e_init_arch_info(target
, arm966e
, target
->tap
);
730 feroceon_common_setup(target
);
735 int feroceon_examine(struct target_s
*target
)
737 armv4_5_common_t
*armv4_5
;
738 arm7_9_common_t
*arm7_9
;
741 retval
= arm9tdmi_examine(target
);
742 if (retval
!= ERROR_OK
)
745 armv4_5
= target
->arch_info
;
746 arm7_9
= armv4_5
->arch_info
;
748 /* the COMMS_CTRL bits are all contiguous */
749 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
750 LOG_ERROR("unexpected Feroceon EICE version signature");
752 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
753 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
754 arm7_9
->has_monitor_mode
= 1;
756 /* vector catch reg is not initialized on reset */
757 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
759 /* clear monitor mode, enable comparators */
760 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
761 jtag_execute_queue();
762 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
763 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
764 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)