target/arm946e: add missing error detection
[openocd.git] / src / target / arm946e.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2010 by Drasko DRASKOVIC *
9 * drasko.draskovic@gmail.com *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
23 ***************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "arm946e.h"
30 #include "target_type.h"
31 #include "arm_opcodes.h"
32
33 #include "breakpoints.h"
34
35 #if 0
36 #define _DEBUG_INSTRUCTION_EXECUTION_
37 #endif
38
39 #define NB_CACHE_WAYS 4
40
41 #define CP15_CTL 0x02
42 #define CP15_CTL_DCACHE (1<<2)
43 #define CP15_CTL_ICACHE (1<<12)
44
45 /**
46 * flag to give info about cache manipulation during debug :
47 * "0" - cache lines are invalidated "on the fly", for affected addresses.
48 * This is prefered from performance point of view.
49 * "1" - cache is invalidated and switched off on debug_entry, and switched back on on restore.
50 * It is kept off during debugging.
51 */
52 static uint8_t arm946e_preserve_cache;
53
54 int arm946e_post_debug_entry(struct target *target);
55 void arm946e_pre_restore_context(struct target *target);
56 static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value);
57
58 int arm946e_init_arch_info(struct target *target,
59 struct arm946e_common *arm946e,
60 struct jtag_tap *tap)
61 {
62 struct arm7_9_common *arm7_9 = &arm946e->arm7_9_common;
63
64 /* initialize arm7/arm9 specific info (including armv4_5) */
65 arm9tdmi_init_arch_info(target, arm7_9, tap);
66
67 arm946e->common_magic = ARM946E_COMMON_MAGIC;
68
69 /**
70 * The ARM946E-S implements the ARMv5TE architecture which
71 * has the BKPT instruction, so we don't have to use a watchpoint comparator
72 */
73 arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
74 arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
75
76
77 arm7_9->post_debug_entry = arm946e_post_debug_entry;
78 arm7_9->pre_restore_context = arm946e_pre_restore_context;
79
80 /**
81 * disabling linefills leads to lockups, so keep them enabled for now
82 * this doesn't affect correctness, but might affect timing issues, if
83 * important data is evicted from the cache during the debug session
84 */
85 arm946e_preserve_cache = 0;
86
87 /* override hw single-step capability from ARM9TDMI */
88 /* arm7_9->has_single_step = 1; */
89
90 return ERROR_OK;
91 }
92
93 static int arm946e_target_create(struct target *target, Jim_Interp *interp)
94 {
95 struct arm946e_common *arm946e = calloc(1, sizeof(struct arm946e_common));
96
97 arm946e_init_arch_info(target, arm946e, target->tap);
98
99 return ERROR_OK;
100 }
101
102 static int arm946e_verify_pointer(struct command_invocation *cmd,
103 struct arm946e_common *arm946e)
104 {
105 if (arm946e->common_magic != ARM946E_COMMON_MAGIC) {
106 command_print(cmd, "target is not an ARM946");
107 return ERROR_TARGET_INVALID;
108 }
109 return ERROR_OK;
110 }
111
112 /*
113 * Update cp15_control_reg, saved on debug_entry.
114 */
115 static void arm946e_update_cp15_caches(struct target *target, uint32_t value)
116 {
117 struct arm946e_common *arm946e = target_to_arm946(target);
118 arm946e->cp15_control_reg = (arm946e->cp15_control_reg & ~(CP15_CTL_DCACHE|CP15_CTL_ICACHE))
119 | (value & (CP15_CTL_DCACHE|CP15_CTL_ICACHE));
120 }
121
122 /*
123 * REVISIT: The "read_cp15" and "write_cp15" commands could hook up
124 * to eventual mrc() and mcr() routines ... the reg_addr values being
125 * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
126 * See section 7.3 of the ARM946E-S TRM.
127 */
128 static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value)
129 {
130 int retval = ERROR_OK;
131 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
132 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
133 struct scan_field fields[3];
134 uint8_t reg_addr_buf = reg_addr & 0x3f;
135 uint8_t nr_w_buf = 0;
136
137 retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
138 if (retval != ERROR_OK)
139 return retval;
140 retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
141 if (retval != ERROR_OK)
142 return retval;
143
144 fields[0].num_bits = 32;
145 /* REVISIT: table 7-2 shows that bits 31-31 need to be
146 * specified for accessing BIST registers ...
147 */
148 fields[0].out_value = NULL;
149 fields[0].in_value = NULL;
150
151 fields[1].num_bits = 6;
152 fields[1].out_value = &reg_addr_buf;
153 fields[1].in_value = NULL;
154
155 fields[2].num_bits = 1;
156 fields[2].out_value = &nr_w_buf;
157 fields[2].in_value = NULL;
158
159 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
160
161 fields[0].in_value = (uint8_t *)value;
162 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
163
164 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
165
166 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
167 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
168 #endif
169
170 retval = jtag_execute_queue();
171 if (retval != ERROR_OK)
172 return retval;
173
174 return ERROR_OK;
175 }
176
177 int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
178 {
179 int retval = ERROR_OK;
180 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
181 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
182 struct scan_field fields[3];
183 uint8_t reg_addr_buf = reg_addr & 0x3f;
184 uint8_t nr_w_buf = 1;
185 uint8_t value_buf[4];
186
187 buf_set_u32(value_buf, 0, 32, value);
188
189 retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
190 if (retval != ERROR_OK)
191 return retval;
192 retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
193 if (retval != ERROR_OK)
194 return retval;
195
196 fields[0].num_bits = 32;
197 fields[0].out_value = value_buf;
198 fields[0].in_value = NULL;
199
200 fields[1].num_bits = 6;
201 fields[1].out_value = &reg_addr_buf;
202 fields[1].in_value = NULL;
203
204 fields[2].num_bits = 1;
205 fields[2].out_value = &nr_w_buf;
206 fields[2].in_value = NULL;
207
208 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
209
210 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
211 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
212 #endif
213
214 retval = jtag_execute_queue();
215 if (retval != ERROR_OK)
216 return retval;
217
218 return ERROR_OK;
219 }
220
221 #define GET_ICACHE_SIZE 6
222 #define GET_DCACHE_SIZE 18
223
224 /*
225 * \param target struct target pointer
226 * \param idsel select GET_ICACHE_SIZE or GET_DCACHE_SIZE
227 * \returns cache size, given in bytes
228 */
229 static uint32_t arm946e_cp15_get_csize(struct target *target, int idsel)
230 {
231 struct arm946e_common *arm946e = target_to_arm946(target);
232 uint32_t csize = arm946e->cp15_cache_info;
233 if (csize == 0) {
234 if (arm946e_read_cp15(target, 0x01, &csize) == ERROR_OK)
235 arm946e->cp15_cache_info = csize;
236 }
237 if (csize & (1<<(idsel-4))) /* cache absent */
238 return 0;
239 csize = (csize >> idsel) & 0x0F;
240 return csize ? 1 << (12 + (csize-3)) : 0;
241 }
242
243 uint32_t arm946e_invalidate_whole_dcache(struct target *target)
244 {
245 uint32_t csize = arm946e_cp15_get_csize(target, GET_DCACHE_SIZE);
246 if (csize == 0)
247 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
248
249 /* One line (index) is 32 bytes (8 words) long, 4-way assoc
250 * ARM DDI 0201D, Section 3.3.5
251 */
252 int nb_idx = (csize / (4*8*NB_CACHE_WAYS)); /* gives nb of lines (indexes) in the cache */
253
254 /* Loop for all segmentde (i.e. ways) */
255 uint32_t seg;
256 for (seg = 0; seg < NB_CACHE_WAYS; seg++) {
257 /* Loop for all indexes */
258 int idx;
259 for (idx = 0; idx < nb_idx; idx++) {
260 /* Form and write cp15 index (segment + line idx) */
261 uint32_t cp15_idx = seg << 30 | idx << 5;
262 int retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
263 if (retval != ERROR_OK) {
264 LOG_DEBUG("ERROR writing index");
265 return retval;
266 }
267
268 /* Read dtag */
269 uint32_t dtag;
270 retval = arm946e_read_cp15(target, 0x16, &dtag);
271 if (retval != ERROR_OK) {
272 LOG_DEBUG("ERROR reading dtag");
273 return retval;
274 }
275
276 /* Check cache line VALID bit */
277 if (!(dtag >> 4 & 0x1))
278 continue;
279
280 /* Clean data cache line */
281 retval = arm946e_write_cp15(target, 0x35, 0x1);
282 if (retval != ERROR_OK) {
283 LOG_DEBUG("ERROR cleaning cache line");
284 return retval;
285 }
286
287 /* Flush data cache line */
288 retval = arm946e_write_cp15(target, 0x1a, 0x1);
289 if (retval != ERROR_OK) {
290 LOG_DEBUG("ERROR flushing cache line");
291 return retval;
292 }
293 }
294 }
295
296 return ERROR_OK;
297 }
298
299 uint32_t arm946e_invalidate_whole_icache(struct target *target)
300 {
301 /* Check cache presence before flushing - avoid undefined behavior */
302 uint32_t csize = arm946e_cp15_get_csize(target, GET_ICACHE_SIZE);
303 if (csize == 0)
304 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
305
306 LOG_DEBUG("FLUSHING I$");
307 /**
308 * Invalidate (flush) I$
309 * mcr 15, 0, r0, cr7, cr5, {0}
310 */
311 int retval = arm946e_write_cp15(target, 0x0f, 0x1);
312 if (retval != ERROR_OK) {
313 LOG_DEBUG("ERROR flushing I$");
314 return retval;
315 }
316
317 return ERROR_OK;
318 }
319
320 int arm946e_post_debug_entry(struct target *target)
321 {
322 uint32_t ctr_reg = 0x0;
323 uint32_t retval = ERROR_OK;
324 struct arm946e_common *arm946e = target_to_arm946(target);
325
326 /* See if CACHES are enabled, and save that info
327 * in the context bits, so that arm946e_pre_restore_context() can use them */
328 arm946e_read_cp15(target, CP15_CTL, &ctr_reg);
329
330 /* Save control reg in the context */
331 arm946e->cp15_control_reg = ctr_reg;
332
333 if (arm946e_preserve_cache) {
334 if (ctr_reg & CP15_CTL_DCACHE) {
335 /* Clean and flush D$ */
336 arm946e_invalidate_whole_dcache(target);
337
338 /* Disable D$ */
339 ctr_reg &= ~CP15_CTL_DCACHE;
340 }
341
342 if (ctr_reg & CP15_CTL_ICACHE) {
343 /* Flush I$ */
344 arm946e_invalidate_whole_icache(target);
345
346 /* Disable I$ */
347 ctr_reg &= ~CP15_CTL_ICACHE;
348 }
349
350 /* Write the new configuration */
351 retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
352 if (retval != ERROR_OK) {
353 LOG_DEBUG("ERROR disabling cache");
354 return retval;
355 }
356 } /* if preserve_cache */
357
358 return ERROR_OK;
359 }
360
361 void arm946e_pre_restore_context(struct target *target)
362 {
363 uint32_t ctr_reg = 0x0;
364 uint32_t retval;
365
366 if (arm946e_preserve_cache) {
367 struct arm946e_common *arm946e = target_to_arm946(target);
368 /* Get the contents of the CTR reg */
369 arm946e_read_cp15(target, CP15_CTL, &ctr_reg);
370
371 /**
372 * Read-modify-write CP15 control
373 * to reenable I/D-cache operation
374 * NOTE: It is not possible to disable cache by CP15.
375 * if arm946e_preserve_cache debugging flag enabled.
376 */
377 ctr_reg |= arm946e->cp15_control_reg & (CP15_CTL_DCACHE|CP15_CTL_ICACHE);
378
379 /* Write the new configuration */
380 retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
381 if (retval != ERROR_OK)
382 LOG_DEBUG("ERROR enabling cache");
383 } /* if preserve_cache */
384 }
385
386 uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
387 uint32_t size, uint32_t count)
388 {
389 uint32_t cur_addr = 0x0;
390 uint32_t cp15_idx, set, way, dtag;
391 uint32_t i = 0;
392 int retval;
393
394 for (i = 0; i < count*size; i++) {
395 cur_addr = address + i;
396
397
398 set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
399
400 for (way = 0; way < NB_CACHE_WAYS; way++) {
401 /**
402 * Find if the affected address is kept in the cache.
403 * Because JTAG Scan Chain 15 offers limited approach,
404 * we have to loop through all cache ways (segments) and
405 * read cache tags, then compare them with with address.
406 */
407
408 /* Form and write cp15 index (segment + line idx) */
409 cp15_idx = way << 30 | set << 5;
410 retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
411 if (retval != ERROR_OK) {
412 LOG_DEBUG("ERROR writing index");
413 return retval;
414 }
415
416 /* Read dtag */
417 retval = arm946e_read_cp15(target, 0x16, &dtag);
418 if (retval != ERROR_OK) {
419 LOG_DEBUG("ERROR reading dtag");
420 return retval;
421 }
422
423 /* Check cache line VALID bit */
424 if (!(dtag >> 4 & 0x1))
425 continue;
426
427 /* If line is valid and corresponds to affected address - invalidate it */
428 if (dtag >> 5 == cur_addr >> 5) {
429 /* Clean data cache line */
430 retval = arm946e_write_cp15(target, 0x35, 0x1);
431 if (retval != ERROR_OK) {
432 LOG_DEBUG("ERROR cleaning cache line");
433 return retval;
434 }
435
436 /* Flush data cache line */
437 retval = arm946e_write_cp15(target, 0x1c, 0x1);
438 if (retval != ERROR_OK) {
439 LOG_DEBUG("ERROR flushing cache line");
440 return retval;
441 }
442
443 break;
444 }
445 } /* loop through all 4 ways */
446 } /* loop through all addresses */
447
448 return ERROR_OK;
449 }
450
451 uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
452 uint32_t size, uint32_t count)
453 {
454 uint32_t cur_addr = 0x0;
455 uint32_t cp15_idx, set, way, itag;
456 uint32_t i = 0;
457 int retval;
458
459 for (i = 0; i < count*size; i++) {
460 cur_addr = address + i;
461
462 set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
463
464 for (way = 0; way < NB_CACHE_WAYS; way++) {
465 /* Form and write cp15 index (segment + line idx) */
466 cp15_idx = way << 30 | set << 5;
467 retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
468 if (retval != ERROR_OK) {
469 LOG_DEBUG("ERROR writing index");
470 return retval;
471 }
472
473 /* Read itag */
474 retval = arm946e_read_cp15(target, 0x17, &itag);
475 if (retval != ERROR_OK) {
476 LOG_DEBUG("ERROR reading itag");
477 return retval;
478 }
479
480 /* Check cache line VALID bit */
481 if (!(itag >> 4 & 0x1))
482 continue;
483
484 /* If line is valid and corresponds to affected address - invalidate it */
485 if (itag >> 5 == cur_addr >> 5) {
486 /* Flush I$ line */
487 retval = arm946e_write_cp15(target, 0x1d, 0x0);
488 if (retval != ERROR_OK) {
489 LOG_DEBUG("ERROR flushing cache line");
490 return retval;
491 }
492
493 break;
494 }
495 } /* way loop */
496 } /* addr loop */
497
498 return ERROR_OK;
499 }
500
501 /** Writes a buffer, in the specified word size, with current MMU settings. */
502 int arm946e_write_memory(struct target *target, target_addr_t address,
503 uint32_t size, uint32_t count, const uint8_t *buffer)
504 {
505 int retval;
506
507 LOG_DEBUG("-");
508
509 struct arm946e_common *arm946e = target_to_arm946(target);
510 /* Invalidate D$ if it is ON */
511 if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_DCACHE))
512 arm946e_invalidate_dcache(target, address, size, count);
513
514 /**
515 * Write memory
516 */
517 retval = arm7_9_write_memory_opt(target, address, size, count, buffer);
518 if (retval != ERROR_OK)
519 return retval;
520
521 /* *
522 * Invalidate I$ if it is ON.
523 *
524 * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
525 * because arm7_9_write_memory() has seen non-valid bit in D$
526 * and wrote data into physical RAM (without touching or allocating the cache line).
527 * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
528 * policy for both I$ and D$ (Chapter 3.2 and 3.3)
529 *
530 * Explanation :
531 * "ARM system developer's guide: designing and optimizing system software" by
532 * Andrew N. Sloss, Dominic Symes and Chris Wright,
533 * Chapter 12.3.3 Allocating Policy on a Cache Miss :
534 * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
535 * If the victim cache line contains valid data, then it is written to main memory before the cache line
536 * is filled with new data.
537 * Under this strategy, a write of new data to memory does not update the contents of the cache memory
538 * unless a cache line was allocated on a previous read from main memory.
539 * If the cache line contains valid data, then the write updates the cache and may update the main memory if
540 * the cache write policy is write-through.
541 * If the data is not in the cache, the controller writes to main memory only.
542 */
543 if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_ICACHE))
544 arm946e_invalidate_icache(target, address, size, count);
545
546 return ERROR_OK;
547
548 }
549
550 int arm946e_read_memory(struct target *target, target_addr_t address,
551 uint32_t size, uint32_t count, uint8_t *buffer)
552 {
553 int retval;
554
555 LOG_DEBUG("-");
556
557 retval = arm7_9_read_memory(target, address, size, count, buffer);
558 if (retval != ERROR_OK)
559 return retval;
560
561 return ERROR_OK;
562 }
563
564 COMMAND_HANDLER(arm946e_handle_cp15)
565 {
566 /* one or two arguments, access a single register (write if second argument is given) */
567 if (CMD_ARGC < 1 || CMD_ARGC > 2)
568 return ERROR_COMMAND_SYNTAX_ERROR;
569
570 struct target *target = get_current_target(CMD_CTX);
571
572 struct arm946e_common *arm946e = target_to_arm946(target);
573 int retval = arm946e_verify_pointer(CMD, arm946e);
574 if (retval != ERROR_OK)
575 return retval;
576
577 if (target->state != TARGET_HALTED) {
578 command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
579 return ERROR_TARGET_NOT_HALTED;
580 }
581
582 uint32_t address;
583 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
584
585 if (CMD_ARGC == 1) {
586 uint32_t value;
587 retval = arm946e_read_cp15(target, address, &value);
588 if (retval != ERROR_OK) {
589 command_print(CMD, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address);
590 return retval;
591 }
592 retval = jtag_execute_queue();
593 if (retval != ERROR_OK)
594 return retval;
595
596 /* Return value in hex format */
597 command_print(CMD, "0x%08" PRIx32, value);
598 } else if (CMD_ARGC == 2) {
599 uint32_t value;
600 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
601
602 retval = arm946e_write_cp15(target, address, value);
603 if (retval != ERROR_OK) {
604 command_print(CMD, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address);
605 return retval;
606 }
607 if (address == CP15_CTL)
608 arm946e_update_cp15_caches(target, value);
609 }
610
611 return ERROR_OK;
612 }
613
614 COMMAND_HANDLER(arm946e_handle_idcache)
615 {
616 if (CMD_ARGC > 1)
617 return ERROR_COMMAND_SYNTAX_ERROR;
618
619 int retval;
620 struct target *target = get_current_target(CMD_CTX);
621 struct arm946e_common *arm946e = target_to_arm946(target);
622
623 retval = arm946e_verify_pointer(CMD, arm946e);
624 if (retval != ERROR_OK)
625 return retval;
626
627 if (target->state != TARGET_HALTED) {
628 command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
629 return ERROR_TARGET_NOT_HALTED;
630 }
631
632 bool icache = (strcmp(CMD_NAME, "icache") == 0);
633 uint32_t csize = arm946e_cp15_get_csize(target, icache ? GET_ICACHE_SIZE : GET_DCACHE_SIZE) / 1024;
634 if (CMD_ARGC == 0) {
635 bool bena = ((arm946e->cp15_control_reg & (icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE)) != 0)
636 && (arm946e->cp15_control_reg & 0x1);
637 if (csize == 0)
638 command_print(CMD, "%s-cache absent", icache ? "I" : "D");
639 else
640 command_print(CMD, "%s-cache size: %" PRIu32 "K, %s",
641 icache ? "I" : "D", csize, bena ? "enabled" : "disabled");
642 return ERROR_OK;
643 }
644
645 bool flush = false;
646 bool enable = false;
647 retval = command_parse_bool_arg(CMD_ARGV[0], &enable);
648 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
649 if (strcmp(CMD_ARGV[0], "flush") == 0) {
650 flush = true;
651 retval = ERROR_OK;
652 } else
653 return retval;
654 }
655
656 /* Do not invalidate or change state, if cache is absent */
657 if (csize == 0) {
658 command_print(CMD, "%s-cache absent, '%s' operation undefined", icache ? "I" : "D", CMD_ARGV[0]);
659 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
660 }
661
662 /* NOTE: flushing entire cache will not preserve lock-down cache regions */
663 if (icache) {
664 if ((arm946e->cp15_control_reg & CP15_CTL_ICACHE) && !enable)
665 retval = arm946e_invalidate_whole_icache(target);
666 } else {
667 if ((arm946e->cp15_control_reg & CP15_CTL_DCACHE) && !enable)
668 retval = arm946e_invalidate_whole_dcache(target);
669 }
670
671 if (retval != ERROR_OK || flush)
672 return retval;
673
674 uint32_t value;
675 retval = arm946e_read_cp15(target, CP15_CTL, &value);
676 if (retval != ERROR_OK)
677 return retval;
678
679 uint32_t vnew = value;
680 uint32_t cmask = icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE;
681 if (enable) {
682 if ((value & 0x1) == 0)
683 LOG_WARNING("arm946e: MPU must be enabled for cache to operate");
684 vnew |= cmask;
685 } else
686 vnew &= ~cmask;
687
688 if (vnew == value)
689 return ERROR_OK;
690
691 retval = arm946e_write_cp15(target, CP15_CTL, vnew);
692 if (retval != ERROR_OK)
693 return retval;
694
695 arm946e_update_cp15_caches(target, vnew);
696 return ERROR_OK;
697 }
698
699 static const struct command_registration arm946e_exec_command_handlers[] = {
700 {
701 .name = "cp15",
702 .handler = arm946e_handle_cp15,
703 .mode = COMMAND_EXEC,
704 .usage = "regnum [value]",
705 .help = "read/modify cp15 register",
706 },
707 {
708 .name = "icache",
709 .handler = arm946e_handle_idcache,
710 .mode = COMMAND_EXEC,
711 .usage = "['enable'|'disable'|'flush']",
712 .help = "I-cache info and operations",
713 },
714 {
715 .name = "dcache",
716 .handler = arm946e_handle_idcache,
717 .mode = COMMAND_EXEC,
718 .usage = "['enable'|'disable'|'flush']",
719 .help = "D-cache info and operations",
720 },
721 COMMAND_REGISTRATION_DONE
722 };
723
724 const struct command_registration arm946e_command_handlers[] = {
725 {
726 .chain = arm9tdmi_command_handlers,
727 },
728 {
729 .name = "arm946e",
730 .mode = COMMAND_ANY,
731 .help = "arm946e command group",
732 .usage = "",
733 .chain = arm946e_exec_command_handlers,
734 },
735 COMMAND_REGISTRATION_DONE
736 };
737
738 /** Holds methods for ARM946 targets. */
739 struct target_type arm946e_target = {
740 .name = "arm946e",
741
742 .poll = arm7_9_poll,
743 .arch_state = arm_arch_state,
744
745 .target_request_data = arm7_9_target_request_data,
746
747 .halt = arm7_9_halt,
748 .resume = arm7_9_resume,
749 .step = arm7_9_step,
750
751 .assert_reset = arm7_9_assert_reset,
752 .deassert_reset = arm7_9_deassert_reset,
753 .soft_reset_halt = arm7_9_soft_reset_halt,
754
755 .get_gdb_arch = arm_get_gdb_arch,
756 .get_gdb_reg_list = arm_get_gdb_reg_list,
757
758 /* .read_memory = arm7_9_read_memory, */
759 /* .write_memory = arm7_9_write_memory, */
760 .read_memory = arm946e_read_memory,
761 .write_memory = arm946e_write_memory,
762
763 .checksum_memory = arm_checksum_memory,
764 .blank_check_memory = arm_blank_check_memory,
765
766 .run_algorithm = armv4_5_run_algorithm,
767
768 .add_breakpoint = arm7_9_add_breakpoint,
769 .remove_breakpoint = arm7_9_remove_breakpoint,
770 /* .add_breakpoint = arm946e_add_breakpoint, */
771 /* .remove_breakpoint = arm946e_remove_breakpoint, */
772
773 .add_watchpoint = arm7_9_add_watchpoint,
774 .remove_watchpoint = arm7_9_remove_watchpoint,
775
776 .commands = arm946e_command_handlers,
777 .target_create = arm946e_target_create,
778 .init_target = arm9tdmi_init_target,
779 .examine = arm7_9_examine,
780 .check_reset = arm7_9_check_reset,
781 };

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)