1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2016-2020 by Marc Schink <dev@zapb.de>
13 #include <helper/log.h>
14 #include <helper/binarybuffer.h>
15 #include <helper/command.h>
20 static int read_rtt_channel(struct target
*target
,
21 const struct rtt_control
*ctrl
, unsigned int channel_index
,
22 enum rtt_channel_type type
, struct rtt_channel
*channel
)
25 uint8_t buf
[RTT_CHANNEL_SIZE
];
26 target_addr_t address
;
28 address
= ctrl
->address
+ RTT_CB_SIZE
+ (channel_index
* RTT_CHANNEL_SIZE
);
30 if (type
== RTT_CHANNEL_TYPE_DOWN
)
31 address
+= ctrl
->num_up_channels
* RTT_CHANNEL_SIZE
;
33 ret
= target_read_buffer(target
, address
, RTT_CHANNEL_SIZE
, buf
);
38 channel
->address
= address
;
39 channel
->name_addr
= buf_get_u32(buf
+ 0, 0, 32);
40 channel
->buffer_addr
= buf_get_u32(buf
+ 4, 0, 32);
41 channel
->size
= buf_get_u32(buf
+ 8, 0, 32);
42 channel
->write_pos
= buf_get_u32(buf
+ 12, 0, 32);
43 channel
->read_pos
= buf_get_u32(buf
+ 16, 0, 32);
44 channel
->flags
= buf_get_u32(buf
+ 20, 0, 32);
49 int target_rtt_start(struct target
*target
, const struct rtt_control
*ctrl
,
55 int target_rtt_stop(struct target
*target
, void *user_data
)
60 static int read_channel_name(struct target
*target
, target_addr_t address
,
61 char *name
, size_t length
)
67 while (offset
< length
) {
71 read_length
= MIN(32, length
- offset
);
72 ret
= target_read_buffer(target
, address
+ offset
, read_length
,
73 (uint8_t *)name
+ offset
);
78 if (memchr(name
+ offset
, '\0', read_length
))
81 offset
+= read_length
;
84 name
[length
- 1] = '\0';
89 static int write_to_channel(struct target
*target
,
90 const struct rtt_channel
*channel
, const uint8_t *buffer
,
99 if (channel
->write_pos
== channel
->read_pos
) {
100 uint32_t first_length
;
102 len
= MIN(*length
, channel
->size
- 1);
103 first_length
= MIN(len
, channel
->size
- channel
->write_pos
);
105 ret
= target_write_buffer(target
,
106 channel
->buffer_addr
+ channel
->write_pos
, first_length
,
112 ret
= target_write_buffer(target
, channel
->buffer_addr
,
113 len
- first_length
, buffer
+ first_length
);
117 } else if (channel
->write_pos
< channel
->read_pos
) {
118 len
= MIN(*length
, channel
->read_pos
- channel
->write_pos
- 1);
125 ret
= target_write_buffer(target
,
126 channel
->buffer_addr
+ channel
->write_pos
, len
, buffer
);
131 uint32_t first_length
;
134 channel
->size
- channel
->write_pos
+ channel
->read_pos
- 1);
141 first_length
= MIN(len
, channel
->size
- channel
->write_pos
);
143 ret
= target_write_buffer(target
,
144 channel
->buffer_addr
+ channel
->write_pos
, first_length
,
150 buffer
= buffer
+ first_length
;
152 ret
= target_write_buffer(target
, channel
->buffer_addr
,
153 len
- first_length
, buffer
);
159 ret
= target_write_u32(target
, channel
->address
+ 12,
160 (channel
->write_pos
+ len
) % channel
->size
);
170 static bool channel_is_active(const struct rtt_channel
*channel
)
181 int target_rtt_write_callback(struct target
*target
, struct rtt_control
*ctrl
,
182 unsigned int channel_index
, const uint8_t *buffer
, size_t *length
,
186 struct rtt_channel channel
;
188 ret
= read_rtt_channel(target
, ctrl
, channel_index
,
189 RTT_CHANNEL_TYPE_DOWN
, &channel
);
191 if (ret
!= ERROR_OK
) {
192 LOG_ERROR("rtt: Failed to read down-channel %u description",
197 if (!channel_is_active(&channel
)) {
198 LOG_WARNING("rtt: Down-channel %u is not active", channel_index
);
202 if (channel
.size
< RTT_CHANNEL_BUFFER_MIN_SIZE
) {
203 LOG_WARNING("rtt: Down-channel %u is not large enough",
208 ret
= write_to_channel(target
, &channel
, buffer
, length
);
213 LOG_DEBUG("rtt: Wrote %zu bytes into down-channel %u", *length
,
219 int target_rtt_read_control_block(struct target
*target
,
220 target_addr_t address
, struct rtt_control
*ctrl
, void *user_data
)
223 uint8_t buf
[RTT_CB_SIZE
];
225 ret
= target_read_buffer(target
, address
, RTT_CB_SIZE
, buf
);
230 memcpy(ctrl
->id
, buf
, RTT_CB_MAX_ID_LENGTH
);
231 ctrl
->id
[RTT_CB_MAX_ID_LENGTH
- 1] = '\0';
232 ctrl
->num_up_channels
= buf_get_u32(buf
+ RTT_CB_MAX_ID_LENGTH
+ 0,
234 ctrl
->num_down_channels
= buf_get_u32(buf
+ RTT_CB_MAX_ID_LENGTH
+ 4,
240 int target_rtt_find_control_block(struct target
*target
,
241 target_addr_t
*address
, size_t size
, const char *id
, bool *found
,
244 target_addr_t address_end
= *address
+ size
;
249 size_t id_matched_length
= 0;
250 const size_t id_length
= strlen(id
);
252 LOG_INFO("rtt: Searching for control block '%s'", id
);
254 for (target_addr_t addr
= *address
; addr
< address_end
; addr
+= sizeof(buf
)) {
257 const size_t buf_size
= MIN(sizeof(buf
), address_end
- addr
);
258 ret
= target_read_buffer(target
, addr
, buf_size
, buf
);
263 for (size_t buf_off
= 0; buf_off
< buf_size
; buf_off
++) {
264 if (id_matched_length
> 0 &&
265 buf
[buf_off
] != id
[id_matched_length
]) {
266 /* Start from beginning */
267 id_matched_length
= 0;
270 if (buf
[buf_off
] == id
[id_matched_length
])
273 if (id_matched_length
== id_length
) {
274 *address
= addr
+ buf_off
+ 1 - id_length
;
284 int target_rtt_read_channel_info(struct target
*target
,
285 const struct rtt_control
*ctrl
, unsigned int channel_index
,
286 enum rtt_channel_type type
, struct rtt_channel_info
*info
,
290 struct rtt_channel channel
;
292 ret
= read_rtt_channel(target
, ctrl
, channel_index
, type
, &channel
);
294 if (ret
!= ERROR_OK
) {
295 LOG_ERROR("rtt: Failed to read channel %u description",
300 ret
= read_channel_name(target
, channel
.name_addr
, info
->name
,
306 info
->size
= channel
.size
;
307 info
->flags
= channel
.flags
;
312 static int read_from_channel(struct target
*target
,
313 const struct rtt_channel
*channel
, uint8_t *buffer
,
322 if (channel
->read_pos
== channel
->write_pos
) {
324 } else if (channel
->read_pos
< channel
->write_pos
) {
325 len
= MIN(*length
, channel
->write_pos
- channel
->read_pos
);
327 ret
= target_read_buffer(target
,
328 channel
->buffer_addr
+ channel
->read_pos
, len
, buffer
);
333 uint32_t first_length
;
336 channel
->size
- channel
->read_pos
+ channel
->write_pos
);
337 first_length
= MIN(len
, channel
->size
- channel
->read_pos
);
339 ret
= target_read_buffer(target
,
340 channel
->buffer_addr
+ channel
->read_pos
, first_length
, buffer
);
345 ret
= target_read_buffer(target
, channel
->buffer_addr
,
346 len
- first_length
, buffer
+ first_length
);
353 ret
= target_write_u32(target
, channel
->address
+ 16,
354 (channel
->read_pos
+ len
) % channel
->size
);
365 int target_rtt_read_callback(struct target
*target
,
366 const struct rtt_control
*ctrl
, struct rtt_sink_list
**sinks
,
367 size_t num_channels
, void *user_data
)
369 num_channels
= MIN(num_channels
, ctrl
->num_up_channels
);
371 for (size_t i
= 0; i
< num_channels
; i
++) {
373 struct rtt_channel channel
;
374 uint8_t buffer
[1024];
380 ret
= read_rtt_channel(target
, ctrl
, i
, RTT_CHANNEL_TYPE_UP
,
383 if (ret
!= ERROR_OK
) {
384 LOG_ERROR("rtt: Failed to read up-channel %zu description", i
);
388 if (!channel_is_active(&channel
)) {
389 LOG_WARNING("rtt: Up-channel %zu is not active", i
);
393 if (channel
.size
< RTT_CHANNEL_BUFFER_MIN_SIZE
) {
394 LOG_WARNING("rtt: Up-channel %zu is not large enough", i
);
398 length
= sizeof(buffer
);
399 ret
= read_from_channel(target
, &channel
, buffer
, &length
);
401 if (ret
!= ERROR_OK
) {
402 LOG_ERROR("rtt: Failed to read from up-channel %zu", i
);
406 for (struct rtt_sink_list
*sink
= sinks
[i
]; sink
; sink
= sink
->next
)
407 sink
->read(i
, buffer
, length
, sink
->user_data
);
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)