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

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)