1 /***************************************************************************
2 * Copyright (C) 2008 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
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. *
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. *
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 ***************************************************************************/
22 * Marvell Feroceon (88F5182, 88F5281) support.
24 * The Feroceon core mimics the ARM926 ICE interface with the following
27 * - the MOE (method of entry) reporting is not implemented
29 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
31 * - due to a different pipeline implementation, some injected debug
32 * instruction sequences have to be somewhat different
36 * - asserting DBGRQ doesn't work if target is looping on the undef vector
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
41 * - the DCC channel is half duplex (only one FIFO for both directions) with
42 * seemingly no proper flow control.
49 #include "arm926ejs.h"
52 #include "arm_simulator.h"
57 int feroceon_examine(struct command_context_s
*cmd_ctx
, 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
);
63 target_type_t feroceon_target
=
68 .arch_state
= arm926ejs_arch_state
,
70 .target_request_data
= arm7_9_target_request_data
,
73 .resume
= arm7_9_resume
,
76 .assert_reset
= arm7_9_assert_reset
,
77 .deassert_reset
= arm7_9_deassert_reset
,
78 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
80 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
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
,
88 .run_algorithm
= armv4_5_run_algorithm
,
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
,
95 .register_commands
= arm926ejs_register_commands
,
96 .target_command
= feroceon_target_command
,
97 .init_target
= feroceon_init_target
,
98 .examine
= feroceon_examine
,
103 void feroceon_change_to_arm(target_t
*target
, u32
*r0
, u32
*pc
)
105 armv4_5_common_t
*armv4_5
= target
->arch_info
;
106 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
107 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
110 * save r0 before using it and put system in ARM state
111 * to allow common handling of ARM and THUMB debugging
114 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
115 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
116 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
117 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
118 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
119 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
120 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
121 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
122 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
124 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
125 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
126 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
127 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
128 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
129 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
130 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
132 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 0, NULL
, 0);
133 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
134 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
135 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
136 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
138 jtag_execute_queue();
141 * fix program counter:
142 * MOV R0, PC was the 10th instruction (+18)
143 * reading PC in Thumb state gives address of instruction + 4
148 void feroceon_read_core_regs(target_t
*target
, u32 mask
, u32
* core_regs
[16])
151 armv4_5_common_t
*armv4_5
= target
->arch_info
;
152 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
153 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
155 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
156 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
157 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
159 for (i
= 0; i
<= 15; i
++)
161 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
163 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
164 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
167 void feroceon_read_core_regs_target_buffer(target_t
*target
, u32 mask
, void* buffer
, int size
)
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
;
173 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
174 u32
*buf_u32
= buffer
;
175 u16
*buf_u16
= buffer
;
178 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
179 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
180 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
182 for (i
= 0; i
<= 15; i
++)
184 if (mask
& (1 << i
)) {
188 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
191 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
194 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
200 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
201 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
204 void feroceon_read_xpsr(target_t
*target
, u32
*xpsr
, int spsr
)
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
;
210 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 0, NULL
, 0);
211 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
212 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
213 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
214 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
215 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
216 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
218 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
219 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
220 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
221 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, xpsr
, 0);
223 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
224 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
227 void feroceon_write_xpsr(target_t
*target
, u32 xpsr
, int spsr
)
229 armv4_5_common_t
*armv4_5
= target
->arch_info
;
230 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
231 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
233 LOG_DEBUG("xpsr: %8.8x, spsr: %i", xpsr
, spsr
);
235 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 0, NULL
, 0);
236 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
237 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
238 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
239 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
240 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
241 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
243 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 0, NULL
, 0);
244 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
245 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
246 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
247 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
248 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
249 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
251 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 0, NULL
, 0);
252 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
253 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
254 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
255 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
256 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
257 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
259 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 0, NULL
, 0);
260 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
261 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
262 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
263 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
264 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
265 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
268 void feroceon_write_xpsr_im8(target_t
*target
, u8 xpsr_im
, int rot
, int spsr
)
270 armv4_5_common_t
*armv4_5
= target
->arch_info
;
271 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
272 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
274 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
276 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 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);
285 void feroceon_write_core_regs(target_t
*target
, u32 mask
, u32 core_regs
[16])
288 armv4_5_common_t
*armv4_5
= target
->arch_info
;
289 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
290 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
292 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 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);
296 for (i
= 0; i
<= 15; i
++)
298 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], 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);
305 void feroceon_branch_resume(target_t
*target
)
307 armv4_5_common_t
*armv4_5
= target
->arch_info
;
308 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
309 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
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_B(0xfffff9, 0), 0, NULL
, 0);
315 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
317 /* need BYPASS before RESTART */
318 jtag_add_end_state(TAP_RTI
);
319 arm_jtag_set_instr(jtag_info
, 0xf, NULL
);
322 void feroceon_branch_resume_thumb(target_t
*target
)
326 armv4_5_common_t
*armv4_5
= target
->arch_info
;
327 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
328 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
329 u32 r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
330 u32 pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
332 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 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
, pc
& ~3, 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 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);
345 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); /* add r0,r15,#1 */
346 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 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);
350 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 1), 0, NULL
, 0);
351 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
352 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, r0
, NULL
, 0);
354 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
355 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
358 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
359 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
361 /* need BYPASS before RESTART */
362 jtag_add_end_state(TAP_RTI
);
363 arm_jtag_set_instr(jtag_info
, 0xf, NULL
);
366 int feroceon_read_cp15(target_t
*target
, u32 op1
, u32 op2
, u32 CRn
, u32 CRm
, u32
*value
)
368 armv4_5_common_t
*armv4_5
= target
->arch_info
;
369 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
370 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
373 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
374 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
375 err
= arm7_9_execute_sys_speed(target
);
379 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 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_NOP
, 0, value
, 0);
383 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
384 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
385 return jtag_execute_queue();
388 int feroceon_write_cp15(target_t
*target
, u32 op1
, u32 op2
, u32 CRn
, u32 CRm
, u32 value
)
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
;
394 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, 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
, value
, 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
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
403 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
404 return arm7_9_execute_sys_speed(target
);
407 void feroceon_enable_single_step(target_t
*target
)
409 armv4_5_common_t
*armv4_5
= target
->arch_info
;
410 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
413 /* calculate PC of next instruction */
414 if (arm_simulate_step(target
, &next_pc
) != ERROR_OK
)
416 u32 current_pc
, current_opcode
;
417 current_pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
418 target_read_u32(target
, current_pc
, ¤t_opcode
);
419 LOG_ERROR("BUG: couldn't calculate PC of next instruction, "
420 "current opcode is 0x%8.8x", current_opcode
);
421 next_pc
= current_pc
;
423 arm7_9_restore_context(target
);
425 /* set a breakpoint there */
426 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
427 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
428 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
429 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
430 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
433 void feroceon_disable_single_step(target_t
*target
)
435 armv4_5_common_t
*armv4_5
= target
->arch_info
;
436 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
438 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
439 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
440 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
441 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
442 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
445 int feroceon_examine_debug_reason(target_t
*target
)
447 /* the MOE is not implemented */
448 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
450 target
->debug_reason
= DBG_REASON_DBGRQ
;
456 int feroceon_bulk_write_memory(target_t
*target
, u32 address
, u32 count
, u8
*buffer
)
458 armv4_5_common_t
*armv4_5
= target
->arch_info
;
459 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
460 enum armv4_5_state core_state
= armv4_5
->core_state
;
461 u32 x
, flip
, shift
, save
[7];
465 * We can't use the dcc flow control bits, so let's transfer data
466 * with 31 bits and flip the MSB each time a new data word is sent.
468 static u32 dcc_code
[] =
470 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
471 0xe3a0301e, /* 1: mov r3, #30 */
472 0xe3a04002, /* mov r4, #2 */
473 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
474 0xe1310005, /* teq r1, r5 */
475 0x0afffffc, /* beq 1b */
476 0xe1a05001, /* mov r5, r1 */
477 0xe1a01081, /* mov r1, r1, lsl #1 */
478 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
479 0xe1320005, /* teq r2, r5 */
480 0x0afffffc, /* beq 3b */
481 0xe1a05002, /* mov r5, r2 */
482 0xe3c22102, /* bic r2, r2, #0x80000000 */
483 0xe1811332, /* orr r1, r1, r2, lsr r3 */
484 0xe2533001, /* subs r3, r3, #1 */
485 0xe4801004, /* str r1, [r0], #4 */
486 0xe1a01412, /* mov r1, r2, lsl r4 */
487 0xe2844001, /* add r4, r4, #1 */
488 0x4affffed, /* bmi 1b */
489 0xeafffff3, /* b 3b */
492 int dcc_size
= sizeof(dcc_code
);
494 if (!arm7_9
->dcc_downloads
)
495 return target
->type
->write_memory(target
, address
, 4, count
, buffer
);
497 /* regrab previously allocated working_area, or allocate a new one */
498 if (!arm7_9
->dcc_working_area
)
500 u8 dcc_code_buf
[dcc_size
];
502 /* make sure we have a working area */
503 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
505 LOG_INFO("no working area available, falling back to memory writes");
506 return target
->type
->write_memory(target
, address
, 4, count
, buffer
);
509 /* copy target instructions to target endianness */
510 for (i
= 0; i
< dcc_size
/4; i
++)
511 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
513 /* write DCC code to working area */
514 target
->type
->write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
, dcc_code_buf
);
517 /* backup clobbered processor state */
518 for (i
= 0; i
<= 5; i
++)
519 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
520 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
522 /* set up target address in r0 */
523 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
524 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
525 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
526 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
528 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
529 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
535 for (i
= 0; i
< count
; i
++)
537 u32 y
= target_buffer_get_u32(target
, buffer
);
538 u32 z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
539 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
540 x
= y
<< (32 - shift
);
541 if (++shift
>= 32 || i
+ 1 >= count
)
543 z
= (x
>> 1) | (flip
^= 0x80000000);
544 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
552 while (target
->state
!= TARGET_HALTED
)
555 /* restore target state */
556 for (i
= 0; i
<= 5; i
++)
558 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
559 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
560 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
562 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
563 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
564 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
565 armv4_5
->core_state
= core_state
;
570 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
)
572 arm9tdmi_init_target(cmd_ctx
, target
);
581 int feroceon_target_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct target_s
*target
)
584 char *variant
= NULL
;
585 armv4_5_common_t
*armv4_5
;
586 arm7_9_common_t
*arm7_9
;
587 arm926ejs_common_t
*arm926ejs
= malloc(sizeof(arm926ejs_common_t
));
588 memset(arm926ejs
, 0, sizeof(*arm926ejs
));
592 LOG_ERROR("'target arm926ejs' requires at least one additional argument");
596 chain_pos
= strtoul(args
[3], NULL
, 0);
601 LOG_DEBUG("chain_pos: %i, variant: %s", chain_pos
, variant
);
603 arm926ejs_init_arch_info(target
, arm926ejs
, chain_pos
, variant
);
605 armv4_5
= target
->arch_info
;
606 arm7_9
= armv4_5
->arch_info
;
608 /* override some insn sequence functions */
609 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
610 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
611 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
612 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
613 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
614 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
615 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
616 arm7_9
->branch_resume
= feroceon_branch_resume
;
617 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
619 /* must be implemented with only one comparator */
620 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
621 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
623 /* MOE is not implemented */
624 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
626 /* the standard ARM926 methods don't always work (don't ask...) */
627 arm926ejs
->read_cp15
= feroceon_read_cp15
;
628 arm926ejs
->write_cp15
= feroceon_write_cp15
;
630 /* asserting DBGRQ won't win over the undef exception */
631 arm7_9
->use_dbgrq
= 0;
633 /* only one working comparator */
634 arm7_9
->wp_available
= 1;
635 arm7_9
->wp1_used
= -1;
641 int feroceon_examine(struct command_context_s
*cmd_ctx
, struct target_s
*target
)
643 armv4_5_common_t
*armv4_5
;
644 arm7_9_common_t
*arm7_9
;
647 retval
= arm9tdmi_examine(cmd_ctx
, target
);
648 if (retval
!=ERROR_OK
)
651 armv4_5
= target
->arch_info
;
652 arm7_9
= armv4_5
->arch_info
;
654 /* the COMMS_CTRL bits are all contiguous */
655 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
656 LOG_ERROR("unexpected Feroceon EICE version signature");
658 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
659 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
660 arm7_9
->has_monitor_mode
= 1;
662 /* vector catch reg is not initialized on reset */
663 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
665 /* clear monitor mode, enable comparators */
666 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
667 jtag_execute_queue();
668 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
669 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
670 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)