Nicolas Pitre <nico@cam.org> tighten error checking in bulk_write
[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 fields[0].in_value = NULL;
136
137 fields[1].tap = jtag_info->tap;
138 fields[1].num_bits = 3;
139 fields[1].out_value = &sysspeed_buf;
140 fields[1].in_value = NULL;
141
142 fields[2].tap = jtag_info->tap;
143 fields[2].num_bits = 32;
144 fields[2].out_value = instr_buf;
145 fields[2].in_value = NULL;
146
147 jtag_add_dr_scan(3, fields, jtag_get_end_state());
148
149 /* no jtag_add_runtest(0, jtag_get_end_state()) here */
150
151 return ERROR_OK;
152 }
153
154 void feroceon_change_to_arm(target_t *target, uint32_t *r0, uint32_t *pc)
155 {
156 armv4_5_common_t *armv4_5 = target->arch_info;
157 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
158 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
159
160 /*
161 * save r0 before using it and put system in ARM state
162 * to allow common handling of ARM and THUMB debugging
163 */
164
165 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
166 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
167 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
168
169 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
170 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
171 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
172 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
173 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
174 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
175
176 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
177 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
178 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
179 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
180 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
181 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
182 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
183
184 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 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, NULL, 0);
188 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
189
190 jtag_execute_queue();
191
192 /*
193 * fix program counter:
194 * MOV R0, PC was the 7th instruction (+12)
195 * reading PC in Thumb state gives address of instruction + 4
196 */
197 *pc -= (12 + 4);
198 }
199
200 void feroceon_read_core_regs(target_t *target, uint32_t mask, uint32_t* core_regs[16])
201 {
202 int i;
203 armv4_5_common_t *armv4_5 = target->arch_info;
204 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
205 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
206
207 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
208 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
209 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
210
211 for (i = 0; i <= 15; i++)
212 if (mask & (1 << i))
213 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
214
215 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
216 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
217 }
218
219 void feroceon_read_core_regs_target_buffer(target_t *target, uint32_t mask, void* buffer, int size)
220 {
221 int i;
222 armv4_5_common_t *armv4_5 = target->arch_info;
223 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
224 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
225 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
226 uint32_t *buf_u32 = buffer;
227 uint16_t *buf_u16 = buffer;
228 uint8_t *buf_u8 = buffer;
229
230 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 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
234 for (i = 0; i <= 15; i++)
235 {
236 if (mask & (1 << i)) {
237 switch (size)
238 {
239 case 4:
240 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
241 break;
242 case 2:
243 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
244 break;
245 case 1:
246 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
247 break;
248 }
249 }
250 }
251
252 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
253 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
254 }
255
256 void feroceon_read_xpsr(target_t *target, uint32_t *xpsr, int spsr)
257 {
258 armv4_5_common_t *armv4_5 = target->arch_info;
259 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
260 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
261
262 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 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_STMIA(0, 1, 0, 0), 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, xpsr, 0);
274
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(target_t *target, uint32_t xpsr, int spsr)
280 {
281 armv4_5_common_t *armv4_5 = target->arch_info;
282 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
283 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
284
285 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
286
287 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
296 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
297 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
298 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
299 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
300 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
301 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
302
303 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
310
311 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
318 }
319
320 void feroceon_write_xpsr_im8(target_t *target, uint8_t xpsr_im, int rot, int spsr)
321 {
322 armv4_5_common_t *armv4_5 = target->arch_info;
323 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
324 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
325
326 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
327
328 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
334 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
335 }
336
337 void feroceon_write_core_regs(target_t *target, uint32_t mask, uint32_t core_regs[16])
338 {
339 int i;
340 armv4_5_common_t *armv4_5 = target->arch_info;
341 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
342 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
343
344 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 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
348 for (i = 0; i <= 15; i++)
349 if (mask & (1 << i))
350 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
351
352 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
353 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
354 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
355 }
356
357 void feroceon_branch_resume(target_t *target)
358 {
359 armv4_5_common_t *armv4_5 = target->arch_info;
360 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
361 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
362
363 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
364 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
365 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
366 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
367 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
368
369 arm7_9->need_bypass_before_restart = 1;
370 }
371
372 void feroceon_branch_resume_thumb(target_t *target)
373 {
374 LOG_DEBUG("-");
375
376 armv4_5_common_t *armv4_5 = target->arch_info;
377 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
378 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
379 uint32_t r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
380 uint32_t pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
381 (void)(r0); // use R0...
382
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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
386 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
387
388 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); // add r0,pc,#1
389 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
390 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
391 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
392
393 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0);
394 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
395 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
396
397 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, pc, NULL, 0);
398 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
399 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
400
401 pc = (pc & 2) >> 1;
402 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
403 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
404
405 arm7_9->need_bypass_before_restart = 1;
406 }
407
408 int feroceon_read_cp15(target_t *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
409 {
410 armv4_5_common_t *armv4_5 = target->arch_info;
411 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
412 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
413 int err;
414
415 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
416 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
417 err = arm7_9_execute_sys_speed(target);
418 if (err != ERROR_OK)
419 return err;
420
421 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
422 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
423 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
424 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0);
425 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
426 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
427 return jtag_execute_queue();
428 }
429
430 int feroceon_write_cp15(target_t *target, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
431 {
432 armv4_5_common_t *armv4_5 = target->arch_info;
433 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
434 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
435
436 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(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, value, NULL, 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 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
443
444 arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
445 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
446 return arm7_9_execute_sys_speed(target);
447 }
448
449 void feroceon_set_dbgrq(target_t *target)
450 {
451 armv4_5_common_t *armv4_5 = target->arch_info;
452 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
453 reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
454
455 buf_set_u32(dbg_ctrl->value, 0, 8, 2);
456 embeddedice_store_reg(dbg_ctrl);
457 }
458
459 void feroceon_enable_single_step(target_t *target, uint32_t next_pc)
460 {
461 armv4_5_common_t *armv4_5 = target->arch_info;
462 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
463
464 /* set a breakpoint there */
465 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
466 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
467 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
468 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
469 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
470 }
471
472 void feroceon_disable_single_step(target_t *target)
473 {
474 armv4_5_common_t *armv4_5 = target->arch_info;
475 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
476
477 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
478 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
479 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
480 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
481 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
482 }
483
484 int feroceon_examine_debug_reason(target_t *target)
485 {
486 /* the MOE is not implemented */
487 if (target->debug_reason != DBG_REASON_SINGLESTEP)
488 {
489 target->debug_reason = DBG_REASON_DBGRQ;
490 }
491
492 return ERROR_OK;
493 }
494
495 int feroceon_bulk_write_memory(target_t *target, uint32_t address, uint32_t count, uint8_t *buffer)
496 {
497 int retval;
498 armv4_5_common_t *armv4_5 = target->arch_info;
499 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
500 enum armv4_5_state core_state = armv4_5->core_state;
501 uint32_t x, flip, shift, save[7];
502 uint32_t i;
503
504 /*
505 * We can't use the dcc flow control bits, so let's transfer data
506 * with 31 bits and flip the MSB each time a new data word is sent.
507 */
508 static uint32_t dcc_code[] =
509 {
510 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
511 0xe3a0301e, /* 1: mov r3, #30 */
512 0xe3a04002, /* mov r4, #2 */
513 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
514 0xe1310005, /* teq r1, r5 */
515 0x0afffffc, /* beq 1b */
516 0xe1a05001, /* mov r5, r1 */
517 0xe1a01081, /* mov r1, r1, lsl #1 */
518 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
519 0xe1320005, /* teq r2, r5 */
520 0x0afffffc, /* beq 3b */
521 0xe1a05002, /* mov r5, r2 */
522 0xe3c22102, /* bic r2, r2, #0x80000000 */
523 0xe1811332, /* orr r1, r1, r2, lsr r3 */
524 0xe2533001, /* subs r3, r3, #1 */
525 0xe4801004, /* str r1, [r0], #4 */
526 0xe1a01412, /* mov r1, r2, lsl r4 */
527 0xe2844001, /* add r4, r4, #1 */
528 0x4affffed, /* bmi 1b */
529 0xeafffff3, /* b 3b */
530 };
531
532 uint32_t dcc_size = sizeof(dcc_code);
533
534 if (!arm7_9->dcc_downloads)
535 return target_write_memory(target, address, 4, count, buffer);
536
537 /* regrab previously allocated working_area, or allocate a new one */
538 if (!arm7_9->dcc_working_area)
539 {
540 uint8_t dcc_code_buf[dcc_size];
541
542 /* make sure we have a working area */
543 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
544 {
545 LOG_INFO("no working area available, falling back to memory writes");
546 return target_write_memory(target, address, 4, count, buffer);
547 }
548
549 /* copy target instructions to target endianness */
550 for (i = 0; i < dcc_size/4; i++)
551 target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
552
553 /* write DCC code to working area */
554 if ((retval = target_write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf)) != ERROR_OK)
555 {
556 return retval;
557 }
558 }
559
560 /* backup clobbered processor state */
561 for (i = 0; i <= 5; i++)
562 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32);
563 save[i] = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
564
565 /* set up target address in r0 */
566 buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
567 armv4_5->core_cache->reg_list[0].valid = 1;
568 armv4_5->core_cache->reg_list[0].dirty = 1;
569 armv4_5->core_state = ARMV4_5_STATE_ARM;
570
571 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
572 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
573
574 /* send data over */
575 x = 0;
576 flip = 0;
577 shift = 1;
578 for (i = 0; i < count; i++)
579 {
580 uint32_t y = target_buffer_get_u32(target, buffer);
581 uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
582 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
583 x = y << (32 - shift);
584 if (++shift >= 32 || i + 1 >= count)
585 {
586 z = (x >> 1) | (flip ^= 0x80000000);
587 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
588 x = 0;
589 shift = 1;
590 }
591 buffer += 4;
592 }
593
594 retval = target_halt(target);
595 if (retval == ERROR_OK)
596 retval = target_wait_state(target, TARGET_HALTED, 500);
597 if (retval == ERROR_OK) {
598 uint32_t endaddress =
599 buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
600 if (endaddress != address + count*4) {
601 LOG_ERROR("DCC write failed,"
602 " expected end address 0x%08" PRIx32
603 " got 0x%0" PRIx32 "",
604 address + count*4, endaddress);
605 retval = ERROR_FAIL;
606 }
607 }
608
609 /* restore target state */
610 for (i = 0; i <= 5; i++)
611 {
612 buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, save[i]);
613 armv4_5->core_cache->reg_list[i].valid = 1;
614 armv4_5->core_cache->reg_list[i].dirty = 1;
615 }
616 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, save[i]);
617 armv4_5->core_cache->reg_list[15].valid = 1;
618 armv4_5->core_cache->reg_list[15].dirty = 1;
619 armv4_5->core_state = core_state;
620
621 return retval;
622 }
623
624 int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
625 {
626 arm9tdmi_init_target(cmd_ctx, target);
627 return ERROR_OK;
628 }
629
630 int feroceon_quit(void)
631 {
632 return ERROR_OK;
633 }
634
635 int feroceon_target_create(struct target_s *target, Jim_Interp *interp)
636 {
637 armv4_5_common_t *armv4_5;
638 arm7_9_common_t *arm7_9;
639 arm926ejs_common_t *arm926ejs = calloc(1,sizeof(arm926ejs_common_t));
640
641 arm926ejs_init_arch_info(target, arm926ejs, target->tap);
642
643 armv4_5 = target->arch_info;
644 arm7_9 = armv4_5->arch_info;
645
646 /* override some insn sequence functions */
647 arm7_9->change_to_arm = feroceon_change_to_arm;
648 arm7_9->read_core_regs = feroceon_read_core_regs;
649 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
650 arm7_9->read_xpsr = feroceon_read_xpsr;
651 arm7_9->write_xpsr = feroceon_write_xpsr;
652 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
653 arm7_9->write_core_regs = feroceon_write_core_regs;
654 arm7_9->branch_resume = feroceon_branch_resume;
655 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
656
657 /* must be implemented with only one comparator */
658 arm7_9->enable_single_step = feroceon_enable_single_step;
659 arm7_9->disable_single_step = feroceon_disable_single_step;
660
661 /* MOE is not implemented */
662 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
663
664 /* the standard ARM926 methods don't always work (don't ask...) */
665 arm926ejs->read_cp15 = feroceon_read_cp15;
666 arm926ejs->write_cp15 = feroceon_write_cp15;
667
668 /* Note: asserting DBGRQ might not win over the undef exception.
669 If that happens then just use "arm7_9 dbgrq disable". */
670 arm7_9->use_dbgrq = 1;
671 arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
672
673 /* only one working comparator */
674 arm7_9->wp_available_max = 1;
675 arm7_9->wp1_used_default = -1;
676
677 return ERROR_OK;
678 }
679
680 int feroceon_examine(struct target_s *target)
681 {
682 armv4_5_common_t *armv4_5;
683 arm7_9_common_t *arm7_9;
684 int retval;
685
686 retval = arm9tdmi_examine(target);
687 if (retval != ERROR_OK)
688 return retval;
689
690 armv4_5 = target->arch_info;
691 arm7_9 = armv4_5->arch_info;
692
693 /* the COMMS_CTRL bits are all contiguous */
694 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
695 LOG_ERROR("unexpected Feroceon EICE version signature");
696
697 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
698 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
699 arm7_9->has_monitor_mode = 1;
700
701 /* vector catch reg is not initialized on reset */
702 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
703
704 /* clear monitor mode, enable comparators */
705 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
706 jtag_execute_queue();
707 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
708 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
709 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
710
711 return ERROR_OK;
712 }

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)