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 ***************************************************************************/
32 #include "target_type.h"
33 #include "arm_opcodes.h"
35 #include "breakpoints.h"
38 #define _DEBUG_INSTRUCTION_EXECUTION_
41 #define NB_CACHE_WAYS 4
44 #define CP15_CTL_DCACHE (1<<2)
45 #define CP15_CTL_ICACHE (1<<12)
48 * flag to give info about cache manipulation during debug :
49 * "0" - cache lines are invalidated "on the fly", for affected addresses.
50 * This is prefered from performance point of view.
51 * "1" - cache is invalidated and switched off on debug_entry, and switched back on on restore.
52 * It is kept off during debugging.
54 static uint8_t arm946e_preserve_cache
;
56 int arm946e_post_debug_entry(struct target
*target
);
57 void arm946e_pre_restore_context(struct target
*target
);
58 static int arm946e_read_cp15(struct target
*target
, int reg_addr
, uint32_t *value
);
60 int arm946e_init_arch_info(struct target
*target
,
61 struct arm946e_common
*arm946e
,
64 struct arm7_9_common
*arm7_9
= &arm946e
->arm7_9_common
;
66 /* initialize arm7/arm9 specific info (including armv4_5) */
67 arm9tdmi_init_arch_info(target
, arm7_9
, tap
);
69 arm946e
->common_magic
= ARM946E_COMMON_MAGIC
;
72 * The ARM946E-S implements the ARMv5TE architecture which
73 * has the BKPT instruction, so we don't have to use a watchpoint comparator
75 arm7_9
->arm_bkpt
= ARMV5_BKPT(0x0);
76 arm7_9
->thumb_bkpt
= ARMV5_T_BKPT(0x0) & 0xffff;
79 arm7_9
->post_debug_entry
= arm946e_post_debug_entry
;
80 arm7_9
->pre_restore_context
= arm946e_pre_restore_context
;
83 * disabling linefills leads to lockups, so keep them enabled for now
84 * this doesn't affect correctness, but might affect timing issues, if
85 * important data is evicted from the cache during the debug session
87 arm946e_preserve_cache
= 0;
89 /* override hw single-step capability from ARM9TDMI */
90 /* arm7_9->has_single_step = 1; */
95 static int arm946e_target_create(struct target
*target
, Jim_Interp
*interp
)
97 struct arm946e_common
*arm946e
= calloc(1, sizeof(struct arm946e_common
));
99 arm946e_init_arch_info(target
, arm946e
, target
->tap
);
104 static int arm946e_verify_pointer(struct command_context
*cmd_ctx
,
105 struct arm946e_common
*arm946e
)
107 if (arm946e
->common_magic
!= ARM946E_COMMON_MAGIC
) {
108 command_print(cmd_ctx
, "target is not an ARM946");
109 return ERROR_TARGET_INVALID
;
115 * Update cp15_control_reg, saved on debug_entry.
117 static void arm946e_update_cp15_caches(struct target
*target
, uint32_t value
)
119 struct arm946e_common
*arm946e
= target_to_arm946(target
);
120 arm946e
->cp15_control_reg
= (arm946e
->cp15_control_reg
& ~(CP15_CTL_DCACHE
|CP15_CTL_ICACHE
))
121 | (value
& (CP15_CTL_DCACHE
|CP15_CTL_ICACHE
));
125 * REVISIT: The "read_cp15" and "write_cp15" commands could hook up
126 * to eventual mrc() and mcr() routines ... the reg_addr values being
127 * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
128 * See section 7.3 of the ARM946E-S TRM.
130 static int arm946e_read_cp15(struct target
*target
, int reg_addr
, uint32_t *value
)
132 int retval
= ERROR_OK
;
133 struct arm7_9_common
*arm7_9
= target_to_arm7_9(target
);
134 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
135 struct scan_field fields
[3];
136 uint8_t reg_addr_buf
= reg_addr
& 0x3f;
137 uint8_t nr_w_buf
= 0;
139 retval
= arm_jtag_scann(jtag_info
, 0xf, TAP_IDLE
);
140 if (retval
!= ERROR_OK
)
142 retval
= arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
, TAP_IDLE
);
143 if (retval
!= ERROR_OK
)
146 fields
[0].num_bits
= 32;
147 /* REVISIT: table 7-2 shows that bits 31-31 need to be
148 * specified for accessing BIST registers ...
150 fields
[0].out_value
= NULL
;
151 fields
[0].in_value
= NULL
;
153 fields
[1].num_bits
= 6;
154 fields
[1].out_value
= ®_addr_buf
;
155 fields
[1].in_value
= NULL
;
157 fields
[2].num_bits
= 1;
158 fields
[2].out_value
= &nr_w_buf
;
159 fields
[2].in_value
= NULL
;
161 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_IDLE
);
163 fields
[0].in_value
= (uint8_t *)value
;
164 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_IDLE
);
166 jtag_add_callback(arm_le_to_h_u32
, (jtag_callback_data_t
)value
);
168 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
169 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr
, *value
);
172 retval
= jtag_execute_queue();
173 if (retval
!= ERROR_OK
)
179 int arm946e_write_cp15(struct target
*target
, int reg_addr
, uint32_t value
)
181 int retval
= ERROR_OK
;
182 struct arm7_9_common
*arm7_9
= target_to_arm7_9(target
);
183 struct arm_jtag
*jtag_info
= &arm7_9
->jtag_info
;
184 struct scan_field fields
[3];
185 uint8_t reg_addr_buf
= reg_addr
& 0x3f;
186 uint8_t nr_w_buf
= 1;
187 uint8_t value_buf
[4];
189 buf_set_u32(value_buf
, 0, 32, value
);
191 retval
= arm_jtag_scann(jtag_info
, 0xf, TAP_IDLE
);
192 if (retval
!= ERROR_OK
)
194 retval
= arm_jtag_set_instr(jtag_info
, jtag_info
->intest_instr
, NULL
, TAP_IDLE
);
195 if (retval
!= ERROR_OK
)
198 fields
[0].num_bits
= 32;
199 fields
[0].out_value
= value_buf
;
200 fields
[0].in_value
= NULL
;
202 fields
[1].num_bits
= 6;
203 fields
[1].out_value
= ®_addr_buf
;
204 fields
[1].in_value
= NULL
;
206 fields
[2].num_bits
= 1;
207 fields
[2].out_value
= &nr_w_buf
;
208 fields
[2].in_value
= NULL
;
210 jtag_add_dr_scan(jtag_info
->tap
, 3, fields
, TAP_IDLE
);
212 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
213 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr
, value
);
216 retval
= jtag_execute_queue();
217 if (retval
!= ERROR_OK
)
223 #define GET_ICACHE_SIZE 6
224 #define GET_DCACHE_SIZE 18
227 * \param target struct target pointer
228 * \param idsel select GET_ICACHE_SIZE or GET_DCACHE_SIZE
229 * \returns cache size, given in bytes
231 static uint32_t arm946e_cp15_get_csize(struct target
*target
, int idsel
)
233 struct arm946e_common
*arm946e
= target_to_arm946(target
);
234 uint32_t csize
= arm946e
->cp15_cache_info
;
236 if (arm946e_read_cp15(target
, 0x01, &csize
) == ERROR_OK
)
237 arm946e
->cp15_cache_info
= csize
;
239 if (csize
& (1<<(idsel
-4))) /* cache absent */
241 csize
= (csize
>> idsel
) & 0x0F;
242 return csize
? 1 << (12 + (csize
-3)) : 0;
245 uint32_t arm946e_invalidate_whole_dcache(struct target
*target
)
247 uint32_t csize
= arm946e_cp15_get_csize(target
, GET_DCACHE_SIZE
);
249 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
251 /* One line (index) is 32 bytes (8 words) long, 4-way assoc
252 * ARM DDI 0201D, Section 3.3.5
254 int nb_idx
= (csize
/ (4*8*NB_CACHE_WAYS
)); /* gives nb of lines (indexes) in the cache */
256 /* Loop for all segmentde (i.e. ways) */
258 for (seg
= 0; seg
< NB_CACHE_WAYS
; seg
++) {
259 /* Loop for all indexes */
261 for (idx
= 0; idx
< nb_idx
; idx
++) {
262 /* Form and write cp15 index (segment + line idx) */
263 uint32_t cp15_idx
= seg
<< 30 | idx
<< 5;
264 int retval
= arm946e_write_cp15(target
, 0x3a, cp15_idx
);
265 if (retval
!= ERROR_OK
) {
266 LOG_DEBUG("ERROR writing index");
272 arm946e_read_cp15(target
, 0x16, (uint32_t *) &dtag
);
274 /* Check cache line VALID bit */
275 if (!(dtag
>> 4 & 0x1))
278 /* Clean data cache line */
279 retval
= arm946e_write_cp15(target
, 0x35, 0x1);
280 if (retval
!= ERROR_OK
) {
281 LOG_DEBUG("ERROR cleaning cache line");
285 /* Flush data cache line */
286 retval
= arm946e_write_cp15(target
, 0x1a, 0x1);
287 if (retval
!= ERROR_OK
) {
288 LOG_DEBUG("ERROR flushing cache line");
297 uint32_t arm946e_invalidate_whole_icache(struct target
*target
)
299 /* Check cache presence before flushing - avoid undefined behavior */
300 uint32_t csize
= arm946e_cp15_get_csize(target
, GET_ICACHE_SIZE
);
302 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
304 LOG_DEBUG("FLUSHING I$");
306 * Invalidate (flush) I$
307 * mcr 15, 0, r0, cr7, cr5, {0}
309 int retval
= arm946e_write_cp15(target
, 0x0f, 0x1);
310 if (retval
!= ERROR_OK
) {
311 LOG_DEBUG("ERROR flushing I$");
318 int arm946e_post_debug_entry(struct target
*target
)
320 uint32_t ctr_reg
= 0x0;
321 uint32_t retval
= ERROR_OK
;
322 struct arm946e_common
*arm946e
= target_to_arm946(target
);
324 /* See if CACHES are enabled, and save that info
325 * in the context bits, so that arm946e_pre_restore_context() can use them */
326 arm946e_read_cp15(target
, CP15_CTL
, (uint32_t *) &ctr_reg
);
328 /* Save control reg in the context */
329 arm946e
->cp15_control_reg
= ctr_reg
;
331 if (arm946e_preserve_cache
) {
332 if (ctr_reg
& CP15_CTL_DCACHE
) {
333 /* Clean and flush D$ */
334 arm946e_invalidate_whole_dcache(target
);
337 ctr_reg
&= ~CP15_CTL_DCACHE
;
340 if (ctr_reg
& CP15_CTL_ICACHE
) {
342 arm946e_invalidate_whole_icache(target
);
345 ctr_reg
&= ~CP15_CTL_ICACHE
;
348 /* Write the new configuration */
349 retval
= arm946e_write_cp15(target
, CP15_CTL
, ctr_reg
);
350 if (retval
!= ERROR_OK
) {
351 LOG_DEBUG("ERROR disabling cache");
354 } /* if preserve_cache */
359 void arm946e_pre_restore_context(struct target
*target
)
361 uint32_t ctr_reg
= 0x0;
364 if (arm946e_preserve_cache
) {
365 struct arm946e_common
*arm946e
= target_to_arm946(target
);
366 /* Get the contents of the CTR reg */
367 arm946e_read_cp15(target
, CP15_CTL
, (uint32_t *) &ctr_reg
);
370 * Read-modify-write CP15 control
371 * to reenable I/D-cache operation
372 * NOTE: It is not possible to disable cache by CP15.
373 * if arm946e_preserve_cache debugging flag enabled.
375 ctr_reg
|= arm946e
->cp15_control_reg
& (CP15_CTL_DCACHE
|CP15_CTL_ICACHE
);
377 /* Write the new configuration */
378 retval
= arm946e_write_cp15(target
, CP15_CTL
, ctr_reg
);
379 if (retval
!= ERROR_OK
)
380 LOG_DEBUG("ERROR enabling cache");
381 } /* if preserve_cache */
384 uint32_t arm946e_invalidate_dcache(struct target
*target
, uint32_t address
,
385 uint32_t size
, uint32_t count
)
387 uint32_t cur_addr
= 0x0;
388 uint32_t cp15_idx
, set
, way
, dtag
;
392 for (i
= 0; i
< count
*size
; i
++) {
393 cur_addr
= address
+ i
;
396 set
= (cur_addr
>> 5) & 0xff; /* set field is 8 bits long */
398 for (way
= 0; way
< NB_CACHE_WAYS
; way
++) {
400 * Find if the affected address is kept in the cache.
401 * Because JTAG Scan Chain 15 offers limited approach,
402 * we have to loop through all cache ways (segments) and
403 * read cache tags, then compare them with with address.
406 /* Form and write cp15 index (segment + line idx) */
407 cp15_idx
= way
<< 30 | set
<< 5;
408 retval
= arm946e_write_cp15(target
, 0x3a, cp15_idx
);
409 if (retval
!= ERROR_OK
) {
410 LOG_DEBUG("ERROR writing index");
415 arm946e_read_cp15(target
, 0x16, (uint32_t *) &dtag
);
417 /* Check cache line VALID bit */
418 if (!(dtag
>> 4 & 0x1))
421 /* If line is valid and corresponds to affected address - invalidate it */
422 if (dtag
>> 5 == cur_addr
>> 5) {
423 /* Clean data cache line */
424 retval
= arm946e_write_cp15(target
, 0x35, 0x1);
425 if (retval
!= ERROR_OK
) {
426 LOG_DEBUG("ERROR cleaning cache line");
430 /* Flush data cache line */
431 retval
= arm946e_write_cp15(target
, 0x1c, 0x1);
432 if (retval
!= ERROR_OK
) {
433 LOG_DEBUG("ERROR flushing cache line");
439 } /* loop through all 4 ways */
440 } /* loop through all addresses */
445 uint32_t arm946e_invalidate_icache(struct target
*target
, uint32_t address
,
446 uint32_t size
, uint32_t count
)
448 uint32_t cur_addr
= 0x0;
449 uint32_t cp15_idx
, set
, way
, itag
;
453 for (i
= 0; i
< count
*size
; i
++) {
454 cur_addr
= address
+ i
;
456 set
= (cur_addr
>> 5) & 0xff; /* set field is 8 bits long */
458 for (way
= 0; way
< NB_CACHE_WAYS
; way
++) {
459 /* Form and write cp15 index (segment + line idx) */
460 cp15_idx
= way
<< 30 | set
<< 5;
461 retval
= arm946e_write_cp15(target
, 0x3a, cp15_idx
);
462 if (retval
!= ERROR_OK
) {
463 LOG_DEBUG("ERROR writing index");
468 arm946e_read_cp15(target
, 0x17, (uint32_t *) &itag
);
470 /* Check cache line VALID bit */
471 if (!(itag
>> 4 & 0x1))
474 /* If line is valid and corresponds to affected address - invalidate it */
475 if (itag
>> 5 == cur_addr
>> 5) {
477 retval
= arm946e_write_cp15(target
, 0x1d, 0x0);
478 if (retval
!= ERROR_OK
) {
479 LOG_DEBUG("ERROR flushing cache line");
491 /** Writes a buffer, in the specified word size, with current MMU settings. */
492 int arm946e_write_memory(struct target
*target
, uint32_t address
,
493 uint32_t size
, uint32_t count
, const uint8_t *buffer
)
499 struct arm946e_common
*arm946e
= target_to_arm946(target
);
500 /* Invalidate D$ if it is ON */
501 if (!arm946e_preserve_cache
&& (arm946e
->cp15_control_reg
& CP15_CTL_DCACHE
))
502 arm946e_invalidate_dcache(target
, address
, size
, count
);
507 retval
= arm7_9_write_memory(target
, address
, size
, count
, buffer
);
508 if (retval
!= ERROR_OK
)
512 * Invalidate I$ if it is ON.
514 * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
515 * because arm7_9_write_memory() has seen non-valid bit in D$
516 * and wrote data into physical RAM (without touching or allocating the cache line).
517 * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
518 * policy for both I$ and D$ (Chapter 3.2 and 3.3)
521 * "ARM system developer's guide: designing and optimizing system software" by
522 * Andrew N. Sloss, Dominic Symes and Chris Wright,
523 * Chapter 12.3.3 Allocating Policy on a Cache Miss :
524 * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
525 * If the victim cache line contains valid data, then it is written to main memory before the cache line
526 * is filled with new data.
527 * Under this strategy, a write of new data to memory does not update the contents of the cache memory
528 * unless a cache line was allocated on a previous read from main memory.
529 * If the cache line contains valid data, then the write updates the cache and may update the main memory if
530 * the cache write policy is write-through.
531 * If the data is not in the cache, the controller writes to main memory only.
533 if (!arm946e_preserve_cache
&& (arm946e
->cp15_control_reg
& CP15_CTL_ICACHE
))
534 arm946e_invalidate_icache(target
, address
, size
, count
);
540 int arm946e_read_memory(struct target
*target
, uint32_t address
,
541 uint32_t size
, uint32_t count
, uint8_t *buffer
)
547 retval
= arm7_9_read_memory(target
, address
, size
, count
, buffer
);
548 if (retval
!= ERROR_OK
)
554 static int jim_arm946e_cp15(Jim_Interp
*interp
, int argc
, Jim_Obj
* const *argv
)
556 /* one or two arguments, access a single register (write if second argument is given) */
557 if (argc
< 2 || argc
> 3) {
558 Jim_WrongNumArgs(interp
, 1, argv
, "addr [value]");
562 struct command_context
*cmd_ctx
= current_command_context(interp
);
563 assert(cmd_ctx
!= NULL
);
565 struct target
*target
= get_current_target(cmd_ctx
);
566 if (target
== NULL
) {
567 LOG_ERROR("arm946e: no current target");
571 struct arm946e_common
*arm946e
= target_to_arm946(target
);
572 int retval
= arm946e_verify_pointer(cmd_ctx
, arm946e
);
573 if (retval
!= ERROR_OK
)
576 if (target
->state
!= TARGET_HALTED
) {
577 command_print(cmd_ctx
, "target %s must be stopped for \"cp15\" command", target_name(target
));
583 retval
= Jim_GetLong(interp
, argv
[1], &l
);
585 if (JIM_OK
!= retval
)
590 retval
= arm946e_read_cp15(target
, address
, &value
);
591 if (retval
!= ERROR_OK
) {
592 command_print(cmd_ctx
, "%s cp15 reg %" PRIi32
" access failed", target_name(target
), address
);
595 retval
= jtag_execute_queue();
596 if (retval
!= ERROR_OK
)
599 sprintf(buf
, "0x%08x", value
);
600 /* Return value in hex format */
601 Jim_SetResultString(interp
, buf
, -1);
602 } else if (argc
== 3) {
604 retval
= Jim_GetLong(interp
, argv
[2], &l
);
606 if (JIM_OK
!= retval
)
608 retval
= arm946e_write_cp15(target
, address
, value
);
609 if (retval
!= ERROR_OK
) {
610 command_print(cmd_ctx
, "%s cp15 reg %" PRIi32
" access failed", target_name(target
), address
);
613 if (address
== CP15_CTL
)
614 arm946e_update_cp15_caches(target
, value
);
620 COMMAND_HANDLER(arm946e_handle_idcache
)
623 return ERROR_COMMAND_SYNTAX_ERROR
;
626 struct target
*target
= get_current_target(CMD_CTX
);
627 struct arm946e_common
*arm946e
= target_to_arm946(target
);
629 retval
= arm946e_verify_pointer(CMD_CTX
, arm946e
);
630 if (retval
!= ERROR_OK
)
633 if (target
->state
!= TARGET_HALTED
) {
634 command_print(CMD_CTX
, "target must be stopped for \"%s\" command", CMD_NAME
);
635 return ERROR_TARGET_NOT_HALTED
;
638 bool icache
= (strcmp(CMD_NAME
, "icache") == 0);
639 uint32_t csize
= arm946e_cp15_get_csize(target
, icache
? GET_ICACHE_SIZE
: GET_DCACHE_SIZE
) / 1024;
641 bool bena
= ((arm946e
->cp15_control_reg
& (icache
? CP15_CTL_ICACHE
: CP15_CTL_DCACHE
)) != 0)
642 && (arm946e
->cp15_control_reg
& 0x1);
644 command_print(CMD_CTX
, "%s-cache absent", icache
? "I" : "D");
646 command_print(CMD_CTX
, "%s-cache size: %dK, %s", icache
? "I" : "D", csize
, bena
? "enabled" : "disabled");
652 retval
= command_parse_bool_arg(CMD_ARGV
[0], &enable
);
653 if (retval
== ERROR_COMMAND_SYNTAX_ERROR
) {
654 if (strcmp(CMD_ARGV
[0], "flush") == 0) {
661 /* Do not invalidate or change state, if cache is absent */
663 command_print(CMD_CTX
, "%s-cache absent, '%s' operation undefined", icache
? "I" : "D", CMD_ARGV
[0]);
664 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
667 /* NOTE: flushing entire cache will not preserve lock-down cache regions */
669 if ((arm946e
->cp15_control_reg
& CP15_CTL_ICACHE
) && !enable
)
670 retval
= arm946e_invalidate_whole_icache(target
);
672 if ((arm946e
->cp15_control_reg
& CP15_CTL_DCACHE
) && !enable
)
673 retval
= arm946e_invalidate_whole_dcache(target
);
676 if (retval
!= ERROR_OK
|| flush
)
680 retval
= arm946e_read_cp15(target
, CP15_CTL
, &value
);
681 if (retval
!= ERROR_OK
)
684 uint32_t vnew
= value
;
685 uint32_t cmask
= icache
? CP15_CTL_ICACHE
: CP15_CTL_DCACHE
;
687 if ((value
& 0x1) == 0)
688 LOG_WARNING("arm946e: MPU must be enabled for cache to operate");
696 retval
= arm946e_write_cp15(target
, CP15_CTL
, vnew
);
697 if (retval
!= ERROR_OK
)
700 arm946e_update_cp15_caches(target
, vnew
);
704 static const struct command_registration arm946e_exec_command_handlers
[] = {
707 .jim_handler
= jim_arm946e_cp15
,
708 .mode
= COMMAND_EXEC
,
709 .usage
= "regnum [value]",
710 .help
= "read/modify cp15 register",
714 .handler
= arm946e_handle_idcache
,
715 .mode
= COMMAND_EXEC
,
716 .usage
= "['enable'|'disable'|'flush']",
717 .help
= "I-cache info and operations",
721 .handler
= arm946e_handle_idcache
,
722 .mode
= COMMAND_EXEC
,
723 .usage
= "['enable'|'disable'|'flush']",
724 .help
= "D-cache info and operations",
726 COMMAND_REGISTRATION_DONE
729 const struct command_registration arm946e_command_handlers
[] = {
731 .chain
= arm9tdmi_command_handlers
,
736 .help
= "arm946e command group",
738 .chain
= arm946e_exec_command_handlers
,
740 COMMAND_REGISTRATION_DONE
743 /** Holds methods for ARM946 targets. */
744 struct target_type arm946e_target
= {
748 .arch_state
= arm_arch_state
,
750 .target_request_data
= arm7_9_target_request_data
,
753 .resume
= arm7_9_resume
,
756 .assert_reset
= arm7_9_assert_reset
,
757 .deassert_reset
= arm7_9_deassert_reset
,
758 .soft_reset_halt
= arm7_9_soft_reset_halt
,
760 .get_gdb_reg_list
= arm_get_gdb_reg_list
,
762 /* .read_memory = arm7_9_read_memory, */
763 /* .write_memory = arm7_9_write_memory, */
764 .read_memory
= arm946e_read_memory
,
765 .write_memory
= arm946e_write_memory
,
767 .bulk_write_memory
= arm7_9_bulk_write_memory
,
769 .checksum_memory
= arm_checksum_memory
,
770 .blank_check_memory
= arm_blank_check_memory
,
772 .run_algorithm
= armv4_5_run_algorithm
,
774 .add_breakpoint
= arm7_9_add_breakpoint
,
775 .remove_breakpoint
= arm7_9_remove_breakpoint
,
776 /* .add_breakpoint = arm946e_add_breakpoint, */
777 /* .remove_breakpoint = arm946e_remove_breakpoint, */
779 .add_watchpoint
= arm7_9_add_watchpoint
,
780 .remove_watchpoint
= arm7_9_remove_watchpoint
,
782 .commands
= arm946e_command_handlers
,
783 .target_create
= arm946e_target_create
,
784 .init_target
= arm9tdmi_init_target
,
785 .examine
= arm7_9_examine
,
786 .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)