1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2010 by Drasko DRASKOVIC *
9 * drasko.draskovic@gmail.com *
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. *
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. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
31 #include "target_type.h"
32 #include "arm_opcodes.h"
34 #include "breakpoints.h"
37 #define _DEBUG_INSTRUCTION_EXECUTION_
40 #define NB_CACHE_WAYS 4
42 static uint32_t dc
= 0x0;
43 static uint32_t ic
= 0x0;
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.
52 static uint8_t arm946e_preserve_cache
;
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
);
59 int arm946e_init_arch_info(struct target
*target
, struct arm946e_common
*arm946e
, struct jtag_tap
*tap
)
61 struct arm7_9_common
*arm7_9
= &arm946e
->arm7_9_common
;
63 /* initialize arm7/arm9 specific info (including armv4_5) */
64 arm9tdmi_init_arch_info(target
, arm7_9
, tap
);
66 arm946e
->common_magic
= ARM946E_COMMON_MAGIC
;
69 * The ARM946E-S implements the ARMv5TE architecture which
70 * has the BKPT instruction, so we don't have to use a watchpoint comparator
72 arm7_9
->arm_bkpt
= ARMV5_BKPT(0x0);
73 arm7_9
->thumb_bkpt
= ARMV5_T_BKPT(0x0) & 0xffff;
76 arm7_9
->post_debug_entry
= arm946e_post_debug_entry
;
77 arm7_9
->pre_restore_context
= arm946e_pre_restore_context
;
80 * disabling linefills leads to lockups, so keep them enabled for now
81 * this doesn't affect correctness, but might affect timing issues, if
82 * important data is evicted from the cache during the debug session
84 arm946e_preserve_cache
= 0;
86 /* override hw single-step capability from ARM9TDMI */
87 //arm7_9->has_single_step = 1;
92 static int arm946e_target_create(struct target
*target
, Jim_Interp
*interp
)
94 struct arm946e_common
*arm946e
= calloc(1,sizeof(struct arm946e_common
));
96 arm946e_init_arch_info(target
, arm946e
, target
->tap
);
101 static int arm946e_verify_pointer(struct command_context
*cmd_ctx
,
102 struct arm946e_common
*arm946e
)
104 if (arm946e
->common_magic
!= ARM946E_COMMON_MAGIC
) {
105 command_print(cmd_ctx
, "target is not an ARM946");
106 return ERROR_TARGET_INVALID
;
112 * REVISIT: The "read_cp15" and "write_cp15" commands could hook up
113 * to eventual mrc() and mcr() routines ... the reg_addr values being
114 * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
115 * See section 7.3 of the ARM946E-S TRM.
117 static int arm946e_read_cp15(struct target
*target
, int reg_addr
, uint32_t *value
)
119 int retval
= ERROR_OK
;
120 struct arm7_9_common
*arm7_9
= target_to_arm7_9(target
);
121 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
122 struct scan_field fields
[3];
123 uint8_t reg_addr_buf
= reg_addr
& 0x3f;
124 uint8_t nr_w_buf
= 0;
126 if ((retval
= arm_jtag_scann(jtag_info
, 0xf, TAP_IDLE
)) != ERROR_OK
)
130 retval
= arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
, TAP_IDLE
);
131 if (retval
!= ERROR_OK
)
134 fields
[0].num_bits
= 32;
135 /* REVISIT: table 7-2 shows that bits 31-31 need to be
136 * specified for accessing BIST registers ...
138 fields
[0].out_value
= NULL
;
139 fields
[0].in_value
= NULL
;
141 fields
[1].num_bits
= 6;
142 fields
[1].out_value
= ®_addr_buf
;
143 fields
[1].in_value
= NULL
;
145 fields
[2].num_bits
= 1;
146 fields
[2].out_value
= &nr_w_buf
;
147 fields
[2].in_value
= NULL
;
149 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_IDLE
);
151 fields
[0].in_value
= (uint8_t *)value
;
152 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_IDLE
);
154 jtag_add_callback(arm_le_to_h_u32
, (jtag_callback_data_t
)value
);
156 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
157 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr
, *value
);
160 if ((retval
= jtag_execute_queue()) != ERROR_OK
)
168 int arm946e_write_cp15(struct target
*target
, int reg_addr
, uint32_t value
)
170 int retval
= ERROR_OK
;
171 struct arm7_9_common
*arm7_9
= target_to_arm7_9(target
);
172 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
173 struct scan_field fields
[3];
174 uint8_t reg_addr_buf
= reg_addr
& 0x3f;
175 uint8_t nr_w_buf
= 1;
176 uint8_t value_buf
[4];
178 buf_set_u32(value_buf
, 0, 32, value
);
180 if ((retval
= arm_jtag_scann(jtag_info
, 0xf, TAP_IDLE
)) != ERROR_OK
)
184 retval
= arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
, TAP_IDLE
);
185 if (retval
!= ERROR_OK
)
188 fields
[0].num_bits
= 32;
189 fields
[0].out_value
= value_buf
;
190 fields
[0].in_value
= NULL
;
192 fields
[1].num_bits
= 6;
193 fields
[1].out_value
= ®_addr_buf
;
194 fields
[1].in_value
= NULL
;
196 fields
[2].num_bits
= 1;
197 fields
[2].out_value
= &nr_w_buf
;
198 fields
[2].in_value
= NULL
;
200 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_IDLE
);
202 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
203 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr
, value
);
206 if ((retval
= jtag_execute_queue()) != ERROR_OK
)
214 uint32_t arm946e_invalidate_whole_dcache(struct target
*target
)
219 uint32_t cp15_idx
, seg
, dtag
;
224 arm946e_read_cp15(target
, 0x01, (uint32_t *) &csize
);
226 csize
= (csize
>> 18) & 0x0F;
231 shift
= csize
- 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
233 /* Cache size, given in bytes */
234 csize
= 1 << (12 + shift
);
235 /* One line (index) is 32 bytes (8 words) long */
236 nb_idx
= (csize
/ 32); /* gives nb of lines (indexes) in the cache */
238 /* Loop for all segmentde (i.e. ways) */
239 for( seg
=0; seg
< NB_CACHE_WAYS
; seg
++)
241 /* Loop for all indexes */
242 for(idx
=0; idx
< nb_idx
; idx
++)
244 /* Form and write cp15 index (segment + line idx) */
245 cp15_idx
= seg
<< 30 | idx
<< 5;
246 retval
= arm946e_write_cp15(target
, 0x3a, cp15_idx
);
247 if (retval
!= ERROR_OK
)
249 LOG_DEBUG("ERROR writing index");
254 arm946e_read_cp15(target
, 0x16, (uint32_t *) &dtag
);
256 /* Check cache line VALID bit */
257 if ( !(dtag
>> 4 & 0x1) )
260 /* Clean data cache line */
261 retval
= arm946e_write_cp15(target
, 0x35, 0x1);
262 if (retval
!= ERROR_OK
)
264 LOG_DEBUG("ERROR cleaning cache line");
268 /* Flush data cache line */
269 retval
= arm946e_write_cp15(target
, 0x1a, 0x1);
270 if (retval
!= ERROR_OK
)
272 LOG_DEBUG("ERROR flushing cache line");
281 uint32_t arm946e_invalidate_whole_icache(struct target
*target
)
285 LOG_DEBUG("FLUSHING I$");
288 * Invalidate (flush) I$
289 * mcr 15, 0, r0, cr7, cr5, {0}
291 retval
= arm946e_write_cp15(target
, 0x0f, 0x1);
292 if (retval
!= ERROR_OK
)
294 LOG_DEBUG("ERROR flushing I$");
301 int arm946e_post_debug_entry(struct target
*target
)
303 uint32_t ctr_reg
= 0x0;
304 uint32_t retval
= ERROR_OK
;
306 /* See if CACHES are enabled, and save that info
307 * in the global vars, so that arm946e_pre_restore_context() can use them */
308 arm946e_read_cp15(target
, 0x02, (uint32_t *) &ctr_reg
);
309 dc
= (ctr_reg
>> 2) & 0x01;
310 ic
= (ctr_reg
>> 12) & 0x01;
312 if (arm946e_preserve_cache
)
316 /* Clean and flush D$ */
317 arm946e_invalidate_whole_dcache(target
);
320 ctr_reg
&= ~(1 << 2);
326 arm946e_invalidate_whole_icache(target
);
329 ctr_reg
&= ~(1 << 12);
332 /* Write the new configuration */
333 retval
= arm946e_write_cp15(target
, 0x02, ctr_reg
);
334 if (retval
!= ERROR_OK
)
336 LOG_DEBUG("ERROR disabling cache");
339 } /* if preserve_cache */
344 void arm946e_pre_restore_context(struct target
*target
)
346 uint32_t ctr_reg
= 0x0;
349 if (arm946e_preserve_cache
)
351 /* Get the contents of the CTR reg */
352 arm946e_read_cp15(target
, 0x02, (uint32_t *) &ctr_reg
);
355 * Read-modify-write CP15 test state register
356 * to reenable I/D-cache linefills
370 /* Write the new configuration */
371 retval
= arm946e_write_cp15(target
, 0x02, ctr_reg
);
372 if (retval
!= ERROR_OK
)
374 LOG_DEBUG("ERROR enabling cache");
376 } /* if preserve_cache */
379 uint32_t arm946e_invalidate_dcache(struct target
*target
, uint32_t address
,
380 uint32_t size
, uint32_t count
)
382 uint32_t csize
= 0x0;
384 uint32_t cur_addr
= 0x0;
385 uint32_t cp15_idx
, set
, way
, dtag
;
389 for(i
= 0; i
< count
*size
; i
++)
391 cur_addr
= address
+ i
;
394 arm946e_read_cp15(target
, 0x01, (uint32_t *) &csize
);
396 /* Conclude cache size to find number of lines */
397 csize
= (csize
>> 18) & 0x0F;
402 shift
= csize
- 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
404 csize
= 1 << (12 + shift
);
406 set
= (cur_addr
>> 5) & 0xff; /* set field is 8 bits long */
408 for (way
= 0; way
< NB_CACHE_WAYS
; way
++)
411 * Find if the affected address is kept in the cache.
412 * Because JTAG Scan Chain 15 offers limited approach,
413 * we have to loop through all cache ways (segments) and
414 * read cache tags, then compare them with with address.
417 /* Form and write cp15 index (segment + line idx) */
418 cp15_idx
= way
<< 30 | set
<< 5;
419 retval
= arm946e_write_cp15(target
, 0x3a, cp15_idx
);
420 if (retval
!= ERROR_OK
)
422 LOG_DEBUG("ERROR writing index");
427 arm946e_read_cp15(target
, 0x16, (uint32_t *) &dtag
);
429 /* Check cache line VALID bit */
430 if ( !(dtag
>> 4 & 0x1) )
433 /* If line is valid and corresponds to affected address - invalidate it */
434 if (dtag
>> 5 == cur_addr
>> 5)
436 /* Clean data cache line */
437 retval
= arm946e_write_cp15(target
, 0x35, 0x1);
438 if (retval
!= ERROR_OK
)
440 LOG_DEBUG("ERROR cleaning cache line");
444 /* Flush data cache line */
445 retval
= arm946e_write_cp15(target
, 0x1c, 0x1);
446 if (retval
!= ERROR_OK
)
448 LOG_DEBUG("ERROR flushing cache line");
454 } /* loop through all 4 ways */
455 } /* loop through all addresses */
460 uint32_t arm946e_invalidate_icache(struct target
*target
, uint32_t address
,
461 uint32_t size
, uint32_t count
)
463 uint32_t cur_addr
= 0x0;
464 uint32_t cp15_idx
, set
, way
, itag
;
468 for(i
= 0; i
< count
*size
; i
++)
470 cur_addr
= address
+ i
;
472 set
= (cur_addr
>> 5) & 0xff; /* set field is 8 bits long */
474 for (way
= 0; way
< NB_CACHE_WAYS
; way
++)
476 /* Form and write cp15 index (segment + line idx) */
477 cp15_idx
= way
<< 30 | set
<< 5;
478 retval
= arm946e_write_cp15(target
, 0x3a, cp15_idx
);
479 if (retval
!= ERROR_OK
)
481 LOG_DEBUG("ERROR writing index");
486 arm946e_read_cp15(target
, 0x17, (uint32_t *) &itag
);
488 /* Check cache line VALID bit */
489 if ( !(itag
>> 4 & 0x1) )
492 /* If line is valid and corresponds to affected address - invalidate it */
493 if (itag
>> 5 == cur_addr
>> 5)
496 retval
= arm946e_write_cp15(target
, 0x1d, 0x0);
497 if (retval
!= ERROR_OK
)
499 LOG_DEBUG("ERROR flushing cache line");
511 /** Writes a buffer, in the specified word size, with current MMU settings. */
512 int arm946e_write_memory(struct target
*target
, uint32_t address
,
513 uint32_t size
, uint32_t count
, const uint8_t *buffer
)
519 /* Invalidate D$ if it is ON */
520 if (!arm946e_preserve_cache
&& dc
== 1)
522 arm946e_invalidate_dcache(target
, address
, size
, count
);
528 if ( ( retval
= arm7_9_write_memory(target
, address
,
529 size
, count
, buffer
) ) != ERROR_OK
)
535 * Invalidate I$ if it is ON.
537 * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
538 * because arm7_9_write_memory() has seen non-valid bit in D$
539 * and wrote data into physical RAM (without touching or allocating the cache line).
540 * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
541 * policy for both I$ and D$ (Chapter 3.2 and 3.3)
544 * "ARM system developer's guide: designing and optimizing system software" by
545 * Andrew N. Sloss, Dominic Symes and Chris Wright,
546 * Chapter 12.3.3 Allocating Policy on a Cache Miss :
547 * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
548 * If the victim cache line contains valid data, then it is written to main memory before the cache line
549 * is filled with new data.
550 * Under this strategy, a write of new data to memory does not update the contents of the cache memory
551 * unless a cache line was allocated on a previous read from main memory.
552 * If the cache line contains valid data, then the write updates the cache and may update the main memory if
553 * the cache write policy is write-through.
554 * If the data is not in the cache, the controller writes to main memory only.
556 if (!arm946e_preserve_cache
&& ic
== 1)
558 arm946e_invalidate_icache(target
, address
, size
, count
);
565 int arm946e_read_memory(struct target
*target
, uint32_t address
,
566 uint32_t size
, uint32_t count
, uint8_t *buffer
)
572 if ( ( retval
= arm7_9_read_memory(target
, address
,
573 size
, count
, buffer
) ) != ERROR_OK
)
582 COMMAND_HANDLER(arm946e_handle_cp15_command
)
585 struct target
*target
= get_current_target(CMD_CTX
);
586 struct arm946e_common
*arm946e
= target_to_arm946(target
);
588 retval
= arm946e_verify_pointer(CMD_CTX
, arm946e
);
589 if (retval
!= ERROR_OK
)
592 if (target
->state
!= TARGET_HALTED
)
594 command_print(CMD_CTX
, "target must be stopped for \"%s\" command", CMD_NAME
);
598 /* one or more argument, access a single register (write if second argument is given */
602 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
607 if ((retval
= arm946e_read_cp15(target
, address
, &value
)) != ERROR_OK
)
609 command_print(CMD_CTX
,
610 "couldn't access reg %" PRIi32
,
614 if ((retval
= jtag_execute_queue()) != ERROR_OK
)
619 command_print(CMD_CTX
, "%" PRIi32
": %8.8" PRIx32
,
622 else if (CMD_ARGC
== 2)
625 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
626 if ((retval
= arm946e_write_cp15(target
, address
, value
)) != ERROR_OK
)
628 command_print(CMD_CTX
,
629 "couldn't access reg %" PRIi32
,
633 command_print(CMD_CTX
, "%" PRIi32
": %8.8" PRIx32
,
641 static const struct command_registration arm946e_exec_command_handlers
[] = {
644 .handler
= arm946e_handle_cp15_command
,
645 .mode
= COMMAND_EXEC
,
646 .usage
= "regnum [value]",
647 .help
= "display/modify cp15 register",
649 COMMAND_REGISTRATION_DONE
652 const struct command_registration arm946e_command_handlers
[] = {
654 .chain
= arm9tdmi_command_handlers
,
659 .help
= "arm946e command group",
660 .chain
= arm946e_exec_command_handlers
,
662 COMMAND_REGISTRATION_DONE
665 /** Holds methods for ARM946 targets. */
666 struct target_type arm946e_target
=
671 .arch_state
= arm_arch_state
,
673 .target_request_data
= arm7_9_target_request_data
,
676 .resume
= arm7_9_resume
,
679 .assert_reset
= arm7_9_assert_reset
,
680 .deassert_reset
= arm7_9_deassert_reset
,
681 .soft_reset_halt
= arm7_9_soft_reset_halt
,
683 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
685 //.read_memory = arm7_9_read_memory,
686 //.write_memory = arm7_9_write_memory,
687 .read_memory
= arm946e_read_memory
,
688 .write_memory
= arm946e_write_memory
,
690 .bulk_write_memory
= arm7_9_bulk_write_memory
,
692 .checksum_memory
= arm_checksum_memory
,
693 .blank_check_memory
= arm_blank_check_memory
,
695 .run_algorithm
= armv4_5_run_algorithm
,
697 .add_breakpoint
= arm7_9_add_breakpoint
,
698 .remove_breakpoint
= arm7_9_remove_breakpoint
,
699 //.add_breakpoint = arm946e_add_breakpoint,
700 //.remove_breakpoint = arm946e_remove_breakpoint,
702 .add_watchpoint
= arm7_9_add_watchpoint
,
703 .remove_watchpoint
= arm7_9_remove_watchpoint
,
705 .commands
= arm946e_command_handlers
,
706 .target_create
= arm946e_target_create
,
707 .init_target
= arm9tdmi_init_target
,
708 .examine
= arm7_9_examine
,
709 .check_reset
= arm7_9_check_reset
,
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)