ARMv7-M: make DAP commands verify target is an ARMv7-M
[openocd.git] / src / target / fa526.c
1 /***************************************************************************
2 * Copyright (C) 2009 by Paulius Zaleckas *
3 * paulius.zaleckas@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 /*
22 * FA526 is very similar to ARM920T with following differences:
23 *
24 * - execution pipeline is 6 steps
25 * - Unified TLB
26 * - has Branch Target Buffer
27 * - does not support reading of I/D cache contents
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "arm920t.h"
35 #include "target_type.h"
36 #include "arm_opcodes.h"
37
38 static void fa526_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc)
39 {
40 LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
41 }
42
43 static void fa526_read_core_regs(struct target *target,
44 uint32_t mask, uint32_t* core_regs[16])
45 {
46 int i;
47 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
48 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
49
50 /* STMIA r0-15, [r0] at debug speed
51 * register values will start to appear on 4th DCLK
52 */
53 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
54
55 /* fetch NOP, STM in DECODE stage */
56 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
57 /* fetch NOP, STM in SHIFT stage */
58 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
59 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
60 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
61
62 for (i = 0; i <= 15; i++)
63 {
64 if (mask & (1 << i))
65 /* nothing fetched, STM in MEMORY (i'th cycle) */
66 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
67 }
68 }
69
70 static void fa526_read_core_regs_target_buffer(struct target *target,
71 uint32_t mask, void* buffer, int size)
72 {
73 int i;
74 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
75 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
76 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
77 uint32_t *buf_u32 = buffer;
78 uint16_t *buf_u16 = buffer;
79 uint8_t *buf_u8 = buffer;
80
81 /* STMIA r0-15, [r0] at debug speed
82 * register values will start to appear on 4th DCLK
83 */
84 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
85
86 /* fetch NOP, STM in DECODE stage */
87 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
88 /* fetch NOP, STM in SHIFT stage */
89 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
90 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
91 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
92
93 for (i = 0; i <= 15; i++)
94 {
95 if (mask & (1 << i))
96 /* nothing fetched, STM in MEMORY (i'th cycle) */
97 switch (size)
98 {
99 case 4:
100 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
101 break;
102 case 2:
103 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
104 break;
105 case 1:
106 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
107 break;
108 }
109 }
110 }
111
112 static void fa526_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
113 {
114 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
115 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
116
117 /* MRS r0, cpsr */
118 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
119 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
120 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
121 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
122 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
123 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
124
125 /* STR r0, [r15] */
126 arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
127 /* fetch NOP, STR in DECODE stage */
128 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
129 /* fetch NOP, STR in SHIFT stage */
130 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
131 /* fetch NOP, STR in EXECUTE stage (1st cycle) */
132 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
133 /* nothing fetched, STR in MEMORY */
134 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
135 }
136
137 static void fa526_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
138 {
139 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
140 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
141
142 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
143
144 /* MSR1 fetched */
145 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
146 /* MSR2 fetched, MSR1 in DECODE */
147 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
148 /* MSR3 fetched, MSR1 in SHIFT, MSR2 in DECODE */
149 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
150 /* MSR4 fetched, MSR1 in EXECUTE (1), MSR2 in SHIFT, MSR3 in DECODE */
151 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
152 /* nothing fetched, MSR1 in EXECUTE (2) */
153 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
154 /* nothing fetched, MSR1 in EXECUTE (3) */
155 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
156 /* nothing fetched, MSR2 in EXECUTE (1), MSR3 in SHIFT, MSR4 in DECODE */
157 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
158 /* nothing fetched, MSR2 in EXECUTE (2) */
159 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
160 /* nothing fetched, MSR2 in EXECUTE (3) */
161 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
162 /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in SHIFT */
163 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
164 /* nothing fetched, MSR3 in EXECUTE (2) */
165 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
166 /* nothing fetched, MSR3 in EXECUTE (3) */
167 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
168 /* NOP fetched, MSR4 in EXECUTE (1) */
169 /* last MSR writes flags, which takes only one cycle */
170 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
171 }
172
173 static void fa526_write_xpsr_im8(struct target *target,
174 uint8_t xpsr_im, int rot, int spsr)
175 {
176 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
177 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
178
179 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
180
181 /* MSR fetched */
182 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
183 /* NOP fetched, MSR in DECODE */
184 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
185 /* NOP fetched, MSR in SHIFT */
186 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
187 /* NOP fetched, MSR in EXECUTE (1) */
188 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
189
190 /* rot == 4 writes flags, which takes only one cycle */
191 if (rot != 4)
192 {
193 /* nothing fetched, MSR in EXECUTE (2) */
194 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
195 /* nothing fetched, MSR in EXECUTE (3) */
196 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
197 }
198 }
199
200 static void fa526_write_core_regs(struct target *target,
201 uint32_t mask, uint32_t core_regs[16])
202 {
203 int i;
204 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
205 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
206
207 /* LDMIA r0-15, [r0] at debug speed
208 * register values will start to appear on 4th DCLK
209 */
210 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
211
212 /* fetch NOP, LDM in DECODE stage */
213 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
214 /* fetch NOP, LDM in SHIFT stage */
215 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
216 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
217 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
218
219 for (i = 0; i <= 15; i++)
220 {
221 if (mask & (1 << i))
222 /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
223 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
224 }
225 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
226 }
227
228 static void fa526_write_pc(struct target *target, uint32_t pc)
229 {
230 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
231 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
232
233 /* LDMIA r0-15, [r0] at debug speed
234 * register values will start to appear on 4th DCLK
235 */
236 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
237
238 /* fetch NOP, LDM in DECODE stage */
239 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
240 /* fetch NOP, LDM in SHIFT stage */
241 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
242 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
243 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
244 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
245 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
246 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
247 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
248 /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
249 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
250 /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
251 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
252 }
253
254 static void fa526_branch_resume_thumb(struct target *target)
255 {
256 LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
257 }
258
259 static int fa526_init_arch_info_2(struct target *target,
260 struct arm7_9_common *arm7_9, struct jtag_tap *tap)
261 {
262 /* prepare JTAG information for the new target */
263 arm7_9->jtag_info.tap = tap;
264 arm7_9->jtag_info.scann_size = 5;
265
266 /* register arch-specific functions */
267 arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
268 arm7_9->change_to_arm = fa526_change_to_arm;
269 arm7_9->read_core_regs = fa526_read_core_regs;
270 arm7_9->read_core_regs_target_buffer = fa526_read_core_regs_target_buffer;
271 arm7_9->read_xpsr = fa526_read_xpsr;
272
273 arm7_9->write_xpsr = fa526_write_xpsr;
274 arm7_9->write_xpsr_im8 = fa526_write_xpsr_im8;
275 arm7_9->write_core_regs = fa526_write_core_regs;
276
277 arm7_9->load_word_regs = arm9tdmi_load_word_regs;
278 arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
279 arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
280
281 arm7_9->store_word_regs = arm9tdmi_store_word_regs;
282 arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
283 arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
284
285 arm7_9->write_pc = fa526_write_pc;
286 arm7_9->branch_resume = arm9tdmi_branch_resume;
287 arm7_9->branch_resume_thumb = fa526_branch_resume_thumb;
288
289 arm7_9->enable_single_step = arm9tdmi_enable_single_step;
290 arm7_9->disable_single_step = arm9tdmi_disable_single_step;
291
292 arm7_9->post_debug_entry = NULL;
293
294 arm7_9->pre_restore_context = NULL;
295 arm7_9->post_restore_context = NULL;
296
297 /* initialize arch-specific breakpoint handling */
298 arm7_9->arm_bkpt = 0xdeeedeee;
299 arm7_9->thumb_bkpt = 0xdeee;
300
301 arm7_9->dbgreq_adjust_pc = 3;
302
303 arm7_9_init_arch_info(target, arm7_9);
304
305 /* override use of DBGRQ, this is safe on ARM9TDMI */
306 arm7_9->use_dbgrq = 1;
307
308 /* all ARM9s have the vector catch register */
309 arm7_9->has_vector_catch = 1;
310
311 return ERROR_OK;
312 }
313
314 static int fa526_init_arch_info(struct target *target,
315 struct arm920t_common *arm920t, struct jtag_tap *tap)
316 {
317 struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
318
319 /* initialize arm7/arm9 specific info (including armv4_5) */
320 fa526_init_arch_info_2(target, arm7_9, tap);
321
322 arm920t->common_magic = ARM920T_COMMON_MAGIC;
323
324 arm7_9->post_debug_entry = arm920t_post_debug_entry;
325 arm7_9->pre_restore_context = arm920t_pre_restore_context;
326
327 arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
328 arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
329 arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
330 arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
331 arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
332 arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
333 arm920t->armv4_5_mmu.has_tiny_pages = 1;
334 arm920t->armv4_5_mmu.mmu_enabled = 0;
335
336 /* disabling linefills leads to lockups, so keep them enabled for now
337 * this doesn't affect correctness, but might affect timing issues, if
338 * important data is evicted from the cache during the debug session
339 * */
340 arm920t->preserve_cache = 0;
341
342 /* override hw single-step capability from ARM9TDMI */
343 arm7_9->has_single_step = 1;
344
345 return ERROR_OK;
346 }
347
348 static int fa526_target_create(struct target *target, Jim_Interp *interp)
349 {
350 struct arm920t_common *arm920t = calloc(1,sizeof(struct arm920t_common));
351
352 return fa526_init_arch_info(target, arm920t, target->tap);
353 }
354
355 /** Holds methods for FA526 targets. */
356 struct target_type fa526_target =
357 {
358 .name = "fa526",
359
360 .poll = arm7_9_poll,
361 .arch_state = arm920t_arch_state,
362
363 .target_request_data = arm7_9_target_request_data,
364
365 .halt = arm7_9_halt,
366 .resume = arm7_9_resume,
367 .step = arm7_9_step,
368
369 .assert_reset = arm7_9_assert_reset,
370 .deassert_reset = arm7_9_deassert_reset,
371 .soft_reset_halt = arm920t_soft_reset_halt,
372
373 .get_gdb_reg_list = arm_get_gdb_reg_list,
374
375 .read_memory = arm920t_read_memory,
376 .write_memory = arm920t_write_memory,
377 .bulk_write_memory = arm7_9_bulk_write_memory,
378
379 .checksum_memory = arm_checksum_memory,
380 .blank_check_memory = arm_blank_check_memory,
381
382 .run_algorithm = armv4_5_run_algorithm,
383
384 .add_breakpoint = arm7_9_add_breakpoint,
385 .remove_breakpoint = arm7_9_remove_breakpoint,
386 .add_watchpoint = arm7_9_add_watchpoint,
387 .remove_watchpoint = arm7_9_remove_watchpoint,
388
389 .commands = arm920t_command_handlers,
390 .target_create = fa526_target_create,
391 .init_target = arm9tdmi_init_target,
392 .examine = arm7_9_examine,
393 .check_reset = arm7_9_check_reset,
394 };

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)