1 /***************************************************************************
2 * Copyright (C) 2013-2014,2019-2020 Synopsys, Inc. *
3 * Frank Dols <frank.dols@synopsys.com> *
4 * Mischa Jonker <mischa.jonker@synopsys.com> *
5 * Anton Kolesov <anton.kolesov@synopsys.com> *
6 * Evgeniy Didin <didin@synopsys.com> *
8 * SPDX-License-Identifier: GPL-2.0-or-later *
9 ***************************************************************************/
17 /* ----- Supporting functions ---------------------------------------------- */
18 static bool arc_mem_is_slow_memory(struct arc_common
*arc
, uint32_t addr
,
19 uint32_t size
, uint32_t count
)
21 uint32_t addr_end
= addr
+ size
* count
;
22 /* `_end` field can overflow - it points to the first byte after the end,
23 * therefore if DCCM is right at the end of memory address space, then
24 * dccm_end will be 0. */
25 assert(addr_end
>= addr
|| addr_end
== 0);
27 return !((addr
>= arc
->dccm_start
&& addr_end
<= arc
->dccm_end
) ||
28 (addr
>= arc
->iccm0_start
&& addr_end
<= arc
->iccm0_end
) ||
29 (addr
>= arc
->iccm1_start
&& addr_end
<= arc
->iccm1_end
));
32 /* Write word at word-aligned address */
33 static int arc_mem_write_block32(struct target
*target
, uint32_t addr
,
34 uint32_t count
, void *buf
)
36 struct arc_common
*arc
= target_to_arc(target
);
38 LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32
", count=%" PRIu32
,
44 /* No need to flush cache, because we don't read values from memory. */
45 CHECK_RETVAL(arc_jtag_write_memory(&arc
->jtag_info
, addr
, count
,
51 /* Write half-word at half-word-aligned address */
52 static int arc_mem_write_block16(struct target
*target
, uint32_t addr
,
53 uint32_t count
, void *buf
)
55 struct arc_common
*arc
= target_to_arc(target
);
58 uint8_t buffer_te
[sizeof(uint32_t)];
59 uint8_t halfword_te
[sizeof(uint16_t)];
61 LOG_DEBUG("Write 2-byte memory block: addr=0x%08" PRIx32
", count=%" PRIu32
,
67 /* non-word writes are less common, than 4-byte writes, so I suppose we can
68 * allowe ourselves to write this in a cycle, instead of calling arc_jtag
70 for (i
= 0; i
< count
; i
++) {
71 /* We can read only word at word-aligned address. Also *jtag_read_memory
72 * functions return data in host endianness, so host endianness !=
73 * target endianness we have to convert data back to target endianness,
74 * or bytes will be at the wrong places.So:
76 * 2) convert to target endianness
78 * 4) convert back to host endianness
79 * 5) write word back to target.
81 bool is_slow_memory
= arc_mem_is_slow_memory(arc
,
82 (addr
+ i
* sizeof(uint16_t)) & ~3u, 4, 1);
83 CHECK_RETVAL(arc_jtag_read_memory(&arc
->jtag_info
,
84 (addr
+ i
* sizeof(uint16_t)) & ~3u, 1, &buffer_he
,
86 target_buffer_set_u32(target
, buffer_te
, buffer_he
);
88 /* buf is in host endianness, convert to target */
89 target_buffer_set_u16(target
, halfword_te
, ((uint16_t *)buf
)[i
]);
91 memcpy(buffer_te
+ ((addr
+ i
* sizeof(uint16_t)) & 3u),
92 halfword_te
, sizeof(uint16_t));
94 buffer_he
= target_buffer_get_u32(target
, buffer_te
);
96 CHECK_RETVAL(arc_jtag_write_memory(&arc
->jtag_info
,
97 (addr
+ i
* sizeof(uint16_t)) & ~3u, 1, &buffer_he
));
103 /* Write byte at address */
104 static int arc_mem_write_block8(struct target
*target
, uint32_t addr
,
105 uint32_t count
, void *buf
)
107 struct arc_common
*arc
= target_to_arc(target
);
110 uint8_t buffer_te
[sizeof(uint32_t)];
113 LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32
", count=%" PRIu32
,
116 /* non-word writes are less common, than 4-byte writes, so I suppose we can
117 * allowe ourselves to write this in a cycle, instead of calling arc_jtag
119 for (i
= 0; i
< count
; i
++) {
120 /* See comment in arc_mem_write_block16 for details. Since it is a byte
121 * there is not need to convert write buffer to target endianness, but
122 * we still have to convert read buffer. */
123 CHECK_RETVAL(arc_jtag_read_memory(&arc
->jtag_info
, (addr
+ i
) & ~3, 1, &buffer_he
,
124 arc_mem_is_slow_memory(arc
, (addr
+ i
) & ~3, 4, 1)));
125 target_buffer_set_u32(target
, buffer_te
, buffer_he
);
126 memcpy(buffer_te
+ ((addr
+ i
) & 3), (uint8_t *)buf
+ i
, 1);
127 buffer_he
= target_buffer_get_u32(target
, buffer_te
);
128 CHECK_RETVAL(arc_jtag_write_memory(&arc
->jtag_info
, (addr
+ i
) & ~3, 1, &buffer_he
));
134 /* ----- Exported functions ------------------------------------------------ */
135 int arc_mem_write(struct target
*target
, target_addr_t address
, uint32_t size
,
136 uint32_t count
, const uint8_t *buffer
)
138 int retval
= ERROR_OK
;
141 LOG_DEBUG("address: 0x%08" TARGET_PRIxADDR
", size: %" PRIu32
", count: %" PRIu32
,
142 address
, size
, count
);
144 if (target
->state
!= TARGET_HALTED
) {
145 LOG_WARNING("target not halted");
146 return ERROR_TARGET_NOT_HALTED
;
149 /* sanitize arguments */
150 if (((size
!= 4) && (size
!= 2) && (size
!= 1)) || !(count
) || !(buffer
))
151 return ERROR_COMMAND_SYNTAX_ERROR
;
153 if (((size
== 4) && (address
& 0x3u
)) || ((size
== 2) && (address
& 0x1u
)))
154 return ERROR_TARGET_UNALIGNED_ACCESS
;
156 /* correct endianess if we have word or hword access */
159 * arc_..._write_mem with size 4/2 requires uint32_t/uint16_t
160 * in host endianness, but byte array represents target endianness.
162 tunnel
= calloc(1, count
* size
* sizeof(uint8_t));
165 LOG_ERROR("Unable to allocate memory");
171 target_buffer_get_u32_array(target
, buffer
, count
,
175 target_buffer_get_u16_array(target
, buffer
, count
,
183 retval
= arc_mem_write_block32(target
, address
, count
, (void *)buffer
);
184 } else if (size
== 2) {
185 /* We convert buffer from host endianness to target. But then in
186 * write_block16, we do the reverse. Is there a way to avoid this without
187 * breaking other cases? */
188 retval
= arc_mem_write_block16(target
, address
, count
, (void *)buffer
);
190 retval
= arc_mem_write_block8(target
, address
, count
, (void *)buffer
);
198 static int arc_mem_read_block(struct target
*target
, target_addr_t addr
,
199 uint32_t size
, uint32_t count
, void *buf
)
201 struct arc_common
*arc
= target_to_arc(target
);
203 LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR
", size=%" PRIu32
204 ", count=%" PRIu32
, addr
, size
, count
);
208 CHECK_RETVAL(arc_jtag_read_memory(&arc
->jtag_info
, addr
, count
, buf
,
209 arc_mem_is_slow_memory(arc
, addr
, size
, count
)));
214 int arc_mem_read(struct target
*target
, target_addr_t address
, uint32_t size
,
215 uint32_t count
, uint8_t *buffer
)
217 int retval
= ERROR_OK
;
220 uint32_t words_to_read
, bytes_to_read
;
223 LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR
", size=%" PRIu32
224 ", count=%" PRIu32
, address
, size
, count
);
226 if (target
->state
!= TARGET_HALTED
) {
227 LOG_WARNING("target not halted");
228 return ERROR_TARGET_NOT_HALTED
;
231 /* Sanitize arguments */
232 if (((size
!= 4) && (size
!= 2) && (size
!= 1)) || !(count
) || !(buffer
))
233 return ERROR_COMMAND_SYNTAX_ERROR
;
235 if (((size
== 4) && (address
& 0x3u
)) || ((size
== 2) && (address
& 0x1u
)))
236 return ERROR_TARGET_UNALIGNED_ACCESS
;
238 /* Reads are word-aligned, so padding might be required if count > 1.
239 * NB: +3 is a padding for the last word (in case it's not aligned;
240 * addr&3 is a padding for the first word (since address can be
241 * unaligned as well). */
242 bytes_to_read
= (count
* size
+ 3 + (address
& 3u)) & ~3u;
243 words_to_read
= bytes_to_read
>> 2;
244 tunnel_he
= calloc(1, bytes_to_read
);
245 tunnel_te
= calloc(1, bytes_to_read
);
247 if (!tunnel_he
|| !tunnel_te
) {
248 LOG_ERROR("Unable to allocate memory");
254 /* We can read only word-aligned words. */
255 retval
= arc_mem_read_block(target
, address
& ~3u, sizeof(uint32_t),
256 words_to_read
, tunnel_he
);
258 /* arc_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */
259 /* endianness, but byte array should represent target endianness */
261 if (ERROR_OK
== retval
) {
264 target_buffer_set_u32_array(target
, buffer
, count
,
268 target_buffer_set_u32_array(target
, tunnel_te
,
269 words_to_read
, tunnel_he
);
270 /* Will that work properly with count > 1 and big endian? */
271 memcpy(buffer
, tunnel_te
+ (address
& 3u),
272 count
* sizeof(uint16_t));
275 target_buffer_set_u32_array(target
, tunnel_te
,
276 words_to_read
, tunnel_he
);
277 /* Will that work properly with count > 1 and big endian? */
278 memcpy(buffer
, tunnel_te
+ (address
& 3u), count
);
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)