2 * Copyright (C) 2016-2020 by Marc Schink <dev@zapb.de>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <helper/log.h>
21 #include <helper/binarybuffer.h>
22 #include <helper/command.h>
27 static int read_rtt_channel(struct target
*target
,
28 const struct rtt_control
*ctrl
, unsigned int channel_index
,
29 enum rtt_channel_type type
, struct rtt_channel
*channel
)
32 uint8_t buf
[RTT_CHANNEL_SIZE
];
33 target_addr_t address
;
35 address
= ctrl
->address
+ RTT_CB_SIZE
+ (channel_index
* RTT_CHANNEL_SIZE
);
37 if (type
== RTT_CHANNEL_TYPE_DOWN
)
38 address
+= ctrl
->num_up_channels
* RTT_CHANNEL_SIZE
;
40 ret
= target_read_buffer(target
, address
, RTT_CHANNEL_SIZE
, buf
);
45 channel
->address
= address
;
46 channel
->name_addr
= buf_get_u32(buf
+ 0, 0, 32);
47 channel
->buffer_addr
= buf_get_u32(buf
+ 4, 0, 32);
48 channel
->size
= buf_get_u32(buf
+ 8, 0, 32);
49 channel
->write_pos
= buf_get_u32(buf
+ 12, 0, 32);
50 channel
->read_pos
= buf_get_u32(buf
+ 16, 0, 32);
51 channel
->flags
= buf_get_u32(buf
+ 20, 0, 32);
56 int target_rtt_start(struct target
*target
, const struct rtt_control
*ctrl
,
62 int target_rtt_stop(struct target
*target
, void *user_data
)
67 static int read_channel_name(struct target
*target
, target_addr_t address
,
68 char *name
, size_t length
)
74 while (offset
< length
) {
78 read_length
= MIN(32, length
- offset
);
79 ret
= target_read_buffer(target
, address
+ offset
, read_length
,
80 (uint8_t *)name
+ offset
);
85 if (memchr(name
+ offset
, '\0', read_length
))
88 offset
+= read_length
;
91 name
[length
- 1] = '\0';
96 static int write_to_channel(struct target
*target
,
97 const struct rtt_channel
*channel
, const uint8_t *buffer
,
106 if (channel
->write_pos
== channel
->read_pos
) {
107 uint32_t first_length
;
109 len
= MIN(*length
, channel
->size
- 1);
110 first_length
= MIN(len
, channel
->size
- channel
->write_pos
);
112 ret
= target_write_buffer(target
,
113 channel
->buffer_addr
+ channel
->write_pos
, first_length
,
119 ret
= target_write_buffer(target
, channel
->buffer_addr
,
120 len
- first_length
, buffer
+ first_length
);
124 } else if (channel
->write_pos
< channel
->read_pos
) {
125 len
= MIN(*length
, channel
->read_pos
- channel
->write_pos
- 1);
132 ret
= target_write_buffer(target
,
133 channel
->buffer_addr
+ channel
->write_pos
, len
, buffer
);
138 uint32_t first_length
;
141 channel
->size
- channel
->write_pos
+ channel
->read_pos
- 1);
148 first_length
= MIN(len
, channel
->size
- channel
->write_pos
);
150 ret
= target_write_buffer(target
,
151 channel
->buffer_addr
+ channel
->write_pos
, first_length
,
157 buffer
= buffer
+ first_length
;
159 ret
= target_write_buffer(target
, channel
->buffer_addr
,
160 len
- first_length
, buffer
);
166 ret
= target_write_u32(target
, channel
->address
+ 12,
167 (channel
->write_pos
+ len
) % channel
->size
);
177 static bool channel_is_active(const struct rtt_channel
*channel
)
188 int target_rtt_write_callback(struct target
*target
, struct rtt_control
*ctrl
,
189 unsigned int channel_index
, const uint8_t *buffer
, size_t *length
,
193 struct rtt_channel channel
;
195 ret
= read_rtt_channel(target
, ctrl
, channel_index
,
196 RTT_CHANNEL_TYPE_DOWN
, &channel
);
198 if (ret
!= ERROR_OK
) {
199 LOG_ERROR("rtt: Failed to read down-channel %u description",
204 if (!channel_is_active(&channel
)) {
205 LOG_WARNING("rtt: Down-channel %u is not active", channel_index
);
209 if (channel
.size
< RTT_CHANNEL_BUFFER_MIN_SIZE
) {
210 LOG_WARNING("rtt: Down-channel %u is not large enough",
215 ret
= write_to_channel(target
, &channel
, buffer
, length
);
220 LOG_DEBUG("rtt: Wrote %zu bytes into down-channel %u", *length
,
226 int target_rtt_read_control_block(struct target
*target
,
227 target_addr_t address
, struct rtt_control
*ctrl
, void *user_data
)
230 uint8_t buf
[RTT_CB_SIZE
];
232 ret
= target_read_buffer(target
, address
, RTT_CB_SIZE
, buf
);
237 memcpy(ctrl
->id
, buf
, RTT_CB_MAX_ID_LENGTH
);
238 ctrl
->id
[RTT_CB_MAX_ID_LENGTH
- 1] = '\0';
239 ctrl
->num_up_channels
= buf_get_u32(buf
+ RTT_CB_MAX_ID_LENGTH
+ 0,
241 ctrl
->num_down_channels
= buf_get_u32(buf
+ RTT_CB_MAX_ID_LENGTH
+ 4,
247 int target_rtt_find_control_block(struct target
*target
,
248 target_addr_t
*address
, size_t size
, const char *id
, bool *found
,
256 size_t cb_offset
= 0;
257 const size_t id_length
= strlen(id
);
259 LOG_INFO("rtt: Searching for control block '%s'", id
);
261 for (target_addr_t addr
= 0; addr
< size
; addr
= addr
+ sizeof(buf
)) {
264 const size_t buf_size
= MIN(sizeof(buf
), size
- addr
);
265 ret
= target_read_buffer(target
, *address
+ addr
, buf_size
, buf
);
273 while (i
< buf_size
) {
274 if (buf
[i
] != id
[j
]) {
286 if (j
== id_length
) {
287 *address
= *address
+ cb_offset
;
297 int target_rtt_read_channel_info(struct target
*target
,
298 const struct rtt_control
*ctrl
, unsigned int channel_index
,
299 enum rtt_channel_type type
, struct rtt_channel_info
*info
,
303 struct rtt_channel channel
;
305 ret
= read_rtt_channel(target
, ctrl
, channel_index
, type
, &channel
);
307 if (ret
!= ERROR_OK
) {
308 LOG_ERROR("rtt: Failed to read channel %u description",
313 ret
= read_channel_name(target
, channel
.name_addr
, info
->name
,
319 info
->size
= channel
.size
;
320 info
->flags
= channel
.flags
;
325 static int read_from_channel(struct target
*target
,
326 const struct rtt_channel
*channel
, uint8_t *buffer
,
335 if (channel
->read_pos
== channel
->write_pos
) {
337 } else if (channel
->read_pos
< channel
->write_pos
) {
338 len
= MIN(*length
, channel
->write_pos
- channel
->read_pos
);
340 ret
= target_read_buffer(target
,
341 channel
->buffer_addr
+ channel
->read_pos
, len
, buffer
);
346 uint32_t first_length
;
349 channel
->size
- channel
->read_pos
+ channel
->write_pos
);
350 first_length
= MIN(len
, channel
->size
- channel
->read_pos
);
352 ret
= target_read_buffer(target
,
353 channel
->buffer_addr
+ channel
->read_pos
, first_length
, buffer
);
358 ret
= target_read_buffer(target
, channel
->buffer_addr
,
359 len
- first_length
, buffer
+ first_length
);
366 ret
= target_write_u32(target
, channel
->address
+ 16,
367 (channel
->read_pos
+ len
) % channel
->size
);
378 int target_rtt_read_callback(struct target
*target
,
379 const struct rtt_control
*ctrl
, struct rtt_sink_list
**sinks
,
380 size_t num_channels
, void *user_data
)
382 num_channels
= MIN(num_channels
, ctrl
->num_up_channels
);
384 for (size_t i
= 0; i
< num_channels
; i
++) {
386 struct rtt_channel channel
;
387 uint8_t buffer
[1024];
393 ret
= read_rtt_channel(target
, ctrl
, i
, RTT_CHANNEL_TYPE_UP
,
396 if (ret
!= ERROR_OK
) {
397 LOG_ERROR("rtt: Failed to read up-channel %zu description", i
);
401 if (!channel_is_active(&channel
)) {
402 LOG_WARNING("rtt: Up-channel %zu is not active", i
);
406 if (channel
.size
< RTT_CHANNEL_BUFFER_MIN_SIZE
) {
407 LOG_WARNING("rtt: Up-channel %zu is not large enough", i
);
411 length
= sizeof(buffer
);
412 ret
= read_from_channel(target
, &channel
, buffer
, &length
);
414 if (ret
!= ERROR_OK
) {
415 LOG_ERROR("rtt: Failed to read from up-channel %zu", i
);
419 for (struct rtt_sink_list
*sink
= sinks
[i
]; sink
; sink
= sink
->next
)
420 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)