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"
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
,
79 .prepare_reset_halt
= arm7_9_prepare_reset_halt
,
81 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
83 .read_memory
= arm7_9_read_memory
,
84 .write_memory
= arm926ejs_write_memory
,
85 .bulk_write_memory
= feroceon_bulk_write_memory
,
86 .checksum_memory
= arm7_9_checksum_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
,
102 void feroceon_change_to_arm(target_t
*target
, u32
*r0
, u32
*pc
)
104 armv4_5_common_t
*armv4_5
= target
->arch_info
;
105 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
106 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
109 * save r0 before using it and put system in ARM state
110 * to allow common handling of ARM and THUMB debugging
113 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
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_STR(0, 0), 0, NULL
, 0);
117 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 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, r0
, 0);
120 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
121 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
123 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
124 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
125 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 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, pc
, 0);
128 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
129 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
131 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 0, NULL
, 0);
132 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 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);
137 jtag_execute_queue();
140 * fix program counter:
141 * MOV R0, PC was the 10th instruction (+18)
142 * reading PC in Thumb state gives address of instruction + 4
147 void feroceon_read_core_regs(target_t
*target
, u32 mask
, u32
* core_regs
[16])
150 armv4_5_common_t
*armv4_5
= target
->arch_info
;
151 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
152 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
154 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
155 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
156 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
158 for (i
= 0; i
<= 15; i
++)
160 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
162 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
163 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
166 void feroceon_read_core_regs_target_buffer(target_t
*target
, u32 mask
, void* buffer
, int size
)
169 armv4_5_common_t
*armv4_5
= target
->arch_info
;
170 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
171 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
172 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
173 u32
*buf_u32
= buffer
;
174 u16
*buf_u16
= buffer
;
177 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
178 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
179 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
181 for (i
= 0; i
<= 15; i
++)
183 if (mask
& (1 << i
)) {
187 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
190 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
193 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
199 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
200 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
203 void feroceon_read_xpsr(target_t
*target
, u32
*xpsr
, int spsr
)
205 armv4_5_common_t
*armv4_5
= target
->arch_info
;
206 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
207 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
209 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 0, NULL
, 0);
210 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
217 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
218 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
219 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
220 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, xpsr
, 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);
226 void feroceon_write_xpsr(target_t
*target
, u32 xpsr
, int spsr
)
228 armv4_5_common_t
*armv4_5
= target
->arch_info
;
229 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
230 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
232 DEBUG("xpsr: %8.8x, spsr: %i", xpsr
, spsr
);
234 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 0, NULL
, 0);
235 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
242 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 0, NULL
, 0);
243 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
250 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 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);
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);
258 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 0, NULL
, 0);
259 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
267 void feroceon_write_xpsr_im8(target_t
*target
, u8 xpsr_im
, int rot
, int spsr
)
269 armv4_5_common_t
*armv4_5
= target
->arch_info
;
270 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
271 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
273 DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
275 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 0, NULL
, 0);
276 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
284 void feroceon_write_core_regs(target_t
*target
, u32 mask
, u32 core_regs
[16])
287 armv4_5_common_t
*armv4_5
= target
->arch_info
;
288 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
289 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
291 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
292 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
293 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
295 for (i
= 0; i
<= 15; i
++)
297 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], NULL
, 0);
299 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
300 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
301 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
304 void feroceon_branch_resume(target_t
*target
)
306 armv4_5_common_t
*armv4_5
= target
->arch_info
;
307 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
308 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
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_B(0xfffff9, 0), 0, NULL
, 0);
314 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
316 /* need BYPASS before RESTART */
317 jtag_add_end_state(TAP_RTI
);
318 arm_jtag_set_instr(jtag_info
, 0xf, NULL
);
321 void feroceon_branch_resume_thumb(target_t
*target
)
325 armv4_5_common_t
*armv4_5
= target
->arch_info
;
326 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
327 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
328 u32 r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
329 u32 pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
331 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 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
, pc
& ~3, NULL
, 0);
335 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
336 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
337 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
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);
344 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); /* add r0,r15,#1 */
345 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 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);
349 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 1), 0, NULL
, 0);
350 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 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
, r0
, NULL
, 0);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
354 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
357 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
358 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
360 /* need BYPASS before RESTART */
361 jtag_add_end_state(TAP_RTI
);
362 arm_jtag_set_instr(jtag_info
, 0xf, NULL
);
365 int feroceon_read_cp15(target_t
*target
, u32 op1
, u32 op2
, u32 CRn
, u32 CRm
, u32
*value
)
367 armv4_5_common_t
*armv4_5
= target
->arch_info
;
368 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
369 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
372 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
373 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
374 err
= arm7_9_execute_sys_speed(target
);
378 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
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, value
, 0);
382 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
383 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
384 return jtag_execute_queue();
387 int feroceon_write_cp15(target_t
*target
, u32 op1
, u32 op2
, u32 CRn
, u32 CRm
, u32 value
)
389 armv4_5_common_t
*armv4_5
= target
->arch_info
;
390 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
391 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
393 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 0);
394 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
395 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
396 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, NULL
, 0);
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);
401 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
402 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
403 return arm7_9_execute_sys_speed(target
);
406 void feroceon_enable_single_step(target_t
*target
)
408 armv4_5_common_t
*armv4_5
= target
->arch_info
;
409 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
412 /* calculate PC of next instruction */
413 if (arm_simulate_step(target
, &next_pc
) != ERROR_OK
)
415 u32 current_pc
, current_opcode
;
416 current_pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
417 target_read_u32(target
, current_pc
, ¤t_opcode
);
418 ERROR("BUG: couldn't calculate PC of next instruction, "
419 "current opcode is 0x%8.8x", current_opcode
);
420 next_pc
= current_pc
;
422 arm7_9_restore_context(target
);
424 /* set a breakpoint there */
425 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
426 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
427 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
428 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
429 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
432 void feroceon_disable_single_step(target_t
*target
)
434 armv4_5_common_t
*armv4_5
= target
->arch_info
;
435 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
437 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
438 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
439 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
440 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
441 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
444 int feroceon_examine_debug_reason(target_t
*target
)
446 /* the MOE is not implemented */
447 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
449 target
->debug_reason
= DBG_REASON_DBGRQ
;
455 int feroceon_bulk_write_memory(target_t
*target
, u32 address
, u32 count
, u8
*buffer
)
457 armv4_5_common_t
*armv4_5
= target
->arch_info
;
458 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
459 enum armv4_5_state core_state
= armv4_5
->core_state
;
460 u32 x
, flip
, shift
, save
[7];
464 * We can't use the dcc flow control bits, so let's transfer data
465 * with 31 bits and flip the MSB each time a new data word is sent.
467 static u32 dcc_code
[] =
469 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
470 0xe3a0301e, /* 1: mov r3, #30 */
471 0xe3a04002, /* mov r4, #2 */
472 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
473 0xe1310005, /* teq r1, r5 */
474 0x0afffffc, /* beq 1b */
475 0xe1a05001, /* mov r5, r1 */
476 0xe1a01081, /* mov r1, r1, lsl #1 */
477 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
478 0xe1320005, /* teq r2, r5 */
479 0x0afffffc, /* beq 3b */
480 0xe1a05002, /* mov r5, r2 */
481 0xe3c22102, /* bic r2, r2, #0x80000000 */
482 0xe1811332, /* orr r1, r1, r2, lsr r3 */
483 0xe2533001, /* subs r3, r3, #1 */
484 0xe4801004, /* str r1, [r0], #4 */
485 0xe1a01412, /* mov r1, r2, lsl r4 */
486 0xe2844001, /* add r4, r4, #1 */
487 0x4affffed, /* bmi 1b */
488 0xeafffff3, /* b 3b */
491 int dcc_size
= sizeof(dcc_code
);
493 if (!arm7_9
->dcc_downloads
)
494 return target
->type
->write_memory(target
, address
, 4, count
, buffer
);
496 /* regrab previously allocated working_area, or allocate a new one */
497 if (!arm7_9
->dcc_working_area
)
499 u8 dcc_code_buf
[dcc_size
];
501 /* make sure we have a working area */
502 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
504 INFO("no working area available, falling back to memory writes");
505 return target
->type
->write_memory(target
, address
, 4, count
, buffer
);
508 /* copy target instructions to target endianness */
509 for (i
= 0; i
< dcc_size
/4; i
++)
510 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
512 /* write DCC code to working area */
513 target
->type
->write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
, dcc_code_buf
);
516 /* backup clobbered processor state */
517 for (i
= 0; i
<= 5; i
++)
518 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
519 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
521 /* set up target address in r0 */
522 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
523 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
524 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
525 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
527 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
528 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
534 for (i
= 0; i
< count
; i
++)
536 u32 y
= target_buffer_get_u32(target
, buffer
);
537 u32 z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
538 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
539 x
= y
<< (32 - shift
);
540 if (++shift
>= 32 || i
+ 1 >= count
)
542 z
= (x
>> 1) | (flip
^= 0x80000000);
543 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
550 target
->type
->halt(target
);
551 while (target
->state
!= TARGET_HALTED
)
552 target
->type
->poll(target
);
554 /* restore target state */
555 for (i
= 0; i
<= 5; i
++)
557 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
558 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
559 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
561 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
562 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
563 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
564 armv4_5
->core_state
= core_state
;
569 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
)
571 armv4_5_common_t
*armv4_5
;
572 arm7_9_common_t
*arm7_9
;
574 arm9tdmi_init_target(cmd_ctx
, target
);
576 armv4_5
= target
->arch_info
;
577 arm7_9
= armv4_5
->arch_info
;
579 /* the COMMS_CTRL bits are all contiguous */
580 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
581 ERROR("unexpected Feroceon EICE version signature");
583 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
584 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
585 arm7_9
->has_monitor_mode
= 1;
587 /* vector catch reg is not initialized on reset */
588 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
590 /* clear monitor mode, enable comparators */
591 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
592 jtag_execute_queue();
593 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
594 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
595 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
605 int feroceon_target_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct target_s
*target
)
608 char *variant
= NULL
;
609 armv4_5_common_t
*armv4_5
;
610 arm7_9_common_t
*arm7_9
;
611 arm926ejs_common_t
*arm926ejs
= malloc(sizeof(arm926ejs_common_t
));
612 memset(arm926ejs
, 0, sizeof(*arm926ejs
));
616 ERROR("'target arm926ejs' requires at least one additional argument");
620 chain_pos
= strtoul(args
[3], NULL
, 0);
625 DEBUG("chain_pos: %i, variant: %s", chain_pos
, variant
);
627 arm926ejs_init_arch_info(target
, arm926ejs
, chain_pos
, variant
);
629 armv4_5
= target
->arch_info
;
630 arm7_9
= armv4_5
->arch_info
;
632 /* override some insn sequence functions */
633 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
634 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
635 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
636 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
637 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
638 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
639 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
640 arm7_9
->branch_resume
= feroceon_branch_resume
;
641 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
643 /* must be implemented with only one comparator */
644 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
645 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
647 /* MOE is not implemented */
648 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
650 /* the standard ARM926 methods don't always work (don't ask...) */
651 arm926ejs
->read_cp15
= feroceon_read_cp15
;
652 arm926ejs
->write_cp15
= feroceon_write_cp15
;
654 /* asserting DBGRQ won't win over the undef exception */
655 arm7_9
->use_dbgrq
= 0;
657 /* only one working comparator */
658 arm7_9
->wp_available
= 1;
659 arm7_9
->wp1_used
= -1;
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)