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
;
135 fields
[0].in_value
= NULL
;
137 fields
[1].tap
= jtag_info
->tap
;
138 fields
[1].num_bits
= 3;
139 fields
[1].out_value
= &sysspeed_buf
;
140 fields
[1].in_value
= NULL
;
142 fields
[2].tap
= jtag_info
->tap
;
143 fields
[2].num_bits
= 32;
144 fields
[2].out_value
= instr_buf
;
145 fields
[2].in_value
= NULL
;
147 jtag_add_dr_scan(3, fields
, jtag_get_end_state());
149 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
154 void feroceon_change_to_arm(target_t
*target
, uint32_t *r0
, uint32_t *pc
)
156 armv4_5_common_t
*armv4_5
= target
->arch_info
;
157 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
158 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
161 * save r0 before using it and put system in ARM state
162 * to allow common handling of ARM and THUMB debugging
165 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
166 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
167 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
169 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
170 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
171 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
172 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
173 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
174 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
176 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
177 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
178 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
179 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
180 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
181 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
182 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
184 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 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, NULL
, 0);
188 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
190 jtag_execute_queue();
193 * fix program counter:
194 * MOV R0, PC was the 7th instruction (+12)
195 * reading PC in Thumb state gives address of instruction + 4
200 void feroceon_read_core_regs(target_t
*target
, uint32_t mask
, uint32_t* core_regs
[16])
203 armv4_5_common_t
*armv4_5
= target
->arch_info
;
204 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
205 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
207 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
208 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
209 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
211 for (i
= 0; i
<= 15; i
++)
213 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
215 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
216 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
219 void feroceon_read_core_regs_target_buffer(target_t
*target
, uint32_t mask
, void* buffer
, int size
)
222 armv4_5_common_t
*armv4_5
= target
->arch_info
;
223 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
224 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
225 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
226 uint32_t *buf_u32
= buffer
;
227 uint16_t *buf_u16
= buffer
;
228 uint8_t *buf_u8
= buffer
;
230 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
231 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
232 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
234 for (i
= 0; i
<= 15; i
++)
236 if (mask
& (1 << i
)) {
240 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
243 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
246 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
252 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
253 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
256 void feroceon_read_xpsr(target_t
*target
, uint32_t *xpsr
, int spsr
)
258 armv4_5_common_t
*armv4_5
= target
->arch_info
;
259 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
260 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
262 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 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);
266 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
267 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
268 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
270 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
271 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
272 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
273 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, xpsr
, 0);
275 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
276 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
279 void feroceon_write_xpsr(target_t
*target
, uint32_t xpsr
, int spsr
)
281 armv4_5_common_t
*armv4_5
= target
->arch_info
;
282 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
283 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
285 LOG_DEBUG("xpsr: %8.8" PRIx32
", spsr: %i", xpsr
, spsr
);
287 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 0, NULL
, 0);
288 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
289 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
290 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
291 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 0, NULL
, 0);
296 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
297 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
298 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, 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);
303 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 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);
309 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
311 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 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);
317 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
320 void feroceon_write_xpsr_im8(target_t
*target
, uint8_t xpsr_im
, int rot
, int spsr
)
322 armv4_5_common_t
*armv4_5
= target
->arch_info
;
323 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
324 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
326 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
328 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 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);
333 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
334 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
337 void feroceon_write_core_regs(target_t
*target
, uint32_t mask
, uint32_t core_regs
[16])
340 armv4_5_common_t
*armv4_5
= target
->arch_info
;
341 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
342 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
344 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 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);
348 for (i
= 0; i
<= 15; i
++)
350 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], NULL
, 0);
352 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
354 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
357 void feroceon_branch_resume(target_t
*target
)
359 armv4_5_common_t
*armv4_5
= target
->arch_info
;
360 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
361 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
363 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
364 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
365 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
366 arm9tdmi_clock_out(jtag_info
, ARMV4_5_B(0xfffff9, 0), 0, NULL
, 0);
367 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
369 arm7_9
->need_bypass_before_restart
= 1;
372 void feroceon_branch_resume_thumb(target_t
*target
)
376 armv4_5_common_t
*armv4_5
= target
->arch_info
;
377 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
378 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
379 uint32_t r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
380 uint32_t pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
381 (void)(r0
); // use R0...
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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
386 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
388 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); // add r0,pc,#1
389 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
390 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
391 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
393 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
394 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
395 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
397 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, pc
, NULL
, 0);
398 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
399 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
402 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
403 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
405 arm7_9
->need_bypass_before_restart
= 1;
408 int feroceon_read_cp15(target_t
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
410 armv4_5_common_t
*armv4_5
= target
->arch_info
;
411 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
412 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
415 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
416 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
417 err
= arm7_9_execute_sys_speed(target
);
421 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
422 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
423 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
424 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 0);
425 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
426 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
427 return jtag_execute_queue();
430 int feroceon_write_cp15(target_t
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
432 armv4_5_common_t
*armv4_5
= target
->arch_info
;
433 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
434 arm_jtag_t
*jtag_info
= &arm7_9
->jtag_info
;
436 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(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
, value
, NULL
, 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
444 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
445 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
446 return arm7_9_execute_sys_speed(target
);
449 void feroceon_set_dbgrq(target_t
*target
)
451 armv4_5_common_t
*armv4_5
= target
->arch_info
;
452 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
453 reg_t
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
455 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
456 embeddedice_store_reg(dbg_ctrl
);
459 void feroceon_enable_single_step(target_t
*target
, uint32_t next_pc
)
461 armv4_5_common_t
*armv4_5
= target
->arch_info
;
462 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
464 /* set a breakpoint there */
465 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
466 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
467 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
468 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
469 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
472 void feroceon_disable_single_step(target_t
*target
)
474 armv4_5_common_t
*armv4_5
= target
->arch_info
;
475 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
477 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
478 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
479 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
480 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
481 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
484 int feroceon_examine_debug_reason(target_t
*target
)
486 /* the MOE is not implemented */
487 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
489 target
->debug_reason
= DBG_REASON_DBGRQ
;
495 int feroceon_bulk_write_memory(target_t
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
)
498 armv4_5_common_t
*armv4_5
= target
->arch_info
;
499 arm7_9_common_t
*arm7_9
= armv4_5
->arch_info
;
500 enum armv4_5_state core_state
= armv4_5
->core_state
;
501 uint32_t x
, flip
, shift
, save
[7];
505 * We can't use the dcc flow control bits, so let's transfer data
506 * with 31 bits and flip the MSB each time a new data word is sent.
508 static uint32_t dcc_code
[] =
510 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
511 0xe3a0301e, /* 1: mov r3, #30 */
512 0xe3a04002, /* mov r4, #2 */
513 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
514 0xe1310005, /* teq r1, r5 */
515 0x0afffffc, /* beq 1b */
516 0xe1a05001, /* mov r5, r1 */
517 0xe1a01081, /* mov r1, r1, lsl #1 */
518 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
519 0xe1320005, /* teq r2, r5 */
520 0x0afffffc, /* beq 3b */
521 0xe1a05002, /* mov r5, r2 */
522 0xe3c22102, /* bic r2, r2, #0x80000000 */
523 0xe1811332, /* orr r1, r1, r2, lsr r3 */
524 0xe2533001, /* subs r3, r3, #1 */
525 0xe4801004, /* str r1, [r0], #4 */
526 0xe1a01412, /* mov r1, r2, lsl r4 */
527 0xe2844001, /* add r4, r4, #1 */
528 0x4affffed, /* bmi 1b */
529 0xeafffff3, /* b 3b */
532 uint32_t dcc_size
= sizeof(dcc_code
);
534 if (!arm7_9
->dcc_downloads
)
535 return target_write_memory(target
, address
, 4, count
, buffer
);
537 /* regrab previously allocated working_area, or allocate a new one */
538 if (!arm7_9
->dcc_working_area
)
540 uint8_t dcc_code_buf
[dcc_size
];
542 /* make sure we have a working area */
543 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
545 LOG_INFO("no working area available, falling back to memory writes");
546 return target_write_memory(target
, address
, 4, count
, buffer
);
549 /* copy target instructions to target endianness */
550 for (i
= 0; i
< dcc_size
/4; i
++)
551 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
553 /* write DCC code to working area */
554 if ((retval
= target_write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
560 /* backup clobbered processor state */
561 for (i
= 0; i
<= 5; i
++)
562 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
563 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
565 /* set up target address in r0 */
566 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
567 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
568 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
569 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
571 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
572 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
578 for (i
= 0; i
< count
; i
++)
580 uint32_t y
= target_buffer_get_u32(target
, buffer
);
581 uint32_t z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
582 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
583 x
= y
<< (32 - shift
);
584 if (++shift
>= 32 || i
+ 1 >= count
)
586 z
= (x
>> 1) | (flip
^= 0x80000000);
587 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
594 retval
= target_halt(target
);
595 if (retval
== ERROR_OK
)
596 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
597 if (retval
== ERROR_OK
) {
598 uint32_t endaddress
=
599 buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
600 if (endaddress
!= address
+ count
*4) {
601 LOG_ERROR("DCC write failed,"
602 " expected end address 0x%08" PRIx32
603 " got 0x%0" PRIx32
"",
604 address
+ count
*4, endaddress
);
609 /* restore target state */
610 for (i
= 0; i
<= 5; i
++)
612 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
613 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
614 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
616 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
617 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
618 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
619 armv4_5
->core_state
= core_state
;
624 int feroceon_init_target(struct command_context_s
*cmd_ctx
, struct target_s
*target
)
626 arm9tdmi_init_target(cmd_ctx
, target
);
630 int feroceon_quit(void)
635 int feroceon_target_create(struct target_s
*target
, Jim_Interp
*interp
)
637 armv4_5_common_t
*armv4_5
;
638 arm7_9_common_t
*arm7_9
;
639 arm926ejs_common_t
*arm926ejs
= calloc(1,sizeof(arm926ejs_common_t
));
641 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
643 armv4_5
= target
->arch_info
;
644 arm7_9
= armv4_5
->arch_info
;
646 /* override some insn sequence functions */
647 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
648 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
649 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
650 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
651 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
652 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
653 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
654 arm7_9
->branch_resume
= feroceon_branch_resume
;
655 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
657 /* must be implemented with only one comparator */
658 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
659 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
661 /* MOE is not implemented */
662 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
664 /* the standard ARM926 methods don't always work (don't ask...) */
665 arm926ejs
->read_cp15
= feroceon_read_cp15
;
666 arm926ejs
->write_cp15
= feroceon_write_cp15
;
668 /* Note: asserting DBGRQ might not win over the undef exception.
669 If that happens then just use "arm7_9 dbgrq disable". */
670 arm7_9
->use_dbgrq
= 1;
671 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
673 /* only one working comparator */
674 arm7_9
->wp_available_max
= 1;
675 arm7_9
->wp1_used_default
= -1;
680 int feroceon_examine(struct target_s
*target
)
682 armv4_5_common_t
*armv4_5
;
683 arm7_9_common_t
*arm7_9
;
686 retval
= arm9tdmi_examine(target
);
687 if (retval
!= ERROR_OK
)
690 armv4_5
= target
->arch_info
;
691 arm7_9
= armv4_5
->arch_info
;
693 /* the COMMS_CTRL bits are all contiguous */
694 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
695 LOG_ERROR("unexpected Feroceon EICE version signature");
697 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
698 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
699 arm7_9
->has_monitor_mode
= 1;
701 /* vector catch reg is not initialized on reset */
702 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
704 /* clear monitor mode, enable comparators */
705 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
706 jtag_execute_queue();
707 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
708 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
709 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)