ARM: rename armv4_5_state_* as arm_state_*
[openocd.git] / src / target / feroceon.c
1 /***************************************************************************
2 * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
4 * *
5 * Copyright (C) 2008 by Hongtao Zheng *
6 * hontor@126.com *
7 * *
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. *
12 * *
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. *
17 * *
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 ***************************************************************************/
23
24 /*
25 * Marvell Feroceon/Dragonite support.
26 *
27 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
28 * mimics the ARM926 ICE interface with the following differences:
29 *
30 * - the MOE (method of entry) reporting is not implemented
31 *
32 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
33 *
34 * - due to a different pipeline implementation, some injected debug
35 * instruction sequences have to be somewhat different
36 *
37 * Other issues:
38 *
39 * - asserting DBGRQ doesn't work if target is looping on the undef vector
40 *
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
43 *
44 * - the DCC channel is half duplex (only one FIFO for both directions) with
45 * seemingly no proper flow control.
46 *
47 * The Dragonite core is the non-mmu version based on the ARM966 model, and
48 * it shares the above issues as well.
49 */
50
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #include "arm926ejs.h"
56 #include "arm966e.h"
57 #include "target_type.h"
58 #include "register.h"
59
60
61 int feroceon_assert_reset(struct target *target)
62 {
63 struct arm *armv4_5 = target->arch_info;
64 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
65 int ud = arm7_9->use_dbgrq;
66
67 arm7_9->use_dbgrq = 0;
68 if (target->reset_halt)
69 arm7_9_halt(target);
70 arm7_9->use_dbgrq = ud;
71 return arm7_9_assert_reset(target);
72 }
73
74 int feroceon_dummy_clock_out(struct arm_jtag *jtag_info, uint32_t instr)
75 {
76 struct scan_field fields[3];
77 uint8_t out_buf[4];
78 uint8_t instr_buf[4];
79 uint8_t sysspeed_buf = 0x0;
80
81 /* prepare buffer */
82 buf_set_u32(out_buf, 0, 32, 0);
83
84 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
85
86 jtag_set_end_state(TAP_DRPAUSE);
87 arm_jtag_scann(jtag_info, 0x1);
88
89 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
90
91 fields[0].tap = jtag_info->tap;
92 fields[0].num_bits = 32;
93 fields[0].out_value = out_buf;
94 fields[0].in_value = NULL;
95
96 fields[1].tap = jtag_info->tap;
97 fields[1].num_bits = 3;
98 fields[1].out_value = &sysspeed_buf;
99 fields[1].in_value = NULL;
100
101 fields[2].tap = jtag_info->tap;
102 fields[2].num_bits = 32;
103 fields[2].out_value = instr_buf;
104 fields[2].in_value = NULL;
105
106 jtag_add_dr_scan(3, fields, jtag_get_end_state());
107
108 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
109
110 return ERROR_OK;
111 }
112
113 void feroceon_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc)
114 {
115 struct arm *armv4_5 = target->arch_info;
116 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
117 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
118
119 /*
120 * save r0 before using it and put system in ARM state
121 * to allow common handling of ARM and THUMB debugging
122 */
123
124 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
125 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
126 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
127
128 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
129 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 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, r0, 0);
132 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
133 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
134
135 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
136 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 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, NULL, 0);
139 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
140 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
141 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
142
143 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 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, NULL, 0);
147 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
148
149 jtag_execute_queue();
150
151 /*
152 * fix program counter:
153 * MOV R0, PC was the 7th instruction (+12)
154 * reading PC in Thumb state gives address of instruction + 4
155 */
156 *pc -= (12 + 4);
157 }
158
159 void feroceon_read_core_regs(struct target *target, uint32_t mask, uint32_t* core_regs[16])
160 {
161 int i;
162 struct arm *armv4_5 = target->arch_info;
163 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
164 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
165
166 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
167 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
168 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
169
170 for (i = 0; i <= 15; i++)
171 if (mask & (1 << i))
172 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
173
174 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
175 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
176 }
177
178 void feroceon_read_core_regs_target_buffer(struct target *target, uint32_t mask, void* buffer, int size)
179 {
180 int i;
181 struct arm *armv4_5 = target->arch_info;
182 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
183 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
184 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
185 uint32_t *buf_u32 = buffer;
186 uint16_t *buf_u16 = buffer;
187 uint8_t *buf_u8 = buffer;
188
189 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
190 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
191 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
192
193 for (i = 0; i <= 15; i++)
194 {
195 if (mask & (1 << i)) {
196 switch (size)
197 {
198 case 4:
199 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
200 break;
201 case 2:
202 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
203 break;
204 case 1:
205 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
206 break;
207 }
208 }
209 }
210
211 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
212 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
213 }
214
215 void feroceon_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
216 {
217 struct arm *armv4_5 = target->arch_info;
218 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
219 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
220
221 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 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);
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
229 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 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, xpsr, 0);
233
234 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
235 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
236 }
237
238 void feroceon_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
239 {
240 struct arm *armv4_5 = target->arch_info;
241 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
242 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
243
244 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
245
246 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 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);
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
254 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 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);
260 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
261
262 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 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);
269
270 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 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);
276 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
277 }
278
279 void feroceon_write_xpsr_im8(struct target *target, uint8_t xpsr_im, int rot, int spsr)
280 {
281 struct arm *armv4_5 = target->arch_info;
282 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
283 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
284
285 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
286
287 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 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);
294 }
295
296 void feroceon_write_core_regs(struct target *target, uint32_t mask, uint32_t core_regs[16])
297 {
298 int i;
299 struct arm *armv4_5 = target->arch_info;
300 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
301 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
302
303 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 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
307 for (i = 0; i <= 15; i++)
308 if (mask & (1 << i))
309 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
310
311 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
312 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
313 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
314 }
315
316 void feroceon_branch_resume(struct target *target)
317 {
318 struct arm *armv4_5 = target->arch_info;
319 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
320 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
321
322 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
323 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
324 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
325 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
326 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
327
328 arm7_9->need_bypass_before_restart = 1;
329 }
330
331 void feroceon_branch_resume_thumb(struct target *target)
332 {
333 LOG_DEBUG("-");
334
335 struct arm *armv4_5 = target->arch_info;
336 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
337 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
338 uint32_t r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
339 uint32_t pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
340
341 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
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
346 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); // add r0,pc,#1
347 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
348 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
349 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
350
351 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0);
352 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
353 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
354
355 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, NULL, 0);
356 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
357 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
358
359 pc = (pc & 2) >> 1;
360 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
361 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
362
363 arm7_9->need_bypass_before_restart = 1;
364 }
365
366 int feroceon_read_cp15(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
367 {
368 struct arm *armv4_5 = target->arch_info;
369 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
370 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
371 int err;
372
373 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
374 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
375 err = arm7_9_execute_sys_speed(target);
376 if (err != ERROR_OK)
377 return err;
378
379 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
380 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 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, value, 0);
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 return jtag_execute_queue();
386 }
387
388 int feroceon_write_cp15(struct target *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
389 {
390 struct arm *armv4_5 = target->arch_info;
391 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
392 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
393
394 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
395 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
396 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
397 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0);
398 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
399 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
400 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
401
402 arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
403 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
404 return arm7_9_execute_sys_speed(target);
405 }
406
407 void feroceon_set_dbgrq(struct target *target)
408 {
409 struct arm *armv4_5 = target->arch_info;
410 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
411 struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
412
413 buf_set_u32(dbg_ctrl->value, 0, 8, 2);
414 embeddedice_store_reg(dbg_ctrl);
415 }
416
417 void feroceon_enable_single_step(struct target *target, uint32_t next_pc)
418 {
419 struct arm *armv4_5 = target->arch_info;
420 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
421
422 /* set a breakpoint there */
423 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
424 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
425 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
426 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
427 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
428 }
429
430 void feroceon_disable_single_step(struct target *target)
431 {
432 struct arm *armv4_5 = target->arch_info;
433 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
434
435 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
436 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
437 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
438 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
439 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
440 }
441
442 int feroceon_examine_debug_reason(struct target *target)
443 {
444 /* the MOE is not implemented */
445 if (target->debug_reason != DBG_REASON_SINGLESTEP)
446 {
447 target->debug_reason = DBG_REASON_DBGRQ;
448 }
449
450 return ERROR_OK;
451 }
452
453 int feroceon_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer)
454 {
455 int retval;
456 struct arm *armv4_5 = target->arch_info;
457 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
458 enum arm_state core_state = armv4_5->core_state;
459 uint32_t x, flip, shift, save[7];
460 uint32_t i;
461
462 /*
463 * We can't use the dcc flow control bits, so let's transfer data
464 * with 31 bits and flip the MSB each time a new data word is sent.
465 */
466 static uint32_t dcc_code[] =
467 {
468 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
469 0xe3a0301e, /* 1: mov r3, #30 */
470 0xe3a04002, /* mov r4, #2 */
471 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
472 0xe1310005, /* teq r1, r5 */
473 0x0afffffc, /* beq 1b */
474 0xe1a05001, /* mov r5, r1 */
475 0xe1a01081, /* mov r1, r1, lsl #1 */
476 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
477 0xe1320005, /* teq r2, r5 */
478 0x0afffffc, /* beq 3b */
479 0xe1a05002, /* mov r5, r2 */
480 0xe3c22102, /* bic r2, r2, #0x80000000 */
481 0xe1811332, /* orr r1, r1, r2, lsr r3 */
482 0xe2533001, /* subs r3, r3, #1 */
483 0xe4801004, /* str r1, [r0], #4 */
484 0xe1a01412, /* mov r1, r2, lsl r4 */
485 0xe2844001, /* add r4, r4, #1 */
486 0x4affffed, /* bmi 1b */
487 0xeafffff3, /* b 3b */
488 };
489
490 uint32_t dcc_size = sizeof(dcc_code);
491
492 if (!arm7_9->dcc_downloads)
493 return target_write_memory(target, address, 4, count, buffer);
494
495 /* regrab previously allocated working_area, or allocate a new one */
496 if (!arm7_9->dcc_working_area)
497 {
498 uint8_t dcc_code_buf[dcc_size];
499
500 /* make sure we have a working area */
501 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
502 {
503 LOG_INFO("no working area available, falling back to memory writes");
504 return target_write_memory(target, address, 4, count, buffer);
505 }
506
507 /* copy target instructions to target endianness */
508 for (i = 0; i < dcc_size/4; i++)
509 target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
510
511 /* write DCC code to working area */
512 if ((retval = target_write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf)) != ERROR_OK)
513 {
514 return retval;
515 }
516 }
517
518 /* backup clobbered processor state */
519 for (i = 0; i <= 5; i++)
520 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32);
521 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
522
523 /* set up target address in r0 */
524 buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
525 armv4_5->core_cache->reg_list[0].valid = 1;
526 armv4_5->core_cache->reg_list[0].dirty = 1;
527 armv4_5->core_state = ARM_STATE_ARM;
528
529 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
530 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
531
532 /* send data over */
533 x = 0;
534 flip = 0;
535 shift = 1;
536 for (i = 0; i < count; i++)
537 {
538 uint32_t y = target_buffer_get_u32(target, buffer);
539 uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
540 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
541 x = y << (32 - shift);
542 if (++shift >= 32 || i + 1 >= count)
543 {
544 z = (x >> 1) | (flip ^= 0x80000000);
545 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
546 x = 0;
547 shift = 1;
548 }
549 buffer += 4;
550 }
551
552 retval = target_halt(target);
553 if (retval == ERROR_OK)
554 retval = target_wait_state(target, TARGET_HALTED, 500);
555 if (retval == ERROR_OK) {
556 uint32_t endaddress =
557 buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
558 if (endaddress != address + count*4) {
559 LOG_ERROR("DCC write failed,"
560 " expected end address 0x%08" PRIx32
561 " got 0x%0" PRIx32 "",
562 address + count*4, endaddress);
563 retval = ERROR_FAIL;
564 }
565 }
566
567 /* restore target state */
568 for (i = 0; i <= 5; i++)
569 {
570 buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, save[i]);
571 armv4_5->core_cache->reg_list[i].valid = 1;
572 armv4_5->core_cache->reg_list[i].dirty = 1;
573 }
574 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, save[i]);
575 armv4_5->core_cache->reg_list[15].valid = 1;
576 armv4_5->core_cache->reg_list[15].dirty = 1;
577 armv4_5->core_state = core_state;
578
579 return retval;
580 }
581
582 int feroceon_init_target(struct command_context *cmd_ctx, struct target *target)
583 {
584 arm9tdmi_init_target(cmd_ctx, target);
585 return ERROR_OK;
586 }
587
588 void feroceon_common_setup(struct target *target)
589 {
590 struct arm *armv4_5 = target->arch_info;
591 struct arm7_9_common *arm7_9 = armv4_5->arch_info;
592
593 /* override some insn sequence functions */
594 arm7_9->change_to_arm = feroceon_change_to_arm;
595 arm7_9->read_core_regs = feroceon_read_core_regs;
596 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
597 arm7_9->read_xpsr = feroceon_read_xpsr;
598 arm7_9->write_xpsr = feroceon_write_xpsr;
599 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
600 arm7_9->write_core_regs = feroceon_write_core_regs;
601 arm7_9->branch_resume = feroceon_branch_resume;
602 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
603
604 /* must be implemented with only one comparator */
605 arm7_9->enable_single_step = feroceon_enable_single_step;
606 arm7_9->disable_single_step = feroceon_disable_single_step;
607
608 /* MOE is not implemented */
609 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
610
611 /* Note: asserting DBGRQ might not win over the undef exception.
612 If that happens then just use "arm7_9 dbgrq disable". */
613 arm7_9->use_dbgrq = 1;
614 arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
615
616 /* only one working comparator */
617 arm7_9->wp_available_max = 1;
618 arm7_9->wp1_used_default = -1;
619 }
620
621 int feroceon_target_create(struct target *target, Jim_Interp *interp)
622 {
623 struct arm926ejs_common *arm926ejs = calloc(1,sizeof(struct arm926ejs_common));
624
625 arm926ejs_init_arch_info(target, arm926ejs, target->tap);
626 feroceon_common_setup(target);
627
628 /* the standard ARM926 methods don't always work (don't ask...) */
629 arm926ejs->read_cp15 = feroceon_read_cp15;
630 arm926ejs->write_cp15 = feroceon_write_cp15;
631
632 return ERROR_OK;
633 }
634
635 int dragonite_target_create(struct target *target, Jim_Interp *interp)
636 {
637 struct arm966e_common *arm966e = calloc(1,sizeof(struct arm966e_common));
638
639 arm966e_init_arch_info(target, arm966e, target->tap);
640 feroceon_common_setup(target);
641
642 return ERROR_OK;
643 }
644
645 int feroceon_examine(struct target *target)
646 {
647 struct arm *armv4_5;
648 struct arm7_9_common *arm7_9;
649 int retval;
650
651 retval = arm7_9_examine(target);
652 if (retval != ERROR_OK)
653 return retval;
654
655 armv4_5 = target->arch_info;
656 arm7_9 = armv4_5->arch_info;
657
658 /* the COMMS_CTRL bits are all contiguous */
659 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
660 LOG_ERROR("unexpected Feroceon EICE version signature");
661
662 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
663 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
664 arm7_9->has_monitor_mode = 1;
665
666 /* vector catch reg is not initialized on reset */
667 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
668
669 /* clear monitor mode, enable comparators */
670 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
671 jtag_execute_queue();
672 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
673 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
674 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
675
676 return ERROR_OK;
677 }
678
679 struct target_type feroceon_target =
680 {
681 .name = "feroceon",
682
683 .poll = arm7_9_poll,
684 .arch_state = arm926ejs_arch_state,
685
686 .target_request_data = arm7_9_target_request_data,
687
688 .halt = arm7_9_halt,
689 .resume = arm7_9_resume,
690 .step = arm7_9_step,
691
692 .assert_reset = feroceon_assert_reset,
693 .deassert_reset = arm7_9_deassert_reset,
694 .soft_reset_halt = arm926ejs_soft_reset_halt,
695
696 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
697
698 .read_memory = arm7_9_read_memory,
699 .write_memory = arm926ejs_write_memory,
700 .bulk_write_memory = feroceon_bulk_write_memory,
701
702 .checksum_memory = arm_checksum_memory,
703 .blank_check_memory = arm_blank_check_memory,
704
705 .run_algorithm = armv4_5_run_algorithm,
706
707 .add_breakpoint = arm7_9_add_breakpoint,
708 .remove_breakpoint = arm7_9_remove_breakpoint,
709 .add_watchpoint = arm7_9_add_watchpoint,
710 .remove_watchpoint = arm7_9_remove_watchpoint,
711
712 .commands = arm926ejs_command_handlers,
713 .target_create = feroceon_target_create,
714 .init_target = feroceon_init_target,
715 .examine = feroceon_examine,
716 };
717
718 struct target_type dragonite_target =
719 {
720 .name = "dragonite",
721
722 .poll = arm7_9_poll,
723 .arch_state = armv4_5_arch_state,
724
725 .target_request_data = arm7_9_target_request_data,
726
727 .halt = arm7_9_halt,
728 .resume = arm7_9_resume,
729 .step = arm7_9_step,
730
731 .assert_reset = feroceon_assert_reset,
732 .deassert_reset = arm7_9_deassert_reset,
733 .soft_reset_halt = arm7_9_soft_reset_halt,
734
735 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
736
737 .read_memory = arm7_9_read_memory,
738 .write_memory = arm7_9_write_memory,
739 .bulk_write_memory = feroceon_bulk_write_memory,
740
741 .checksum_memory = arm_checksum_memory,
742 .blank_check_memory = arm_blank_check_memory,
743
744 .run_algorithm = armv4_5_run_algorithm,
745
746 .add_breakpoint = arm7_9_add_breakpoint,
747 .remove_breakpoint = arm7_9_remove_breakpoint,
748 .add_watchpoint = arm7_9_add_watchpoint,
749 .remove_watchpoint = arm7_9_remove_watchpoint,
750
751 .commands = arm966e_command_handlers,
752 .target_create = dragonite_target_create,
753 .init_target = feroceon_init_target,
754 .examine = feroceon_examine,
755 };
756

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)