Fix usage of timeval_ms()
[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_context *cmd_ctx,
103 struct arm946e_common *arm946e)
104 {
105 if (arm946e->common_magic != ARM946E_COMMON_MAGIC) {
106 command_print(cmd_ctx, "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 arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
271
272 /* Check cache line VALID bit */
273 if (!(dtag >> 4 & 0x1))
274 continue;
275
276 /* Clean data cache line */
277 retval = arm946e_write_cp15(target, 0x35, 0x1);
278 if (retval != ERROR_OK) {
279 LOG_DEBUG("ERROR cleaning cache line");
280 return retval;
281 }
282
283 /* Flush data cache line */
284 retval = arm946e_write_cp15(target, 0x1a, 0x1);
285 if (retval != ERROR_OK) {
286 LOG_DEBUG("ERROR flushing cache line");
287 return retval;
288 }
289 }
290 }
291
292 return ERROR_OK;
293 }
294
295 uint32_t arm946e_invalidate_whole_icache(struct target *target)
296 {
297 /* Check cache presence before flushing - avoid undefined behavior */
298 uint32_t csize = arm946e_cp15_get_csize(target, GET_ICACHE_SIZE);
299 if (csize == 0)
300 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
301
302 LOG_DEBUG("FLUSHING I$");
303 /**
304 * Invalidate (flush) I$
305 * mcr 15, 0, r0, cr7, cr5, {0}
306 */
307 int retval = arm946e_write_cp15(target, 0x0f, 0x1);
308 if (retval != ERROR_OK) {
309 LOG_DEBUG("ERROR flushing I$");
310 return retval;
311 }
312
313 return ERROR_OK;
314 }
315
316 int arm946e_post_debug_entry(struct target *target)
317 {
318 uint32_t ctr_reg = 0x0;
319 uint32_t retval = ERROR_OK;
320 struct arm946e_common *arm946e = target_to_arm946(target);
321
322 /* See if CACHES are enabled, and save that info
323 * in the context bits, so that arm946e_pre_restore_context() can use them */
324 arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg);
325
326 /* Save control reg in the context */
327 arm946e->cp15_control_reg = ctr_reg;
328
329 if (arm946e_preserve_cache) {
330 if (ctr_reg & CP15_CTL_DCACHE) {
331 /* Clean and flush D$ */
332 arm946e_invalidate_whole_dcache(target);
333
334 /* Disable D$ */
335 ctr_reg &= ~CP15_CTL_DCACHE;
336 }
337
338 if (ctr_reg & CP15_CTL_ICACHE) {
339 /* Flush I$ */
340 arm946e_invalidate_whole_icache(target);
341
342 /* Disable I$ */
343 ctr_reg &= ~CP15_CTL_ICACHE;
344 }
345
346 /* Write the new configuration */
347 retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
348 if (retval != ERROR_OK) {
349 LOG_DEBUG("ERROR disabling cache");
350 return retval;
351 }
352 } /* if preserve_cache */
353
354 return ERROR_OK;
355 }
356
357 void arm946e_pre_restore_context(struct target *target)
358 {
359 uint32_t ctr_reg = 0x0;
360 uint32_t retval;
361
362 if (arm946e_preserve_cache) {
363 struct arm946e_common *arm946e = target_to_arm946(target);
364 /* Get the contents of the CTR reg */
365 arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg);
366
367 /**
368 * Read-modify-write CP15 control
369 * to reenable I/D-cache operation
370 * NOTE: It is not possible to disable cache by CP15.
371 * if arm946e_preserve_cache debugging flag enabled.
372 */
373 ctr_reg |= arm946e->cp15_control_reg & (CP15_CTL_DCACHE|CP15_CTL_ICACHE);
374
375 /* Write the new configuration */
376 retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
377 if (retval != ERROR_OK)
378 LOG_DEBUG("ERROR enabling cache");
379 } /* if preserve_cache */
380 }
381
382 uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
383 uint32_t size, uint32_t count)
384 {
385 uint32_t cur_addr = 0x0;
386 uint32_t cp15_idx, set, way, dtag;
387 uint32_t i = 0;
388 int retval;
389
390 for (i = 0; i < count*size; i++) {
391 cur_addr = address + i;
392
393
394 set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
395
396 for (way = 0; way < NB_CACHE_WAYS; way++) {
397 /**
398 * Find if the affected address is kept in the cache.
399 * Because JTAG Scan Chain 15 offers limited approach,
400 * we have to loop through all cache ways (segments) and
401 * read cache tags, then compare them with with address.
402 */
403
404 /* Form and write cp15 index (segment + line idx) */
405 cp15_idx = way << 30 | set << 5;
406 retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
407 if (retval != ERROR_OK) {
408 LOG_DEBUG("ERROR writing index");
409 return retval;
410 }
411
412 /* Read dtag */
413 arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
414
415 /* Check cache line VALID bit */
416 if (!(dtag >> 4 & 0x1))
417 continue;
418
419 /* If line is valid and corresponds to affected address - invalidate it */
420 if (dtag >> 5 == cur_addr >> 5) {
421 /* Clean data cache line */
422 retval = arm946e_write_cp15(target, 0x35, 0x1);
423 if (retval != ERROR_OK) {
424 LOG_DEBUG("ERROR cleaning cache line");
425 return retval;
426 }
427
428 /* Flush data cache line */
429 retval = arm946e_write_cp15(target, 0x1c, 0x1);
430 if (retval != ERROR_OK) {
431 LOG_DEBUG("ERROR flushing cache line");
432 return retval;
433 }
434
435 break;
436 }
437 } /* loop through all 4 ways */
438 } /* loop through all addresses */
439
440 return ERROR_OK;
441 }
442
443 uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
444 uint32_t size, uint32_t count)
445 {
446 uint32_t cur_addr = 0x0;
447 uint32_t cp15_idx, set, way, itag;
448 uint32_t i = 0;
449 int retval;
450
451 for (i = 0; i < count*size; i++) {
452 cur_addr = address + i;
453
454 set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
455
456 for (way = 0; way < NB_CACHE_WAYS; way++) {
457 /* Form and write cp15 index (segment + line idx) */
458 cp15_idx = way << 30 | set << 5;
459 retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
460 if (retval != ERROR_OK) {
461 LOG_DEBUG("ERROR writing index");
462 return retval;
463 }
464
465 /* Read itag */
466 arm946e_read_cp15(target, 0x17, (uint32_t *) &itag);
467
468 /* Check cache line VALID bit */
469 if (!(itag >> 4 & 0x1))
470 continue;
471
472 /* If line is valid and corresponds to affected address - invalidate it */
473 if (itag >> 5 == cur_addr >> 5) {
474 /* Flush I$ line */
475 retval = arm946e_write_cp15(target, 0x1d, 0x0);
476 if (retval != ERROR_OK) {
477 LOG_DEBUG("ERROR flushing cache line");
478 return retval;
479 }
480
481 break;
482 }
483 } /* way loop */
484 } /* addr loop */
485
486 return ERROR_OK;
487 }
488
489 /** Writes a buffer, in the specified word size, with current MMU settings. */
490 int arm946e_write_memory(struct target *target, uint32_t address,
491 uint32_t size, uint32_t count, const uint8_t *buffer)
492 {
493 int retval;
494
495 LOG_DEBUG("-");
496
497 struct arm946e_common *arm946e = target_to_arm946(target);
498 /* Invalidate D$ if it is ON */
499 if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_DCACHE))
500 arm946e_invalidate_dcache(target, address, size, count);
501
502 /**
503 * Write memory
504 */
505 retval = arm7_9_write_memory_opt(target, address, size, count, buffer);
506 if (retval != ERROR_OK)
507 return retval;
508
509 /* *
510 * Invalidate I$ if it is ON.
511 *
512 * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
513 * because arm7_9_write_memory() has seen non-valid bit in D$
514 * and wrote data into physical RAM (without touching or allocating the cache line).
515 * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
516 * policy for both I$ and D$ (Chapter 3.2 and 3.3)
517 *
518 * Explanation :
519 * "ARM system developer's guide: designing and optimizing system software" by
520 * Andrew N. Sloss, Dominic Symes and Chris Wright,
521 * Chapter 12.3.3 Allocating Policy on a Cache Miss :
522 * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
523 * If the victim cache line contains valid data, then it is written to main memory before the cache line
524 * is filled with new data.
525 * Under this strategy, a write of new data to memory does not update the contents of the cache memory
526 * unless a cache line was allocated on a previous read from main memory.
527 * If the cache line contains valid data, then the write updates the cache and may update the main memory if
528 * the cache write policy is write-through.
529 * If the data is not in the cache, the controller writes to main memory only.
530 */
531 if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_ICACHE))
532 arm946e_invalidate_icache(target, address, size, count);
533
534 return ERROR_OK;
535
536 }
537
538 int arm946e_read_memory(struct target *target, uint32_t address,
539 uint32_t size, uint32_t count, uint8_t *buffer)
540 {
541 int retval;
542
543 LOG_DEBUG("-");
544
545 retval = arm7_9_read_memory(target, address, size, count, buffer);
546 if (retval != ERROR_OK)
547 return retval;
548
549 return ERROR_OK;
550 }
551
552 static int jim_arm946e_cp15(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
553 {
554 /* one or two arguments, access a single register (write if second argument is given) */
555 if (argc < 2 || argc > 3) {
556 Jim_WrongNumArgs(interp, 1, argv, "addr [value]");
557 return JIM_ERR;
558 }
559
560 struct command_context *cmd_ctx = current_command_context(interp);
561 assert(cmd_ctx != NULL);
562
563 struct target *target = get_current_target(cmd_ctx);
564 if (target == NULL) {
565 LOG_ERROR("arm946e: no current target");
566 return JIM_ERR;
567 }
568
569 struct arm946e_common *arm946e = target_to_arm946(target);
570 int retval = arm946e_verify_pointer(cmd_ctx, arm946e);
571 if (retval != ERROR_OK)
572 return JIM_ERR;
573
574 if (target->state != TARGET_HALTED) {
575 command_print(cmd_ctx, "target %s must be stopped for \"cp15\" command", target_name(target));
576 return JIM_ERR;
577 }
578
579 long l;
580 uint32_t address;
581 retval = Jim_GetLong(interp, argv[1], &l);
582 address = l;
583 if (JIM_OK != retval)
584 return retval;
585
586 if (argc == 2) {
587 uint32_t value;
588 retval = arm946e_read_cp15(target, address, &value);
589 if (retval != ERROR_OK) {
590 command_print(cmd_ctx, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address);
591 return JIM_ERR;
592 }
593 retval = jtag_execute_queue();
594 if (retval != ERROR_OK)
595 return JIM_ERR;
596 char buf[20];
597 sprintf(buf, "0x%08" PRIx32, value);
598 /* Return value in hex format */
599 Jim_SetResultString(interp, buf, -1);
600 } else if (argc == 3) {
601 uint32_t value;
602 retval = Jim_GetLong(interp, argv[2], &l);
603 value = l;
604 if (JIM_OK != retval)
605 return retval;
606 retval = arm946e_write_cp15(target, address, value);
607 if (retval != ERROR_OK) {
608 command_print(cmd_ctx, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address);
609 return JIM_ERR;
610 }
611 if (address == CP15_CTL)
612 arm946e_update_cp15_caches(target, value);
613 }
614
615 return JIM_OK;
616 }
617
618 COMMAND_HANDLER(arm946e_handle_idcache)
619 {
620 if (CMD_ARGC > 1)
621 return ERROR_COMMAND_SYNTAX_ERROR;
622
623 int retval;
624 struct target *target = get_current_target(CMD_CTX);
625 struct arm946e_common *arm946e = target_to_arm946(target);
626
627 retval = arm946e_verify_pointer(CMD_CTX, arm946e);
628 if (retval != ERROR_OK)
629 return retval;
630
631 if (target->state != TARGET_HALTED) {
632 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
633 return ERROR_TARGET_NOT_HALTED;
634 }
635
636 bool icache = (strcmp(CMD_NAME, "icache") == 0);
637 uint32_t csize = arm946e_cp15_get_csize(target, icache ? GET_ICACHE_SIZE : GET_DCACHE_SIZE) / 1024;
638 if (CMD_ARGC == 0) {
639 bool bena = ((arm946e->cp15_control_reg & (icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE)) != 0)
640 && (arm946e->cp15_control_reg & 0x1);
641 if (csize == 0)
642 command_print(CMD_CTX, "%s-cache absent", icache ? "I" : "D");
643 else
644 command_print(CMD_CTX, "%s-cache size: %" PRIu32 "K, %s",
645 icache ? "I" : "D", csize, bena ? "enabled" : "disabled");
646 return ERROR_OK;
647 }
648
649 bool flush = false;
650 bool enable = false;
651 retval = command_parse_bool_arg(CMD_ARGV[0], &enable);
652 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
653 if (strcmp(CMD_ARGV[0], "flush") == 0) {
654 flush = true;
655 retval = ERROR_OK;
656 } else
657 return retval;
658 }
659
660 /* Do not invalidate or change state, if cache is absent */
661 if (csize == 0) {
662 command_print(CMD_CTX, "%s-cache absent, '%s' operation undefined", icache ? "I" : "D", CMD_ARGV[0]);
663 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
664 }
665
666 /* NOTE: flushing entire cache will not preserve lock-down cache regions */
667 if (icache) {
668 if ((arm946e->cp15_control_reg & CP15_CTL_ICACHE) && !enable)
669 retval = arm946e_invalidate_whole_icache(target);
670 } else {
671 if ((arm946e->cp15_control_reg & CP15_CTL_DCACHE) && !enable)
672 retval = arm946e_invalidate_whole_dcache(target);
673 }
674
675 if (retval != ERROR_OK || flush)
676 return retval;
677
678 uint32_t value;
679 retval = arm946e_read_cp15(target, CP15_CTL, &value);
680 if (retval != ERROR_OK)
681 return retval;
682
683 uint32_t vnew = value;
684 uint32_t cmask = icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE;
685 if (enable) {
686 if ((value & 0x1) == 0)
687 LOG_WARNING("arm946e: MPU must be enabled for cache to operate");
688 vnew |= cmask;
689 } else
690 vnew &= ~cmask;
691
692 if (vnew == value)
693 return ERROR_OK;
694
695 retval = arm946e_write_cp15(target, CP15_CTL, vnew);
696 if (retval != ERROR_OK)
697 return retval;
698
699 arm946e_update_cp15_caches(target, vnew);
700 return ERROR_OK;
701 }
702
703 static const struct command_registration arm946e_exec_command_handlers[] = {
704 {
705 .name = "cp15",
706 .jim_handler = jim_arm946e_cp15,
707 .mode = COMMAND_EXEC,
708 .usage = "regnum [value]",
709 .help = "read/modify cp15 register",
710 },
711 {
712 .name = "icache",
713 .handler = arm946e_handle_idcache,
714 .mode = COMMAND_EXEC,
715 .usage = "['enable'|'disable'|'flush']",
716 .help = "I-cache info and operations",
717 },
718 {
719 .name = "dcache",
720 .handler = arm946e_handle_idcache,
721 .mode = COMMAND_EXEC,
722 .usage = "['enable'|'disable'|'flush']",
723 .help = "D-cache info and operations",
724 },
725 COMMAND_REGISTRATION_DONE
726 };
727
728 const struct command_registration arm946e_command_handlers[] = {
729 {
730 .chain = arm9tdmi_command_handlers,
731 },
732 {
733 .name = "arm946e",
734 .mode = COMMAND_ANY,
735 .help = "arm946e command group",
736 .usage = "",
737 .chain = arm946e_exec_command_handlers,
738 },
739 COMMAND_REGISTRATION_DONE
740 };
741
742 /** Holds methods for ARM946 targets. */
743 struct target_type arm946e_target = {
744 .name = "arm946e",
745
746 .poll = arm7_9_poll,
747 .arch_state = arm_arch_state,
748
749 .target_request_data = arm7_9_target_request_data,
750
751 .halt = arm7_9_halt,
752 .resume = arm7_9_resume,
753 .step = arm7_9_step,
754
755 .assert_reset = arm7_9_assert_reset,
756 .deassert_reset = arm7_9_deassert_reset,
757 .soft_reset_halt = arm7_9_soft_reset_halt,
758
759 .get_gdb_reg_list = arm_get_gdb_reg_list,
760
761 /* .read_memory = arm7_9_read_memory, */
762 /* .write_memory = arm7_9_write_memory, */
763 .read_memory = arm946e_read_memory,
764 .write_memory = arm946e_write_memory,
765
766 .checksum_memory = arm_checksum_memory,
767 .blank_check_memory = arm_blank_check_memory,
768
769 .run_algorithm = armv4_5_run_algorithm,
770
771 .add_breakpoint = arm7_9_add_breakpoint,
772 .remove_breakpoint = arm7_9_remove_breakpoint,
773 /* .add_breakpoint = arm946e_add_breakpoint, */
774 /* .remove_breakpoint = arm946e_remove_breakpoint, */
775
776 .add_watchpoint = arm7_9_add_watchpoint,
777 .remove_watchpoint = arm7_9_remove_watchpoint,
778
779 .commands = arm946e_command_handlers,
780 .target_create = arm946e_target_create,
781 .init_target = arm9tdmi_init_target,
782 .examine = arm7_9_examine,
783 .check_reset = arm7_9_check_reset,
784 };

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)