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>
17 #include <target/rtt.h>
21 static int read_rtt_channel(struct target
*target
,
22 const struct rtt_control
*ctrl
, unsigned int channel_index
,
23 enum rtt_channel_type type
, struct rtt_channel
*channel
)
26 uint8_t buf
[RTT_CHANNEL_SIZE
];
27 target_addr_t address
;
29 address
= ctrl
->address
+ RTT_CB_SIZE
+ (channel_index
* RTT_CHANNEL_SIZE
);
31 if (type
== RTT_CHANNEL_TYPE_DOWN
)
32 address
+= ctrl
->num_up_channels
* RTT_CHANNEL_SIZE
;
34 ret
= target_read_buffer(target
, address
, RTT_CHANNEL_SIZE
, buf
);
39 channel
->address
= address
;
40 channel
->name_addr
= buf_get_u32(buf
+ 0, 0, 32);
41 channel
->buffer_addr
= buf_get_u32(buf
+ 4, 0, 32);
42 channel
->size
= buf_get_u32(buf
+ 8, 0, 32);
43 channel
->write_pos
= buf_get_u32(buf
+ 12, 0, 32);
44 channel
->read_pos
= buf_get_u32(buf
+ 16, 0, 32);
45 channel
->flags
= buf_get_u32(buf
+ 20, 0, 32);
50 int target_rtt_start(struct target
*target
, const struct rtt_control
*ctrl
,
56 int target_rtt_stop(struct target
*target
, void *user_data
)
61 static int read_channel_name(struct target
*target
, target_addr_t address
,
62 char *name
, size_t length
)
68 while (offset
< length
) {
72 read_length
= MIN(32, length
- offset
);
73 ret
= target_read_buffer(target
, address
+ offset
, read_length
,
74 (uint8_t *)name
+ offset
);
79 if (memchr(name
+ offset
, '\0', read_length
))
82 offset
+= read_length
;
85 name
[length
- 1] = '\0';
90 static int write_to_channel(struct target
*target
,
91 const struct rtt_channel
*channel
, const uint8_t *buffer
,
100 if (channel
->write_pos
== channel
->read_pos
) {
101 uint32_t first_length
;
103 len
= MIN(*length
, channel
->size
- 1);
104 first_length
= MIN(len
, channel
->size
- channel
->write_pos
);
106 ret
= target_write_buffer(target
,
107 channel
->buffer_addr
+ channel
->write_pos
, first_length
,
113 ret
= target_write_buffer(target
, channel
->buffer_addr
,
114 len
- first_length
, buffer
+ first_length
);
118 } else if (channel
->write_pos
< channel
->read_pos
) {
119 len
= MIN(*length
, channel
->read_pos
- channel
->write_pos
- 1);
126 ret
= target_write_buffer(target
,
127 channel
->buffer_addr
+ channel
->write_pos
, len
, buffer
);
132 uint32_t first_length
;
135 channel
->size
- channel
->write_pos
+ channel
->read_pos
- 1);
142 first_length
= MIN(len
, channel
->size
- channel
->write_pos
);
144 ret
= target_write_buffer(target
,
145 channel
->buffer_addr
+ channel
->write_pos
, first_length
,
151 buffer
= buffer
+ first_length
;
153 ret
= target_write_buffer(target
, channel
->buffer_addr
,
154 len
- first_length
, buffer
);
160 ret
= target_write_u32(target
, channel
->address
+ 12,
161 (channel
->write_pos
+ len
) % channel
->size
);
171 static bool channel_is_active(const struct rtt_channel
*channel
)
182 int target_rtt_write_callback(struct target
*target
, struct rtt_control
*ctrl
,
183 unsigned int channel_index
, const uint8_t *buffer
, size_t *length
,
187 struct rtt_channel channel
;
189 ret
= read_rtt_channel(target
, ctrl
, channel_index
,
190 RTT_CHANNEL_TYPE_DOWN
, &channel
);
192 if (ret
!= ERROR_OK
) {
193 LOG_ERROR("rtt: Failed to read down-channel %u description",
198 if (!channel_is_active(&channel
)) {
199 LOG_WARNING("rtt: Down-channel %u is not active", channel_index
);
203 if (channel
.size
< RTT_CHANNEL_BUFFER_MIN_SIZE
) {
204 LOG_WARNING("rtt: Down-channel %u is not large enough",
209 ret
= write_to_channel(target
, &channel
, buffer
, length
);
214 LOG_DEBUG("rtt: Wrote %zu bytes into down-channel %u", *length
,
220 int target_rtt_read_control_block(struct target
*target
,
221 target_addr_t address
, struct rtt_control
*ctrl
, void *user_data
)
224 uint8_t buf
[RTT_CB_SIZE
];
226 ret
= target_read_buffer(target
, address
, RTT_CB_SIZE
, buf
);
231 memcpy(ctrl
->id
, buf
, RTT_CB_MAX_ID_LENGTH
);
232 ctrl
->id
[RTT_CB_MAX_ID_LENGTH
- 1] = '\0';
233 ctrl
->num_up_channels
= buf_get_u32(buf
+ RTT_CB_MAX_ID_LENGTH
+ 0,
235 ctrl
->num_down_channels
= buf_get_u32(buf
+ RTT_CB_MAX_ID_LENGTH
+ 4,
241 int target_rtt_find_control_block(struct target
*target
,
242 target_addr_t
*address
, size_t size
, const char *id
, bool *found
,
245 target_addr_t address_end
= *address
+ size
;
250 size_t id_matched_length
= 0;
251 const size_t id_length
= strlen(id
);
253 LOG_INFO("rtt: Searching for control block '%s'", id
);
255 for (target_addr_t addr
= *address
; addr
< address_end
; addr
+= sizeof(buf
)) {
258 const size_t buf_size
= MIN(sizeof(buf
), address_end
- addr
);
259 ret
= target_read_buffer(target
, addr
, buf_size
, buf
);
264 for (size_t buf_off
= 0; buf_off
< buf_size
; buf_off
++) {
265 if (id_matched_length
> 0 &&
266 buf
[buf_off
] != id
[id_matched_length
]) {
267 /* Start from beginning */
268 id_matched_length
= 0;
271 if (buf
[buf_off
] == id
[id_matched_length
])
274 if (id_matched_length
== id_length
) {
275 *address
= addr
+ buf_off
+ 1 - id_length
;
285 int target_rtt_read_channel_info(struct target
*target
,
286 const struct rtt_control
*ctrl
, unsigned int channel_index
,
287 enum rtt_channel_type type
, struct rtt_channel_info
*info
,
291 struct rtt_channel channel
;
293 ret
= read_rtt_channel(target
, ctrl
, channel_index
, type
, &channel
);
295 if (ret
!= ERROR_OK
) {
296 LOG_ERROR("rtt: Failed to read channel %u description",
301 ret
= read_channel_name(target
, channel
.name_addr
, info
->name
,
307 info
->size
= channel
.size
;
308 info
->flags
= channel
.flags
;
313 static int read_from_channel(struct target
*target
,
314 const struct rtt_channel
*channel
, uint8_t *buffer
,
323 if (channel
->read_pos
== channel
->write_pos
) {
325 } else if (channel
->read_pos
< channel
->write_pos
) {
326 len
= MIN(*length
, channel
->write_pos
- channel
->read_pos
);
328 ret
= target_read_buffer(target
,
329 channel
->buffer_addr
+ channel
->read_pos
, len
, buffer
);
334 uint32_t first_length
;
337 channel
->size
- channel
->read_pos
+ channel
->write_pos
);
338 first_length
= MIN(len
, channel
->size
- channel
->read_pos
);
340 ret
= target_read_buffer(target
,
341 channel
->buffer_addr
+ channel
->read_pos
, first_length
, buffer
);
346 ret
= target_read_buffer(target
, channel
->buffer_addr
,
347 len
- first_length
, buffer
+ first_length
);
354 ret
= target_write_u32(target
, channel
->address
+ 16,
355 (channel
->read_pos
+ len
) % channel
->size
);
366 int target_rtt_read_callback(struct target
*target
,
367 const struct rtt_control
*ctrl
, struct rtt_sink_list
**sinks
,
368 size_t num_channels
, void *user_data
)
370 num_channels
= MIN(num_channels
, ctrl
->num_up_channels
);
372 for (size_t i
= 0; i
< num_channels
; i
++) {
374 struct rtt_channel channel
;
375 uint8_t buffer
[1024];
381 ret
= read_rtt_channel(target
, ctrl
, i
, RTT_CHANNEL_TYPE_UP
,
384 if (ret
!= ERROR_OK
) {
385 LOG_ERROR("rtt: Failed to read up-channel %zu description", i
);
389 if (!channel_is_active(&channel
)) {
390 LOG_WARNING("rtt: Up-channel %zu is not active", i
);
394 if (channel
.size
< RTT_CHANNEL_BUFFER_MIN_SIZE
) {
395 LOG_WARNING("rtt: Up-channel %zu is not large enough", i
);
399 length
= sizeof(buffer
);
400 ret
= read_from_channel(target
, &channel
, buffer
, &length
);
402 if (ret
!= ERROR_OK
) {
403 LOG_ERROR("rtt: Failed to read from up-channel %zu", i
);
407 for (struct rtt_sink_list
*sink
= sinks
[i
]; sink
; sink
= sink
->next
)
408 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)