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

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)