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].tap
= jtag_info
->tap
;
93 fields
[0].num_bits
= 32;
94 fields
[0].out_value
= out_buf
;
95 fields
[0].in_value
= NULL
;
97 fields
[1].tap
= jtag_info
->tap
;
98 fields
[1].num_bits
= 3;
99 fields
[1].out_value
= &sysspeed_buf
;
100 fields
[1].in_value
= NULL
;
102 fields
[2].tap
= jtag_info
->tap
;
103 fields
[2].num_bits
= 32;
104 fields
[2].out_value
= instr_buf
;
105 fields
[2].in_value
= NULL
;
107 jtag_add_dr_scan(3, fields
, jtag_get_end_state());
109 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
114 void feroceon_change_to_arm(struct target
*target
, uint32_t *r0
, uint32_t *pc
)
116 struct arm
*armv4_5
= target
->arch_info
;
117 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
118 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
121 * save r0 before using it and put system in ARM state
122 * to allow common handling of ARM and THUMB debugging
125 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
126 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
127 feroceon_dummy_clock_out(jtag_info
, ARMV4_5_T_NOP
);
129 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 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);
132 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, r0
, 0);
133 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
134 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
136 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_MOV(0, 15), 0, NULL
, 0);
137 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_STR(0, 0), 0, NULL
, 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);
140 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, pc
, 0);
141 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
142 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
144 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_BX(15), 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, NULL
, 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 jtag_execute_queue();
153 * fix program counter:
154 * MOV R0, PC was the 7th instruction (+12)
155 * reading PC in Thumb state gives address of instruction + 4
160 void feroceon_read_core_regs(struct target
*target
, uint32_t mask
, uint32_t* core_regs
[16])
163 struct arm
*armv4_5
= target
->arch_info
;
164 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
165 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
167 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
168 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
169 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
171 for (i
= 0; i
<= 15; i
++)
173 arm9tdmi_clock_data_in(jtag_info
, core_regs
[i
]);
175 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
176 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
179 void feroceon_read_core_regs_target_buffer(struct target
*target
, uint32_t mask
, void* buffer
, int size
)
182 struct arm
*armv4_5
= target
->arch_info
;
183 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
184 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
185 int be
= (target
->endianness
== TARGET_BIG_ENDIAN
) ? 1 : 0;
186 uint32_t *buf_u32
= buffer
;
187 uint16_t *buf_u16
= buffer
;
188 uint8_t *buf_u8
= buffer
;
190 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, mask
& 0xffff, 0, 0), 0, NULL
, 0);
191 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
192 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
194 for (i
= 0; i
<= 15; i
++)
196 if (mask
& (1 << i
)) {
200 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u32
++, 4, be
);
203 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u16
++, 2, be
);
206 arm9tdmi_clock_data_in_endianness(jtag_info
, buf_u8
++, 1, be
);
212 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
213 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
216 void feroceon_read_xpsr(struct target
*target
, uint32_t *xpsr
, int spsr
)
218 struct arm
*armv4_5
= target
->arch_info
;
219 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
220 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
222 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRS(0, spsr
& 1), 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);
226 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
227 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
228 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
230 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 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);
233 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, xpsr
, 0);
235 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
236 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
239 void feroceon_write_xpsr(struct target
*target
, uint32_t xpsr
, int spsr
)
241 struct arm
*armv4_5
= target
->arch_info
;
242 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
243 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
245 LOG_DEBUG("xpsr: %8.8" PRIx32
", spsr: %i", xpsr
, spsr
);
247 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr
& 0xff, 0, 1, spsr
), 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);
251 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
252 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
253 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
255 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff00) >> 8, 0xc, 2, spsr
), 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);
260 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
261 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
263 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff0000) >> 16, 0x8, 4, spsr
), 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);
269 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
271 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM((xpsr
& 0xff000000) >> 24, 0x4, 8, spsr
), 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);
276 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
277 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
280 void feroceon_write_xpsr_im8(struct target
*target
, uint8_t xpsr_im
, int rot
, int spsr
)
282 struct arm
*armv4_5
= target
->arch_info
;
283 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
284 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
286 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im
, rot
, spsr
);
288 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MSR_IM(xpsr_im
, rot
, 1, spsr
), 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);
294 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
297 void feroceon_write_core_regs(struct target
*target
, uint32_t mask
, uint32_t core_regs
[16])
300 struct arm
*armv4_5
= target
->arch_info
;
301 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
302 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
304 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, mask
& 0xffff, 0, 0), 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);
308 for (i
= 0; i
<= 15; i
++)
310 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, core_regs
[i
], 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);
317 void feroceon_branch_resume(struct target
*target
)
319 struct arm
*armv4_5
= target
->arch_info
;
320 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
321 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
323 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
324 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
325 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
326 arm9tdmi_clock_out(jtag_info
, ARMV4_5_B(0xfffff9, 0), 0, NULL
, 0);
327 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
329 arm7_9
->need_bypass_before_restart
= 1;
332 void feroceon_branch_resume_thumb(struct target
*target
)
336 struct arm
*armv4_5
= target
->arch_info
;
337 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
338 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
339 uint32_t r0
= buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
340 uint32_t pc
= buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
342 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
343 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 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);
347 arm9tdmi_clock_out(jtag_info
, 0xE28F0001, 0, NULL
, 0); // add r0,pc,#1
348 arm9tdmi_clock_out(jtag_info
, ARMV4_5_BX(0), 0, NULL
, 0);
349 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
350 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 0);
352 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL
, 0);
353 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
354 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
356 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, r0
, NULL
, 0);
357 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
358 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 0);
361 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_B(0x7e9 + pc
), 0, NULL
, 0);
362 arm9tdmi_clock_out(jtag_info
, ARMV4_5_T_NOP
, 0, NULL
, 1);
364 arm7_9
->need_bypass_before_restart
= 1;
367 int feroceon_read_cp15(struct target
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t *value
)
369 struct arm
*armv4_5
= target
->arch_info
;
370 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
371 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
374 arm9tdmi_clock_out(jtag_info
, ARMV4_5_MRC(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
375 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
376 err
= arm7_9_execute_sys_speed(target
);
380 arm9tdmi_clock_out(jtag_info
, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL
, 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 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, value
, 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 return jtag_execute_queue();
389 int feroceon_write_cp15(struct target
*target
, uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
, uint32_t value
)
391 struct arm
*armv4_5
= target
->arch_info
;
392 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
393 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
395 arm9tdmi_clock_out(jtag_info
, ARMV4_5_LDMIA(0, 1, 0, 0), 0, 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
, value
, 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
, ARMV4_5_MCR(15, op1
, 0, CRn
, CRm
, op2
), 0, NULL
, 0);
404 arm9tdmi_clock_out(jtag_info
, ARMV4_5_NOP
, 0, NULL
, 1);
405 return arm7_9_execute_sys_speed(target
);
408 void feroceon_set_dbgrq(struct target
*target
)
410 struct arm
*armv4_5
= target
->arch_info
;
411 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
412 struct reg
*dbg_ctrl
= &arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
];
414 buf_set_u32(dbg_ctrl
->value
, 0, 8, 2);
415 embeddedice_store_reg(dbg_ctrl
);
418 void feroceon_enable_single_step(struct target
*target
, uint32_t next_pc
)
420 struct arm
*armv4_5
= target
->arch_info
;
421 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
423 /* set a breakpoint there */
424 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
], next_pc
);
425 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
], 0);
426 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
], 0xffffffff);
427 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
], 0x100);
428 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
], 0xf7);
431 void feroceon_disable_single_step(struct target
*target
)
433 struct arm
*armv4_5
= target
->arch_info
;
434 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
436 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_VALUE
]);
437 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_ADDR_MASK
]);
438 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_DATA_MASK
]);
439 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_MASK
]);
440 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_W0_CONTROL_VALUE
]);
443 int feroceon_examine_debug_reason(struct target
*target
)
445 /* the MOE is not implemented */
446 if (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)
448 target
->debug_reason
= DBG_REASON_DBGRQ
;
454 int feroceon_bulk_write_memory(struct target
*target
, uint32_t address
, uint32_t count
, uint8_t *buffer
)
457 struct arm
*armv4_5
= target
->arch_info
;
458 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
459 enum arm_state core_state
= armv4_5
->core_state
;
460 uint32_t x
, flip
, shift
, save
[7];
464 * We can't use the dcc flow control bits, so let's transfer data
465 * with 31 bits and flip the MSB each time a new data word is sent.
467 static uint32_t dcc_code
[] =
469 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
470 0xe3a0301e, /* 1: mov r3, #30 */
471 0xe3a04002, /* mov r4, #2 */
472 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
473 0xe1310005, /* teq r1, r5 */
474 0x0afffffc, /* beq 1b */
475 0xe1a05001, /* mov r5, r1 */
476 0xe1a01081, /* mov r1, r1, lsl #1 */
477 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
478 0xe1320005, /* teq r2, r5 */
479 0x0afffffc, /* beq 3b */
480 0xe1a05002, /* mov r5, r2 */
481 0xe3c22102, /* bic r2, r2, #0x80000000 */
482 0xe1811332, /* orr r1, r1, r2, lsr r3 */
483 0xe2533001, /* subs r3, r3, #1 */
484 0xe4801004, /* str r1, [r0], #4 */
485 0xe1a01412, /* mov r1, r2, lsl r4 */
486 0xe2844001, /* add r4, r4, #1 */
487 0x4affffed, /* bmi 1b */
488 0xeafffff3, /* b 3b */
491 uint32_t dcc_size
= sizeof(dcc_code
);
493 if (!arm7_9
->dcc_downloads
)
494 return target_write_memory(target
, address
, 4, count
, buffer
);
496 /* regrab previously allocated working_area, or allocate a new one */
497 if (!arm7_9
->dcc_working_area
)
499 uint8_t dcc_code_buf
[dcc_size
];
501 /* make sure we have a working area */
502 if (target_alloc_working_area(target
, dcc_size
, &arm7_9
->dcc_working_area
) != ERROR_OK
)
504 LOG_INFO("no working area available, falling back to memory writes");
505 return target_write_memory(target
, address
, 4, count
, buffer
);
508 /* copy target instructions to target endianness */
509 for (i
= 0; i
< dcc_size
/4; i
++)
510 target_buffer_set_u32(target
, dcc_code_buf
+ i
*4, dcc_code
[i
]);
512 /* write DCC code to working area */
513 if ((retval
= target_write_memory(target
, arm7_9
->dcc_working_area
->address
, 4, dcc_size
/4, dcc_code_buf
)) != ERROR_OK
)
519 /* backup clobbered processor state */
520 for (i
= 0; i
<= 5; i
++)
521 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32);
522 save
[i
] = buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32);
524 /* set up target address in r0 */
525 buf_set_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32, address
);
526 armv4_5
->core_cache
->reg_list
[0].valid
= 1;
527 armv4_5
->core_cache
->reg_list
[0].dirty
= 1;
528 armv4_5
->core_state
= ARM_STATE_ARM
;
530 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], 0);
531 arm7_9_resume(target
, 0, arm7_9
->dcc_working_area
->address
, 1, 1);
537 for (i
= 0; i
< count
; i
++)
539 uint32_t y
= target_buffer_get_u32(target
, buffer
);
540 uint32_t z
= (x
>> 1) | (y
>> shift
) | (flip
^= 0x80000000);
541 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
542 x
= y
<< (32 - shift
);
543 if (++shift
>= 32 || i
+ 1 >= count
)
545 z
= (x
>> 1) | (flip
^= 0x80000000);
546 embeddedice_write_reg(&arm7_9
->eice_cache
->reg_list
[EICE_COMMS_DATA
], z
);
553 retval
= target_halt(target
);
554 if (retval
== ERROR_OK
)
555 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
556 if (retval
== ERROR_OK
) {
557 uint32_t endaddress
=
558 buf_get_u32(armv4_5
->core_cache
->reg_list
[0].value
, 0, 32);
559 if (endaddress
!= address
+ count
*4) {
560 LOG_ERROR("DCC write failed,"
561 " expected end address 0x%08" PRIx32
562 " got 0x%0" PRIx32
"",
563 address
+ count
*4, endaddress
);
568 /* restore target state */
569 for (i
= 0; i
<= 5; i
++)
571 buf_set_u32(armv4_5
->core_cache
->reg_list
[i
].value
, 0, 32, save
[i
]);
572 armv4_5
->core_cache
->reg_list
[i
].valid
= 1;
573 armv4_5
->core_cache
->reg_list
[i
].dirty
= 1;
575 buf_set_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32, save
[i
]);
576 armv4_5
->core_cache
->reg_list
[15].valid
= 1;
577 armv4_5
->core_cache
->reg_list
[15].dirty
= 1;
578 armv4_5
->core_state
= core_state
;
583 int feroceon_init_target(struct command_context
*cmd_ctx
, struct target
*target
)
585 arm9tdmi_init_target(cmd_ctx
, target
);
589 void feroceon_common_setup(struct target
*target
)
591 struct arm
*armv4_5
= target
->arch_info
;
592 struct arm7_9_common
*arm7_9
= armv4_5
->arch_info
;
594 /* override some insn sequence functions */
595 arm7_9
->change_to_arm
= feroceon_change_to_arm
;
596 arm7_9
->read_core_regs
= feroceon_read_core_regs
;
597 arm7_9
->read_core_regs_target_buffer
= feroceon_read_core_regs_target_buffer
;
598 arm7_9
->read_xpsr
= feroceon_read_xpsr
;
599 arm7_9
->write_xpsr
= feroceon_write_xpsr
;
600 arm7_9
->write_xpsr_im8
= feroceon_write_xpsr_im8
;
601 arm7_9
->write_core_regs
= feroceon_write_core_regs
;
602 arm7_9
->branch_resume
= feroceon_branch_resume
;
603 arm7_9
->branch_resume_thumb
= feroceon_branch_resume_thumb
;
605 /* must be implemented with only one comparator */
606 arm7_9
->enable_single_step
= feroceon_enable_single_step
;
607 arm7_9
->disable_single_step
= feroceon_disable_single_step
;
609 /* MOE is not implemented */
610 arm7_9
->examine_debug_reason
= feroceon_examine_debug_reason
;
612 /* Note: asserting DBGRQ might not win over the undef exception.
613 If that happens then just use "arm7_9 dbgrq disable". */
614 arm7_9
->use_dbgrq
= 1;
615 arm7_9
->set_special_dbgrq
= feroceon_set_dbgrq
;
617 /* only one working comparator */
618 arm7_9
->wp_available_max
= 1;
619 arm7_9
->wp1_used_default
= -1;
622 int feroceon_target_create(struct target
*target
, Jim_Interp
*interp
)
624 struct arm926ejs_common
*arm926ejs
= calloc(1,sizeof(struct arm926ejs_common
));
626 arm926ejs_init_arch_info(target
, arm926ejs
, target
->tap
);
627 feroceon_common_setup(target
);
629 /* the standard ARM926 methods don't always work (don't ask...) */
630 arm926ejs
->read_cp15
= feroceon_read_cp15
;
631 arm926ejs
->write_cp15
= feroceon_write_cp15
;
636 int dragonite_target_create(struct target
*target
, Jim_Interp
*interp
)
638 struct arm966e_common
*arm966e
= calloc(1,sizeof(struct arm966e_common
));
640 arm966e_init_arch_info(target
, arm966e
, target
->tap
);
641 feroceon_common_setup(target
);
646 int feroceon_examine(struct target
*target
)
649 struct arm7_9_common
*arm7_9
;
652 retval
= arm7_9_examine(target
);
653 if (retval
!= ERROR_OK
)
656 armv4_5
= target
->arch_info
;
657 arm7_9
= armv4_5
->arch_info
;
659 /* the COMMS_CTRL bits are all contiguous */
660 if (buf_get_u32(arm7_9
->eice_cache
->reg_list
[EICE_COMMS_CTRL
].value
, 2, 4) != 6)
661 LOG_ERROR("unexpected Feroceon EICE version signature");
663 arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].size
= 6;
664 arm7_9
->eice_cache
->reg_list
[EICE_DBG_STAT
].size
= 5;
665 arm7_9
->has_monitor_mode
= 1;
667 /* vector catch reg is not initialized on reset */
668 embeddedice_set_reg(&arm7_9
->eice_cache
->reg_list
[EICE_VEC_CATCH
], 0);
670 /* clear monitor mode, enable comparators */
671 embeddedice_read_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
672 jtag_execute_queue();
673 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 4, 1, 0);
674 buf_set_u32(arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
].value
, 5, 1, 0);
675 embeddedice_store_reg(&arm7_9
->eice_cache
->reg_list
[EICE_DBG_CTRL
]);
680 struct target_type feroceon_target
=
685 .arch_state
= arm926ejs_arch_state
,
687 .target_request_data
= arm7_9_target_request_data
,
690 .resume
= arm7_9_resume
,
693 .assert_reset
= feroceon_assert_reset
,
694 .deassert_reset
= arm7_9_deassert_reset
,
695 .soft_reset_halt
= arm926ejs_soft_reset_halt
,
697 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
699 .read_memory
= arm7_9_read_memory
,
700 .write_memory
= arm926ejs_write_memory
,
701 .bulk_write_memory
= feroceon_bulk_write_memory
,
703 .checksum_memory
= arm_checksum_memory
,
704 .blank_check_memory
= arm_blank_check_memory
,
706 .run_algorithm
= armv4_5_run_algorithm
,
708 .add_breakpoint
= arm7_9_add_breakpoint
,
709 .remove_breakpoint
= arm7_9_remove_breakpoint
,
710 .add_watchpoint
= arm7_9_add_watchpoint
,
711 .remove_watchpoint
= arm7_9_remove_watchpoint
,
713 .commands
= arm926ejs_command_handlers
,
714 .target_create
= feroceon_target_create
,
715 .init_target
= feroceon_init_target
,
716 .examine
= feroceon_examine
,
719 struct target_type dragonite_target
=
724 .arch_state
= arm_arch_state
,
726 .target_request_data
= arm7_9_target_request_data
,
729 .resume
= arm7_9_resume
,
732 .assert_reset
= feroceon_assert_reset
,
733 .deassert_reset
= arm7_9_deassert_reset
,
734 .soft_reset_halt
= arm7_9_soft_reset_halt
,
736 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
738 .read_memory
= arm7_9_read_memory
,
739 .write_memory
= arm7_9_write_memory
,
740 .bulk_write_memory
= feroceon_bulk_write_memory
,
742 .checksum_memory
= arm_checksum_memory
,
743 .blank_check_memory
= arm_blank_check_memory
,
745 .run_algorithm
= armv4_5_run_algorithm
,
747 .add_breakpoint
= arm7_9_add_breakpoint
,
748 .remove_breakpoint
= arm7_9_remove_breakpoint
,
749 .add_watchpoint
= arm7_9_add_watchpoint
,
750 .remove_watchpoint
= arm7_9_remove_watchpoint
,
752 .commands
= arm966e_command_handlers
,
753 .target_create
= dragonite_target_create
,
754 .init_target
= feroceon_init_target
,
755 .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)