1 /***************************************************************************
2 * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
5 * Copyright (C) 2008 by Hongtao Zheng *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
23 * Marvell Feroceon/Dragonite support.
25 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
26 * mimics the ARM926 ICE interface with the following differences:
28 * - the MOE (method of entry) reporting is not implemented
30 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
32 * - due to a different pipeline implementation, some injected debug
33 * instruction sequences have to be somewhat different
37 * - asserting DBGRQ doesn't work if target is looping on the undef vector
39 * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
40 * not at the top, and rather meaningless due to existing discrepancies
42 * - the DCC channel is half duplex (only one FIFO for both directions) with
43 * seemingly no proper flow control.
45 * The Dragonite core is the non-mmu version based on the ARM966 model, and
46 * it shares the above issues as well.
53 #include "arm926ejs.h"
55 #include "target_type.h"
57 #include "arm_opcodes.h"
59 static int feroceon_assert_reset(struct target
*target
)
61 struct arm
*arm
= target
->arch_info
;
62 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
63 int ud
= arm7_9
->use_dbgrq
;
65 /* TODO: apply hw reset signal in not examined state */
66 if (!(target_was_examined(target
))) {
67 LOG_WARNING("Reset is not asserted because the target is not examined.");
68 LOG_WARNING("Use a reset button or power cycle the target.");
69 return ERROR_TARGET_NOT_EXAMINED
;
72 arm7_9
->use_dbgrq
= 0;
73 if (target
->reset_halt
)
75 arm7_9
->use_dbgrq
= ud
;
76 return arm7_9_assert_reset(target
);
79 static int feroceon_dummy_clock_out(struct arm_jtag
*jtag_info
, uint32_t instr
)
81 struct scan_field fields
[3];
84 uint8_t sysspeed_buf
= 0x0;
88 buf_set_u32(out_buf
, 0, 32, 0);
90 buf_set_u32(instr_buf
, 0, 32, flip_u32(instr
, 32));
92 retval
= arm_jtag_scann(jtag_info
, 0x1, TAP_DRPAUSE
);
93 if (retval
!= ERROR_OK
)
96 retval
= arm_jtag_set_instr(jtag_info
->tap
, jtag_info
->intest_instr
, NULL
, TAP_DRPAUSE
);
97 if (retval
!= ERROR_OK
)
100 fields
[0].num_bits
= 32;
101 fields
[0].out_value
= out_buf
;
102 fields
[0].in_value
= NULL
;
104 fields
[1].num_bits
= 3;
105 fields
[1].out_value
= &sysspeed_buf
;
106 fields
[1].in_value
= NULL
;
108 fields
[2].num_bits
= 32;
109 fields
[2].out_value
= instr_buf
;
110 fields
[2].in_value
= NULL
;
112 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_DRPAUSE
);
114 /* no jtag_add_runtest(0, TAP_DRPAUSE) here */
119 static void feroceon_change_to_arm(struct target
*target
, uint32_t *r0
,
122 struct arm
*arm
= target
->arch_info
;
123 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
124 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
127 * save r0 before using it and put system in ARM state
128 * to allow common handling of ARM and THUMB debugging
131 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
132 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
133 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
135 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
136 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
137 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
138 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
139 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
140 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
142 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
143 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
144 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
145 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
146 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
147 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
148 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
150 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 0, NULL
, 0);
151 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
152 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
153 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
154 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
156 jtag_execute_queue();
159 * fix program counter:
160 * MOV R0, PC was the 7th instruction (+12)
161 * reading PC in Thumb state gives address of instruction + 4
166 static void feroceon_read_core_regs(struct target
*target
,
167 uint32_t mask
, uint32_t *core_regs
[16])
170 struct arm
*arm
= target
->arch_info
;
171 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
172 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
174 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
175 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
176 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
178 for (i
= 0; i
<= 15; i
++)
180 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
182 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
183 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
186 static void feroceon_read_core_regs_target_buffer(struct target
*target
,
187 uint32_t mask
, void *buffer
, int size
)
190 struct arm
*arm
= target
->arch_info
;
191 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
192 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
193 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
194 uint32_t *buf_u32
= buffer
;
195 uint16_t *buf_u16
= buffer
;
196 uint8_t *buf_u8
= buffer
;
198 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
199 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
200 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
202 for (i
= 0; i
<= 15; i
++) {
203 if (mask
& (1 << i
)) {
206 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
209 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
212 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
218 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
219 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
222 static void feroceon_read_xpsr(struct target
*target
, uint32_t *xpsr
, int spsr
)
224 struct arm
*arm
= target
->arch_info
;
225 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
226 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
228 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 0, NULL
, 0);
229 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
230 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
233 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
234 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
236 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 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, xpsr
, 0);
241 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
242 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
245 static void feroceon_write_xpsr(struct target
*target
, uint32_t xpsr
, int spsr
)
247 struct arm
*arm
= target
->arch_info
;
248 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
249 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
251 LOG_DEBUG("xpsr: %8.8" PRIx32
", spsr: %i", xpsr
, spsr
);
253 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 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);
258 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
259 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
261 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 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);
266 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
267 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
269 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 0, NULL
, 0);
270 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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, NULL
, 0);
274 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
275 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
277 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 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);
286 static void feroceon_write_xpsr_im8(struct target
*target
,
287 uint8_t xpsr_im
, int rot
, int spsr
)
289 struct arm
*arm
= target
->arch_info
;
290 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
291 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
293 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
295 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, 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);
304 static void feroceon_write_core_regs(struct target
*target
,
305 uint32_t mask
, uint32_t core_regs
[16])
308 struct arm
*arm
= target
->arch_info
;
309 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
310 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
312 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 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);
316 for (i
= 0; i
<= 15; i
++)
318 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], 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);
325 static void feroceon_branch_resume(struct target
*target
)
327 struct arm
*arm
= target
->arch_info
;
328 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
329 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
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_B(0xfffff9, 0), 0, NULL
, 0);
335 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
337 arm7_9
->need_bypass_before_restart
= 1;
340 static void feroceon_branch_resume_thumb(struct target
*target
)
344 struct arm
*arm
= target
->arch_info
;
345 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
346 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
347 uint32_t r0
= buf_get_u32(arm
->core_cache
->reg_list
[0].value
, 0, 32);
348 uint32_t pc
= buf_get_u32(arm
->pc
->value
, 0, 32);
350 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
351 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
352 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
355 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); /* add r0,pc,#1 */
356 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
357 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
358 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
360 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
361 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
362 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
364 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, r0
, NULL
, 0);
365 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
366 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
369 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
370 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
372 arm7_9
->need_bypass_before_restart
= 1;
375 static int feroceon_read_cp15(struct target
*target
, uint32_t op1
,
376 uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
378 struct arm
*arm
= target
->arch_info
;
379 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
380 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
383 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
384 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
385 err
= arm7_9_execute_sys_speed(target
);
389 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 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);
392 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 0);
393 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
394 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
395 return jtag_execute_queue();
398 static int feroceon_write_cp15(struct target
*target
, uint32_t op1
,
399 uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
401 struct arm
*arm
= target
->arch_info
;
402 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
403 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
405 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 0);
406 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
407 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
408 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, NULL
, 0);
409 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
410 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
411 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
413 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
414 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
415 return arm7_9_execute_sys_speed(target
);
418 static void feroceon_set_dbgrq(struct target
*target
)
420 struct arm
*arm
= target
->arch_info
;
421 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
422 struct reg
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
424 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
425 embeddedice_store_reg(dbg_ctrl
);
428 static void feroceon_enable_single_step(struct target
*target
, uint32_t next_pc
)
430 struct arm
*arm
= target
->arch_info
;
431 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
433 /* set a breakpoint there */
434 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
435 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
436 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
437 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
438 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
441 static void feroceon_disable_single_step(struct target
*target
)
443 struct arm
*arm
= target
->arch_info
;
444 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
446 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
447 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
448 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
449 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
450 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
453 static int feroceon_examine_debug_reason(struct target
*target
)
455 /* the MOE is not implemented */
456 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
457 target
->debug_reason
= DBG_REASON_DBGRQ
;
462 static int feroceon_bulk_write_memory(struct target
*target
,
463 target_addr_t address
, uint32_t count
, const uint8_t *buffer
)
466 struct arm
*arm
= target
->arch_info
;
467 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
468 enum arm_state core_state
= arm
->core_state
;
469 uint32_t x
, flip
, shift
, save
[7];
473 * We can't use the dcc flow control bits, so let's transfer data
474 * with 31 bits and flip the MSB each time a new data word is sent.
476 static uint32_t dcc_code
[] = {
477 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
478 0xe3a0301e, /* 1: mov r3, #30 */
479 0xe3a04002, /* mov r4, #2 */
480 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
481 0xe1310005, /* teq r1, r5 */
482 0x0afffffc, /* beq 1b */
483 0xe1a05001, /* mov r5, r1 */
484 0xe1a01081, /* mov r1, r1, lsl #1 */
485 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
486 0xe1320005, /* teq r2, r5 */
487 0x0afffffc, /* beq 3b */
488 0xe1a05002, /* mov r5, r2 */
489 0xe3c22102, /* bic r2, r2, #0x80000000 */
490 0xe1811332, /* orr r1, r1, r2, lsr r3 */
491 0xe2533001, /* subs r3, r3, #1 */
492 0xe4801004, /* str r1, [r0], #4 */
493 0xe1a01412, /* mov r1, r2, lsl r4 */
494 0xe2844001, /* add r4, r4, #1 */
495 0x4affffed, /* bmi 1b */
496 0xeafffff3, /* b 3b */
499 uint32_t dcc_size
= sizeof(dcc_code
);
501 if (address
% 4 != 0)
502 return ERROR_TARGET_UNALIGNED_ACCESS
;
504 if (!arm7_9
->dcc_downloads
)
505 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
507 /* regrab previously allocated working_area, or allocate a new one */
508 if (!arm7_9
->dcc_working_area
) {
509 uint8_t dcc_code_buf
[dcc_size
];
511 /* make sure we have a working area */
512 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
) {
513 LOG_INFO("no working area available, falling back to memory writes");
514 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
517 /* copy target instructions to target endianness */
518 target_buffer_set_u32_array(target
, dcc_code_buf
, ARRAY_SIZE(dcc_code
), dcc_code
);
520 /* write DCC code to working area, using the non-optimized
521 * memory write to avoid ending up here again */
522 retval
= arm7_9_write_memory_no_opt(target
,
523 arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
);
524 if (retval
!= ERROR_OK
)
528 /* backup clobbered processor state */
529 for (i
= 0; i
<= 5; i
++)
530 save
[i
] = buf_get_u32(arm
->core_cache
->reg_list
[i
].value
, 0, 32);
531 save
[i
] = buf_get_u32(arm
->pc
->value
, 0, 32);
533 /* set up target address in r0 */
534 buf_set_u32(arm
->core_cache
->reg_list
[0].value
, 0, 32, address
);
535 arm
->core_cache
->reg_list
[0].valid
= true;
536 arm
->core_cache
->reg_list
[0].dirty
= true;
537 arm
->core_state
= ARM_STATE_ARM
;
539 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
540 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
546 for (i
= 0; i
< count
; i
++) {
547 uint32_t y
= target_buffer_get_u32(target
, buffer
);
548 uint32_t z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
549 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
550 x
= y
<< (32 - shift
);
551 if (++shift
>= 32 || i
+ 1 >= count
) {
552 z
= (x
>> 1) | (flip
^= 0x80000000);
553 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
560 retval
= target_halt(target
);
561 if (retval
== ERROR_OK
)
562 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
563 if (retval
== ERROR_OK
) {
564 uint32_t endaddress
=
565 buf_get_u32(arm
->core_cache
->reg_list
[0].value
, 0, 32);
566 if (endaddress
!= address
+ count
*4) {
567 LOG_ERROR("DCC write failed,"
568 " expected end address 0x%08" TARGET_PRIxADDR
569 " got 0x%0" PRIx32
"",
570 address
+ count
*4, endaddress
);
575 /* restore target state */
576 for (i
= 0; i
<= 5; i
++) {
577 buf_set_u32(arm
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
578 arm
->core_cache
->reg_list
[i
].valid
= true;
579 arm
->core_cache
->reg_list
[i
].dirty
= true;
581 buf_set_u32(arm
->pc
->value
, 0, 32, save
[i
]);
582 arm
->pc
->valid
= true;
583 arm
->pc
->dirty
= true;
584 arm
->core_state
= core_state
;
589 static int feroceon_init_target(struct command_context
*cmd_ctx
,
590 struct target
*target
)
592 arm9tdmi_init_target(cmd_ctx
, target
);
596 static void feroceon_deinit_target(struct target
*target
)
598 arm9tdmi_deinit_target(target
);
601 static void feroceon_common_setup(struct target
*target
)
603 struct arm
*arm
= target
->arch_info
;
604 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
606 /* override some insn sequence functions */
607 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
608 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
609 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
610 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
611 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
612 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
613 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
614 arm7_9
->branch_resume
= feroceon_branch_resume
;
615 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
617 /* must be implemented with only one comparator */
618 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
619 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
621 arm7_9
->bulk_write_memory
= feroceon_bulk_write_memory
;
623 /* MOE is not implemented */
624 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
626 /* Note: asserting DBGRQ might not win over the undef exception.
627 If that happens then just use "arm7_9 dbgrq disable". */
628 arm7_9
->use_dbgrq
= 1;
629 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
631 /* only one working comparator */
632 arm7_9
->wp_available_max
= 1;
633 arm7_9
->wp1_used_default
= -1;
636 static int feroceon_target_create(struct target
*target
, Jim_Interp
*interp
)
638 struct arm926ejs_common
*arm926ejs
= calloc(1, sizeof(struct arm926ejs_common
));
640 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
641 feroceon_common_setup(target
);
643 struct arm
*arm
= target
->arch_info
;
644 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
645 arm7_9
->write_memory
= arm926ejs_write_memory
;
647 /* the standard ARM926 methods don't always work (don't ask...) */
648 arm926ejs
->read_cp15
= feroceon_read_cp15
;
649 arm926ejs
->write_cp15
= feroceon_write_cp15
;
654 static int dragonite_target_create(struct target
*target
, Jim_Interp
*interp
)
656 struct arm966e_common
*arm966e
= calloc(1, sizeof(struct arm966e_common
));
658 arm966e_init_arch_info(target
, arm966e
, target
->tap
);
659 feroceon_common_setup(target
);
661 struct arm
*arm
= target
->arch_info
;
662 struct arm7_9_common
*arm7_9
= arm
->arch_info
;
663 arm7_9
->write_memory
= arm7_9_write_memory
;
668 static int feroceon_examine(struct target
*target
)
671 struct arm7_9_common
*arm7_9
;
674 retval
= arm7_9_examine(target
);
675 if (retval
!= ERROR_OK
)
678 arm
= target
->arch_info
;
679 arm7_9
= arm
->arch_info
;
681 /* the COMMS_CTRL bits are all contiguous */
682 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
683 LOG_ERROR("unexpected Feroceon EICE version signature");
685 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
686 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
687 arm7_9
->has_monitor_mode
= 1;
689 /* vector catch reg is not initialized on reset */
690 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
692 /* clear monitor mode, enable comparators */
693 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
694 jtag_execute_queue();
695 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
696 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
697 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
702 struct target_type feroceon_target
= {
706 .arch_state
= arm926ejs_arch_state
,
708 .target_request_data
= arm7_9_target_request_data
,
711 .resume
= arm7_9_resume
,
714 .assert_reset
= feroceon_assert_reset
,
715 .deassert_reset
= arm7_9_deassert_reset
,
716 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
718 .get_gdb_arch
= arm_get_gdb_arch
,
719 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
721 .read_memory
= arm7_9_read_memory
,
722 .write_memory
= arm7_9_write_memory_opt
,
724 .checksum_memory
= arm_checksum_memory
,
725 .blank_check_memory
= arm_blank_check_memory
,
727 .run_algorithm
= armv4_5_run_algorithm
,
729 .add_breakpoint
= arm7_9_add_breakpoint
,
730 .remove_breakpoint
= arm7_9_remove_breakpoint
,
731 .add_watchpoint
= arm7_9_add_watchpoint
,
732 .remove_watchpoint
= arm7_9_remove_watchpoint
,
734 .commands
= arm926ejs_command_handlers
,
735 .target_create
= feroceon_target_create
,
736 .init_target
= feroceon_init_target
,
737 .deinit_target
= feroceon_deinit_target
,
738 .examine
= feroceon_examine
,
741 struct target_type dragonite_target
= {
745 .arch_state
= arm_arch_state
,
747 .target_request_data
= arm7_9_target_request_data
,
750 .resume
= arm7_9_resume
,
753 .assert_reset
= feroceon_assert_reset
,
754 .deassert_reset
= arm7_9_deassert_reset
,
755 .soft_reset_halt
= arm7_9_soft_reset_halt
,
757 .get_gdb_arch
= arm_get_gdb_arch
,
758 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
760 .read_memory
= arm7_9_read_memory
,
761 .write_memory
= arm7_9_write_memory_opt
,
763 .checksum_memory
= arm_checksum_memory
,
764 .blank_check_memory
= arm_blank_check_memory
,
766 .run_algorithm
= armv4_5_run_algorithm
,
768 .add_breakpoint
= arm7_9_add_breakpoint
,
769 .remove_breakpoint
= arm7_9_remove_breakpoint
,
770 .add_watchpoint
= arm7_9_add_watchpoint
,
771 .remove_watchpoint
= arm7_9_remove_watchpoint
,
773 .commands
= arm966e_command_handlers
,
774 .target_create
= dragonite_target_create
,
775 .init_target
= feroceon_init_target
,
776 .examine
= feroceon_examine
,
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)