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"
53 #include "target_type.h"
56 int feroceon_examine(struct target_s
*target
);
57 int feroceon_target_create(struct target_s
*target
, Jim_Interp
*interp
);
58 int feroceon_bulk_write_memory(target_t
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
);
59 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
);
60 int feroceon_quit(void);
62 int feroceon_assert_reset(target_t
*target
)
64 armv4_5_common_t
*armv4_5
= target
->arch_info
;
65 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
66 int ud
= arm7_9
->use_dbgrq
;
68 arm7_9
->use_dbgrq
= 0;
69 if (target
->reset_halt
)
71 arm7_9
->use_dbgrq
= ud
;
72 return arm7_9_assert_reset(target
);
75 target_type_t feroceon_target
=
80 .arch_state
= arm926ejs_arch_state
,
82 .target_request_data
= arm7_9_target_request_data
,
85 .resume
= arm7_9_resume
,
88 .assert_reset
= feroceon_assert_reset
,
89 .deassert_reset
= arm7_9_deassert_reset
,
90 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
92 .get_gdb_reg_list
= armv4_5_get_gdb_reg_list
,
94 .read_memory
= arm7_9_read_memory
,
95 .write_memory
= arm926ejs_write_memory
,
96 .bulk_write_memory
= feroceon_bulk_write_memory
,
97 .checksum_memory
= arm7_9_checksum_memory
,
98 .blank_check_memory
= arm7_9_blank_check_memory
,
100 .run_algorithm
= armv4_5_run_algorithm
,
102 .add_breakpoint
= arm7_9_add_breakpoint
,
103 .remove_breakpoint
= arm7_9_remove_breakpoint
,
104 .add_watchpoint
= arm7_9_add_watchpoint
,
105 .remove_watchpoint
= arm7_9_remove_watchpoint
,
107 .register_commands
= arm926ejs_register_commands
,
108 .target_create
= feroceon_target_create
,
109 .init_target
= feroceon_init_target
,
110 .examine
= feroceon_examine
,
111 .quit
= feroceon_quit
115 int feroceon_dummy_clock_out(arm_jtag_t
*jtag_info
, uint32_t instr
)
117 scan_field_t fields
[3];
119 uint8_t instr_buf
[4];
120 uint8_t sysspeed_buf
= 0x0;
123 buf_set_u32(out_buf
, 0, 32, 0);
125 buf_set_u32(instr_buf
, 0, 32, flip_u32(instr
, 32));
127 jtag_set_end_state(TAP_DRPAUSE
);
128 arm_jtag_scann(jtag_info
, 0x1);
130 arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
);
132 fields
[0].tap
= jtag_info
->tap
;
133 fields
[0].num_bits
= 32;
134 fields
[0].out_value
= out_buf
;
136 fields
[0].in_value
= NULL
;
142 fields
[1].tap
= jtag_info
->tap
;
143 fields
[1].num_bits
= 3;
144 fields
[1].out_value
= &sysspeed_buf
;
146 fields
[1].in_value
= NULL
;
152 fields
[2].tap
= jtag_info
->tap
;
153 fields
[2].num_bits
= 32;
154 fields
[2].out_value
= instr_buf
;
156 fields
[2].in_value
= NULL
;
162 jtag_add_dr_scan(3, fields
, jtag_get_end_state());
164 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
169 void feroceon_change_to_arm(target_t
*target
, uint32_t *r0
, uint32_t *pc
)
171 armv4_5_common_t
*armv4_5
= target
->arch_info
;
172 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
173 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
176 * save r0 before using it and put system in ARM state
177 * to allow common handling of ARM and THUMB debugging
180 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
181 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
182 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
184 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 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, NULL
, 0);
187 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
188 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
189 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
191 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
192 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 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, NULL
, 0);
195 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
196 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
197 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
199 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 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);
203 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
205 jtag_execute_queue();
208 * fix program counter:
209 * MOV R0, PC was the 7th instruction (+12)
210 * reading PC in Thumb state gives address of instruction + 4
215 void feroceon_read_core_regs(target_t
*target
, uint32_t mask
, uint32_t* core_regs
[16])
218 armv4_5_common_t
*armv4_5
= target
->arch_info
;
219 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
220 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
222 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 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);
226 for (i
= 0; i
<= 15; i
++)
228 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
230 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
231 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
234 void feroceon_read_core_regs_target_buffer(target_t
*target
, uint32_t mask
, void* buffer
, int size
)
237 armv4_5_common_t
*armv4_5
= target
->arch_info
;
238 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
239 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
240 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
241 uint32_t *buf_u32
= buffer
;
242 uint16_t *buf_u16
= buffer
;
243 uint8_t *buf_u8
= buffer
;
245 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 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);
249 for (i
= 0; i
<= 15; i
++)
251 if (mask
& (1 << i
)) {
255 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
258 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
261 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
267 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
268 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
271 void feroceon_read_xpsr(target_t
*target
, uint32_t *xpsr
, int spsr
)
273 armv4_5_common_t
*armv4_5
= target
->arch_info
;
274 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
275 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
277 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 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);
283 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
285 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 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, NULL
, 0);
288 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, xpsr
, 0);
290 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
291 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
294 void feroceon_write_xpsr(target_t
*target
, uint32_t xpsr
, int spsr
)
296 armv4_5_common_t
*armv4_5
= target
->arch_info
;
297 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
298 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
300 LOG_DEBUG("xpsr: %8.8x, spsr: %i", xpsr
, spsr
);
302 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 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);
308 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
310 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 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);
316 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
318 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 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);
324 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
326 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 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);
332 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
335 void feroceon_write_xpsr_im8(target_t
*target
, uint8_t xpsr_im
, int rot
, int spsr
)
337 armv4_5_common_t
*armv4_5
= target
->arch_info
;
338 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
339 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
341 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
343 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 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);
349 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
352 void feroceon_write_core_regs(target_t
*target
, uint32_t mask
, uint32_t core_regs
[16])
355 armv4_5_common_t
*armv4_5
= target
->arch_info
;
356 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
357 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
359 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
360 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
361 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
363 for (i
= 0; i
<= 15; i
++)
365 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], 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);
369 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
372 void feroceon_branch_resume(target_t
*target
)
374 armv4_5_common_t
*armv4_5
= target
->arch_info
;
375 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
376 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
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_NOP
, 0, NULL
, 0);
381 arm9tdmi_clock_out(jtag_info
, ARMV4_5_B(0xfffff9, 0), 0, NULL
, 0);
382 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
384 arm7_9
->need_bypass_before_restart
= 1;
387 void feroceon_branch_resume_thumb(target_t
*target
)
391 armv4_5_common_t
*armv4_5
= target
->arch_info
;
392 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
393 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
394 uint32_t r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
395 uint32_t pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
396 (void)(r0
); // use R0...
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);
401 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
403 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); // add r0,pc,#1
404 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
405 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
406 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
408 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
409 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
410 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
412 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, pc
, NULL
, 0);
413 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
414 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
417 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
418 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
420 arm7_9
->need_bypass_before_restart
= 1;
423 int feroceon_read_cp15(target_t
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
425 armv4_5_common_t
*armv4_5
= target
->arch_info
;
426 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
427 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
430 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
431 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
432 err
= arm7_9_execute_sys_speed(target
);
436 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 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, NULL
, 0);
439 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 0);
440 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
441 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
442 return jtag_execute_queue();
445 int feroceon_write_cp15(target_t
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
447 armv4_5_common_t
*armv4_5
= target
->arch_info
;
448 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
449 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
451 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 0);
452 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
453 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
454 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, 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);
457 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
459 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
460 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
461 return arm7_9_execute_sys_speed(target
);
464 void feroceon_set_dbgrq(target_t
*target
)
466 armv4_5_common_t
*armv4_5
= target
->arch_info
;
467 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
468 reg_t
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
470 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
471 embeddedice_store_reg(dbg_ctrl
);
474 void feroceon_enable_single_step(target_t
*target
, uint32_t next_pc
)
476 armv4_5_common_t
*armv4_5
= target
->arch_info
;
477 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
479 /* set a breakpoint there */
480 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
481 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
482 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
483 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
484 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
487 void feroceon_disable_single_step(target_t
*target
)
489 armv4_5_common_t
*armv4_5
= target
->arch_info
;
490 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
492 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
493 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
494 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
495 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
496 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
499 int feroceon_examine_debug_reason(target_t
*target
)
501 /* the MOE is not implemented */
502 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
504 target
->debug_reason
= DBG_REASON_DBGRQ
;
510 int feroceon_bulk_write_memory(target_t
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
)
513 armv4_5_common_t
*armv4_5
= target
->arch_info
;
514 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
515 enum armv4_5_state core_state
= armv4_5
->core_state
;
516 uint32_t x
, flip
, shift
, save
[7];
520 * We can't use the dcc flow control bits, so let's transfer data
521 * with 31 bits and flip the MSB each time a new data word is sent.
523 static uint32_t dcc_code
[] =
525 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
526 0xe3a0301e, /* 1: mov r3, #30 */
527 0xe3a04002, /* mov r4, #2 */
528 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
529 0xe1310005, /* teq r1, r5 */
530 0x0afffffc, /* beq 1b */
531 0xe1a05001, /* mov r5, r1 */
532 0xe1a01081, /* mov r1, r1, lsl #1 */
533 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
534 0xe1320005, /* teq r2, r5 */
535 0x0afffffc, /* beq 3b */
536 0xe1a05002, /* mov r5, r2 */
537 0xe3c22102, /* bic r2, r2, #0x80000000 */
538 0xe1811332, /* orr r1, r1, r2, lsr r3 */
539 0xe2533001, /* subs r3, r3, #1 */
540 0xe4801004, /* str r1, [r0], #4 */
541 0xe1a01412, /* mov r1, r2, lsl r4 */
542 0xe2844001, /* add r4, r4, #1 */
543 0x4affffed, /* bmi 1b */
544 0xeafffff3, /* b 3b */
547 uint32_t dcc_size
= sizeof(dcc_code
);
549 if (!arm7_9
->dcc_downloads
)
550 return target_write_memory(target
, address
, 4, count
, buffer
);
552 /* regrab previously allocated working_area, or allocate a new one */
553 if (!arm7_9
->dcc_working_area
)
555 uint8_t dcc_code_buf
[dcc_size
];
557 /* make sure we have a working area */
558 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
560 LOG_INFO("no working area available, falling back to memory writes");
561 return target_write_memory(target
, address
, 4, count
, buffer
);
564 /* copy target instructions to target endianness */
565 for (i
= 0; i
< dcc_size
/4; i
++)
566 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
568 /* write DCC code to working area */
569 if((retval
= target_write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
575 /* backup clobbered processor state */
576 for (i
= 0; i
<= 5; i
++)
577 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
578 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
580 /* set up target address in r0 */
581 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
582 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
583 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
584 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
586 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
587 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
593 for (i
= 0; i
< count
; i
++)
595 uint32_t y
= target_buffer_get_u32(target
, buffer
);
596 uint32_t z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
597 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
598 x
= y
<< (32 - shift
);
599 if (++shift
>= 32 || i
+ 1 >= count
)
601 z
= (x
>> 1) | (flip
^= 0x80000000);
602 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
610 while (target
->state
!= TARGET_HALTED
)
613 /* restore target state */
614 for (i
= 0; i
<= 5; i
++)
616 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
617 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
618 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
620 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
621 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
622 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
623 armv4_5
->core_state
= core_state
;
628 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
)
630 arm9tdmi_init_target(cmd_ctx
, target
);
634 int feroceon_quit(void)
639 int feroceon_target_create(struct target_s
*target
, Jim_Interp
*interp
)
641 armv4_5_common_t
*armv4_5
;
642 arm7_9_common_t
*arm7_9
;
643 arm926ejs_common_t
*arm926ejs
= calloc(1,sizeof(arm926ejs_common_t
));
645 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
647 armv4_5
= target
->arch_info
;
648 arm7_9
= armv4_5
->arch_info
;
650 /* override some insn sequence functions */
651 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
652 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
653 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
654 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
655 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
656 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
657 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
658 arm7_9
->branch_resume
= feroceon_branch_resume
;
659 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
661 /* must be implemented with only one comparator */
662 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
663 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
665 /* MOE is not implemented */
666 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
668 /* the standard ARM926 methods don't always work (don't ask...) */
669 arm926ejs
->read_cp15
= feroceon_read_cp15
;
670 arm926ejs
->write_cp15
= feroceon_write_cp15
;
672 /* Note: asserting DBGRQ might not win over the undef exception.
673 If that happens then just use "arm7_9 dbgrq disable". */
674 arm7_9
->use_dbgrq
= 1;
675 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
677 /* only one working comparator */
678 arm7_9
->wp_available_max
= 1;
679 arm7_9
->wp1_used_default
= -1;
684 int feroceon_examine(struct target_s
*target
)
686 armv4_5_common_t
*armv4_5
;
687 arm7_9_common_t
*arm7_9
;
690 retval
= arm9tdmi_examine(target
);
691 if (retval
!=ERROR_OK
)
694 armv4_5
= target
->arch_info
;
695 arm7_9
= armv4_5
->arch_info
;
697 /* the COMMS_CTRL bits are all contiguous */
698 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
699 LOG_ERROR("unexpected Feroceon EICE version signature");
701 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
702 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
703 arm7_9
->has_monitor_mode
= 1;
705 /* vector catch reg is not initialized on reset */
706 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
708 /* clear monitor mode, enable comparators */
709 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
710 jtag_execute_queue();
711 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
712 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
713 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)