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, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
25 * Marvell Feroceon/Dragonite support.
27 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
28 * mimics the ARM926 ICE interface with the following differences:
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.
47 * The Dragonite core is the non-mmu version based on the ARM966 model, and
48 * it shares the above issues as well.
55 #include "arm926ejs.h"
57 #include "target_type.h"
59 #include "arm_opcodes.h"
62 int feroceon_assert_reset(struct target
*target
)
64 struct arm
*armv4_5
= target
->arch_info
;
65 struct arm7_9_common
*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 int feroceon_dummy_clock_out(struct arm_jtag
*jtag_info
, uint32_t instr
)
77 struct scan_field fields
[3];
80 uint8_t sysspeed_buf
= 0x0;
83 buf_set_u32(out_buf
, 0, 32, 0);
85 buf_set_u32(instr_buf
, 0, 32, flip_u32(instr
, 32));
87 jtag_set_end_state(TAP_DRPAUSE
);
88 arm_jtag_scann(jtag_info
, 0x1);
90 arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
);
92 fields
[0].num_bits
= 32;
93 fields
[0].out_value
= out_buf
;
94 fields
[0].in_value
= NULL
;
96 fields
[1].num_bits
= 3;
97 fields
[1].out_value
= &sysspeed_buf
;
98 fields
[1].in_value
= NULL
;
100 fields
[2].num_bits
= 32;
101 fields
[2].out_value
= instr_buf
;
102 fields
[2].in_value
= NULL
;
104 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, jtag_get_end_state());
106 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
111 void feroceon_change_to_arm(struct target
*target
, uint32_t *r0
, uint32_t *pc
)
113 struct arm
*armv4_5
= target
->arch_info
;
114 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
115 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
118 * save r0 before using it and put system in ARM state
119 * to allow common handling of ARM and THUMB debugging
122 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
123 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
124 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
126 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
127 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
128 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
129 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
130 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
131 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
133 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
134 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 0);
135 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
136 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
137 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
138 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
139 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
141 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 0, NULL
, 0);
142 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
143 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 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);
147 jtag_execute_queue();
150 * fix program counter:
151 * MOV R0, PC was the 7th instruction (+12)
152 * reading PC in Thumb state gives address of instruction + 4
157 void feroceon_read_core_regs(struct target
*target
, uint32_t mask
, uint32_t* core_regs
[16])
160 struct arm
*armv4_5
= target
->arch_info
;
161 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
162 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
164 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
165 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
166 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
168 for (i
= 0; i
<= 15; i
++)
170 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
172 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
173 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
176 void feroceon_read_core_regs_target_buffer(struct target
*target
, uint32_t mask
, void* buffer
, int size
)
179 struct arm
*armv4_5
= target
->arch_info
;
180 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
181 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
182 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
183 uint32_t *buf_u32
= buffer
;
184 uint16_t *buf_u16
= buffer
;
185 uint8_t *buf_u8
= buffer
;
187 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
188 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
189 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
191 for (i
= 0; i
<= 15; i
++)
193 if (mask
& (1 << i
)) {
197 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
200 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
203 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
209 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
210 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
213 void feroceon_read_xpsr(struct target
*target
, uint32_t *xpsr
, int spsr
)
215 struct arm
*armv4_5
= target
->arch_info
;
216 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
217 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
219 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 0, NULL
, 0);
220 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
221 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 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);
224 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
225 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
227 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
228 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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, xpsr
, 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);
236 void feroceon_write_xpsr(struct target
*target
, uint32_t xpsr
, int spsr
)
238 struct arm
*armv4_5
= target
->arch_info
;
239 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
240 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
242 LOG_DEBUG("xpsr: %8.8" PRIx32
", spsr: %i", xpsr
, spsr
);
244 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 0, NULL
, 0);
245 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
246 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
247 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
248 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
249 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
250 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
252 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 0, NULL
, 0);
253 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
254 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
255 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
256 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
257 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
258 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
260 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 0, NULL
, 0);
261 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
262 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
263 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
264 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
265 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
266 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
268 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 0, NULL
, 0);
269 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
277 void feroceon_write_xpsr_im8(struct target
*target
, uint8_t xpsr_im
, int rot
, int spsr
)
279 struct arm
*armv4_5
= target
->arch_info
;
280 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
281 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
283 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
285 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 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, 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);
294 void feroceon_write_core_regs(struct target
*target
, uint32_t mask
, uint32_t core_regs
[16])
297 struct arm
*armv4_5
= target
->arch_info
;
298 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
299 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
301 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
302 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
303 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
305 for (i
= 0; i
<= 15; i
++)
307 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], NULL
, 0);
309 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
310 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
311 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
314 void feroceon_branch_resume(struct target
*target
)
316 struct arm
*armv4_5
= target
->arch_info
;
317 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
318 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
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_B(0xfffff9, 0), 0, NULL
, 0);
324 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
326 arm7_9
->need_bypass_before_restart
= 1;
329 void feroceon_branch_resume_thumb(struct target
*target
)
333 struct arm
*armv4_5
= target
->arch_info
;
334 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
335 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
336 uint32_t r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
337 uint32_t pc
= buf_get_u32(armv4_5
->pc
->value
, 0, 32);
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,pc,#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, 0x1), 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);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, r0
, NULL
, 0);
354 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
355 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
358 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
359 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
361 arm7_9
->need_bypass_before_restart
= 1;
364 int feroceon_read_cp15(struct target
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
366 struct arm
*armv4_5
= target
->arch_info
;
367 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
368 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
371 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
372 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
373 err
= arm7_9_execute_sys_speed(target
);
377 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 0);
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, value
, 0);
381 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
382 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
383 return jtag_execute_queue();
386 int feroceon_write_cp15(struct target
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
388 struct arm
*armv4_5
= target
->arch_info
;
389 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
390 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
392 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL
, 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, value
, NULL
, 0);
396 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, 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);
400 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
401 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
402 return arm7_9_execute_sys_speed(target
);
405 void feroceon_set_dbgrq(struct target
*target
)
407 struct arm
*armv4_5
= target
->arch_info
;
408 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
409 struct reg
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
411 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
412 embeddedice_store_reg(dbg_ctrl
);
415 void feroceon_enable_single_step(struct target
*target
, uint32_t next_pc
)
417 struct arm
*armv4_5
= target
->arch_info
;
418 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
420 /* set a breakpoint there */
421 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
422 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
423 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
424 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
425 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
428 void feroceon_disable_single_step(struct target
*target
)
430 struct arm
*armv4_5
= target
->arch_info
;
431 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
433 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
434 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
435 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
436 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
437 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
440 int feroceon_examine_debug_reason(struct target
*target
)
442 /* the MOE is not implemented */
443 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
445 target
->debug_reason
= DBG_REASON_DBGRQ
;
451 int feroceon_bulk_write_memory(struct target
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
)
454 struct arm
*armv4_5
= target
->arch_info
;
455 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
456 enum arm_state core_state
= armv4_5
->core_state
;
457 uint32_t x
, flip
, shift
, save
[7];
461 * We can't use the dcc flow control bits, so let's transfer data
462 * with 31 bits and flip the MSB each time a new data word is sent.
464 static uint32_t dcc_code
[] =
466 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
467 0xe3a0301e, /* 1: mov r3, #30 */
468 0xe3a04002, /* mov r4, #2 */
469 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
470 0xe1310005, /* teq r1, r5 */
471 0x0afffffc, /* beq 1b */
472 0xe1a05001, /* mov r5, r1 */
473 0xe1a01081, /* mov r1, r1, lsl #1 */
474 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
475 0xe1320005, /* teq r2, r5 */
476 0x0afffffc, /* beq 3b */
477 0xe1a05002, /* mov r5, r2 */
478 0xe3c22102, /* bic r2, r2, #0x80000000 */
479 0xe1811332, /* orr r1, r1, r2, lsr r3 */
480 0xe2533001, /* subs r3, r3, #1 */
481 0xe4801004, /* str r1, [r0], #4 */
482 0xe1a01412, /* mov r1, r2, lsl r4 */
483 0xe2844001, /* add r4, r4, #1 */
484 0x4affffed, /* bmi 1b */
485 0xeafffff3, /* b 3b */
488 uint32_t dcc_size
= sizeof(dcc_code
);
490 if (!arm7_9
->dcc_downloads
)
491 return target_write_memory(target
, address
, 4, count
, buffer
);
493 /* regrab previously allocated working_area, or allocate a new one */
494 if (!arm7_9
->dcc_working_area
)
496 uint8_t dcc_code_buf
[dcc_size
];
498 /* make sure we have a working area */
499 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
501 LOG_INFO("no working area available, falling back to memory writes");
502 return target_write_memory(target
, address
, 4, count
, buffer
);
505 /* copy target instructions to target endianness */
506 for (i
= 0; i
< dcc_size
/4; i
++)
507 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
509 /* write DCC code to working area */
510 if ((retval
= target_write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
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
->pc
->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
= ARM_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 uint32_t y
= target_buffer_get_u32(target
, buffer
);
537 uint32_t 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 retval
= target_halt(target
);
551 if (retval
== ERROR_OK
)
552 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
553 if (retval
== ERROR_OK
) {
554 uint32_t endaddress
=
555 buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
556 if (endaddress
!= address
+ count
*4) {
557 LOG_ERROR("DCC write failed,"
558 " expected end address 0x%08" PRIx32
559 " got 0x%0" PRIx32
"",
560 address
+ count
*4, endaddress
);
565 /* restore target state */
566 for (i
= 0; i
<= 5; i
++)
568 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
569 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
570 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
572 buf_set_u32(armv4_5
->pc
->value
, 0, 32, save
[i
]);
573 armv4_5
->pc
->valid
= 1;
574 armv4_5
->pc
->dirty
= 1;
575 armv4_5
->core_state
= core_state
;
580 int feroceon_init_target(struct command_context
*cmd_ctx
, struct target
*target
)
582 arm9tdmi_init_target(cmd_ctx
, target
);
586 void feroceon_common_setup(struct target
*target
)
588 struct arm
*armv4_5
= target
->arch_info
;
589 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
591 /* override some insn sequence functions */
592 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
593 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
594 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
595 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
596 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
597 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
598 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
599 arm7_9
->branch_resume
= feroceon_branch_resume
;
600 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
602 /* must be implemented with only one comparator */
603 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
604 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
606 /* MOE is not implemented */
607 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
609 /* Note: asserting DBGRQ might not win over the undef exception.
610 If that happens then just use "arm7_9 dbgrq disable". */
611 arm7_9
->use_dbgrq
= 1;
612 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
614 /* only one working comparator */
615 arm7_9
->wp_available_max
= 1;
616 arm7_9
->wp1_used_default
= -1;
619 int feroceon_target_create(struct target
*target
, Jim_Interp
*interp
)
621 struct arm926ejs_common
*arm926ejs
= calloc(1,sizeof(struct arm926ejs_common
));
623 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
624 feroceon_common_setup(target
);
626 /* the standard ARM926 methods don't always work (don't ask...) */
627 arm926ejs
->read_cp15
= feroceon_read_cp15
;
628 arm926ejs
->write_cp15
= feroceon_write_cp15
;
633 int dragonite_target_create(struct target
*target
, Jim_Interp
*interp
)
635 struct arm966e_common
*arm966e
= calloc(1,sizeof(struct arm966e_common
));
637 arm966e_init_arch_info(target
, arm966e
, target
->tap
);
638 feroceon_common_setup(target
);
643 int feroceon_examine(struct target
*target
)
646 struct arm7_9_common
*arm7_9
;
649 retval
= arm7_9_examine(target
);
650 if (retval
!= ERROR_OK
)
653 armv4_5
= target
->arch_info
;
654 arm7_9
= armv4_5
->arch_info
;
656 /* the COMMS_CTRL bits are all contiguous */
657 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
658 LOG_ERROR("unexpected Feroceon EICE version signature");
660 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
661 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
662 arm7_9
->has_monitor_mode
= 1;
664 /* vector catch reg is not initialized on reset */
665 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
667 /* clear monitor mode, enable comparators */
668 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
669 jtag_execute_queue();
670 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
671 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
672 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
677 struct target_type feroceon_target
=
682 .arch_state
= arm926ejs_arch_state
,
684 .target_request_data
= arm7_9_target_request_data
,
687 .resume
= arm7_9_resume
,
690 .assert_reset
= feroceon_assert_reset
,
691 .deassert_reset
= arm7_9_deassert_reset
,
692 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
694 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
696 .read_memory
= arm7_9_read_memory
,
697 .write_memory
= arm926ejs_write_memory
,
698 .bulk_write_memory
= feroceon_bulk_write_memory
,
700 .checksum_memory
= arm_checksum_memory
,
701 .blank_check_memory
= arm_blank_check_memory
,
703 .run_algorithm
= armv4_5_run_algorithm
,
705 .add_breakpoint
= arm7_9_add_breakpoint
,
706 .remove_breakpoint
= arm7_9_remove_breakpoint
,
707 .add_watchpoint
= arm7_9_add_watchpoint
,
708 .remove_watchpoint
= arm7_9_remove_watchpoint
,
710 .commands
= arm926ejs_command_handlers
,
711 .target_create
= feroceon_target_create
,
712 .init_target
= feroceon_init_target
,
713 .examine
= feroceon_examine
,
716 struct target_type dragonite_target
=
721 .arch_state
= arm_arch_state
,
723 .target_request_data
= arm7_9_target_request_data
,
726 .resume
= arm7_9_resume
,
729 .assert_reset
= feroceon_assert_reset
,
730 .deassert_reset
= arm7_9_deassert_reset
,
731 .soft_reset_halt
= arm7_9_soft_reset_halt
,
733 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
735 .read_memory
= arm7_9_read_memory
,
736 .write_memory
= arm7_9_write_memory
,
737 .bulk_write_memory
= feroceon_bulk_write_memory
,
739 .checksum_memory
= arm_checksum_memory
,
740 .blank_check_memory
= arm_blank_check_memory
,
742 .run_algorithm
= armv4_5_run_algorithm
,
744 .add_breakpoint
= arm7_9_add_breakpoint
,
745 .remove_breakpoint
= arm7_9_remove_breakpoint
,
746 .add_watchpoint
= arm7_9_add_watchpoint
,
747 .remove_watchpoint
= arm7_9_remove_watchpoint
,
749 .commands
= arm966e_command_handlers
,
750 .target_create
= dragonite_target_create
,
751 .init_target
= feroceon_init_target
,
752 .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)