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/>.
22 #include <helper/log.h>
23 #include <helper/list.h>
24 #include <target/target.h>
25 #include <target/rtt.h>
30 struct rtt_source source
;
32 struct rtt_control ctrl
;
33 struct target
*target
;
34 /** Start address to search for the control block. */
36 /** Size of the control block search area. */
38 /** Control block identifier. */
39 char id
[RTT_CB_MAX_ID_LENGTH
];
40 /** Whether RTT is configured. */
42 /** Whether RTT is started. */
44 /** Whether configuration changed. */
46 /** Whether the control block was found. */
49 struct rtt_sink_list
**sink_list
;
50 size_t sink_list_length
;
52 unsigned int polling_interval
;
57 rtt
.sink_list_length
= 1;
58 rtt
.sink_list
= calloc(rtt
.sink_list_length
,
59 sizeof(struct rtt_sink_list
*));
64 rtt
.sink_list
[0] = NULL
;
67 rtt
.polling_interval
= 100;
79 static int read_channel_callback(void *user_data
)
83 ret
= rtt
.source
.read(rtt
.target
, &rtt
.ctrl
, rtt
.sink_list
,
84 rtt
.sink_list_length
, NULL
);
86 if (ret
!= ERROR_OK
) {
87 target_unregister_timer_callback(&read_channel_callback
, NULL
);
88 rtt
.source
.stop(rtt
.target
, NULL
);
95 int rtt_setup(target_addr_t address
, size_t size
, const char *id
)
97 size_t id_length
= strlen(id
);
99 if (!id_length
|| id_length
>= RTT_CB_MAX_ID_LENGTH
) {
100 LOG_ERROR("rtt: Invalid control block ID");
101 return ERROR_COMMAND_ARGUMENT_INVALID
;
106 strncpy(rtt
.id
, id
, id_length
+ 1);
108 rtt
.configured
= true;
113 int rtt_register_source(const struct rtt_source source
,
114 struct target
*target
)
116 if (!source
.find_cb
|| !source
.read_cb
|| !source
.read_channel_info
)
119 if (!source
.start
|| !source
.stop
)
122 if (!source
.read
|| !source
.write
)
134 target_addr_t addr
= rtt
.addr
;
139 if (!rtt
.found_cb
|| rtt
.changed
) {
140 rtt
.source
.find_cb(rtt
.target
, &addr
, rtt
.size
, rtt
.id
,
141 &rtt
.found_cb
, NULL
);
146 LOG_INFO("rtt: Control block found at 0x%" TARGET_PRIxADDR
,
148 rtt
.ctrl
.address
= addr
;
150 LOG_INFO("rtt: No control block found");
155 ret
= rtt
.source
.read_cb(rtt
.target
, rtt
.ctrl
.address
, &rtt
.ctrl
, NULL
);
160 ret
= rtt
.source
.start(rtt
.target
, &rtt
.ctrl
, NULL
);
165 target_register_timer_callback(&read_channel_callback
,
166 rtt
.polling_interval
, 1, NULL
);
176 if (!rtt
.configured
) {
177 LOG_ERROR("rtt: Not configured");
181 target_unregister_timer_callback(&read_channel_callback
, NULL
);
184 ret
= rtt
.source
.stop(rtt
.target
, NULL
);
192 static int adjust_sink_list(size_t length
)
194 struct rtt_sink_list
**tmp
;
196 if (length
<= rtt
.sink_list_length
)
199 tmp
= realloc(rtt
.sink_list
, sizeof(struct rtt_sink_list
*) * length
);
204 for (size_t i
= rtt
.sink_list_length
; i
< length
; i
++)
208 rtt
.sink_list_length
= length
;
213 int rtt_register_sink(unsigned int channel_index
, rtt_sink_read read
,
216 struct rtt_sink_list
*tmp
;
218 if (channel_index
>= rtt
.sink_list_length
) {
219 if (adjust_sink_list(channel_index
+ 1) != ERROR_OK
)
223 LOG_DEBUG("rtt: Registering sink for channel %u", channel_index
);
225 tmp
= malloc(sizeof(struct rtt_sink_list
));
231 tmp
->user_data
= user_data
;
232 tmp
->next
= rtt
.sink_list
[channel_index
];
234 rtt
.sink_list
[channel_index
] = tmp
;
239 int rtt_unregister_sink(unsigned int channel_index
, rtt_sink_read read
,
242 struct rtt_sink_list
*prev_sink
;
244 LOG_DEBUG("rtt: Unregistering sink for channel %u", channel_index
);
246 if (channel_index
>= rtt
.sink_list_length
)
249 prev_sink
= rtt
.sink_list
[channel_index
];
251 for (struct rtt_sink_list
*sink
= rtt
.sink_list
[channel_index
]; sink
;
252 prev_sink
= sink
, sink
= sink
->next
) {
253 if (sink
->read
== read
&& sink
->user_data
== user_data
) {
255 if (sink
== rtt
.sink_list
[channel_index
])
256 rtt
.sink_list
[channel_index
] = sink
->next
;
258 prev_sink
->next
= sink
->next
;
269 int rtt_get_polling_interval(unsigned int *interval
)
274 *interval
= rtt
.polling_interval
;
279 int rtt_set_polling_interval(unsigned int interval
)
284 if (rtt
.polling_interval
!= interval
) {
285 target_unregister_timer_callback(&read_channel_callback
, NULL
);
286 target_register_timer_callback(&read_channel_callback
, interval
, 1,
290 rtt
.polling_interval
= interval
;
295 int rtt_write_channel(unsigned int channel_index
, const uint8_t *buffer
,
298 if (channel_index
>= rtt
.ctrl
.num_up_channels
) {
299 LOG_WARNING("rtt: Down-channel %u is not available", channel_index
);
303 return rtt
.source
.write(rtt
.target
, &rtt
.ctrl
, channel_index
, buffer
,
307 bool rtt_started(void)
312 bool rtt_configured(void)
314 return rtt
.configured
;
317 bool rtt_found_cb(void)
322 const struct rtt_control
*rtt_get_control(void)
327 int rtt_read_channel_info(unsigned int channel_index
,
328 enum rtt_channel_type type
, struct rtt_channel_info
*info
)
330 return rtt
.source
.read_channel_info(rtt
.target
, &rtt
.ctrl
,
331 channel_index
, type
, info
, NULL
);
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)