1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2016-2020 by Marc Schink <dev@zapb.de>
15 #include <helper/log.h>
16 #include <helper/list.h>
17 #include <target/target.h>
18 #include <target/rtt.h>
23 struct rtt_source source
;
25 struct rtt_control ctrl
;
26 struct target
*target
;
27 /** Start address to search for the control block. */
29 /** Size of the control block search area. */
31 /** Control block identifier. */
32 char id
[RTT_CB_MAX_ID_LENGTH
];
33 /** Whether RTT is configured. */
35 /** Whether RTT is started. */
37 /** Whether configuration changed. */
39 /** Whether the control block was found. */
42 struct rtt_sink_list
**sink_list
;
43 size_t sink_list_length
;
45 unsigned int polling_interval
;
50 rtt
.sink_list_length
= 1;
51 rtt
.sink_list
= calloc(rtt
.sink_list_length
,
52 sizeof(struct rtt_sink_list
*));
57 rtt
.sink_list
[0] = NULL
;
60 rtt
.polling_interval
= 100;
72 static int read_channel_callback(void *user_data
)
76 ret
= rtt
.source
.read(rtt
.target
, &rtt
.ctrl
, rtt
.sink_list
,
77 rtt
.sink_list_length
, NULL
);
79 if (ret
!= ERROR_OK
) {
80 target_unregister_timer_callback(&read_channel_callback
, NULL
);
81 rtt
.source
.stop(rtt
.target
, NULL
);
88 int rtt_setup(target_addr_t address
, size_t size
, const char *id
)
90 size_t id_length
= strlen(id
);
92 if (!id_length
|| id_length
>= RTT_CB_MAX_ID_LENGTH
) {
93 LOG_ERROR("rtt: Invalid control block ID");
94 return ERROR_COMMAND_ARGUMENT_INVALID
;
99 strncpy(rtt
.id
, id
, id_length
+ 1);
101 rtt
.configured
= true;
106 int rtt_register_source(const struct rtt_source source
,
107 struct target
*target
)
109 if (!source
.find_cb
|| !source
.read_cb
|| !source
.read_channel_info
)
112 if (!source
.start
|| !source
.stop
)
115 if (!source
.read
|| !source
.write
)
127 target_addr_t addr
= rtt
.addr
;
132 if (!rtt
.found_cb
|| rtt
.changed
) {
133 rtt
.source
.find_cb(rtt
.target
, &addr
, rtt
.size
, rtt
.id
,
134 &rtt
.found_cb
, NULL
);
139 LOG_INFO("rtt: Control block found at 0x%" TARGET_PRIxADDR
,
141 rtt
.ctrl
.address
= addr
;
143 LOG_INFO("rtt: No control block found");
148 ret
= rtt
.source
.read_cb(rtt
.target
, rtt
.ctrl
.address
, &rtt
.ctrl
, NULL
);
153 ret
= rtt
.source
.start(rtt
.target
, &rtt
.ctrl
, NULL
);
158 target_register_timer_callback(&read_channel_callback
,
159 rtt
.polling_interval
, 1, NULL
);
169 if (!rtt
.configured
) {
170 LOG_ERROR("rtt: Not configured");
174 target_unregister_timer_callback(&read_channel_callback
, NULL
);
177 ret
= rtt
.source
.stop(rtt
.target
, NULL
);
185 static int adjust_sink_list(size_t length
)
187 struct rtt_sink_list
**tmp
;
189 if (length
<= rtt
.sink_list_length
)
192 tmp
= realloc(rtt
.sink_list
, sizeof(struct rtt_sink_list
*) * length
);
197 for (size_t i
= rtt
.sink_list_length
; i
< length
; i
++)
201 rtt
.sink_list_length
= length
;
206 int rtt_register_sink(unsigned int channel_index
, rtt_sink_read read
,
209 struct rtt_sink_list
*tmp
;
211 if (channel_index
>= rtt
.sink_list_length
) {
212 if (adjust_sink_list(channel_index
+ 1) != ERROR_OK
)
216 LOG_DEBUG("rtt: Registering sink for channel %u", channel_index
);
218 tmp
= malloc(sizeof(struct rtt_sink_list
));
224 tmp
->user_data
= user_data
;
225 tmp
->next
= rtt
.sink_list
[channel_index
];
227 rtt
.sink_list
[channel_index
] = tmp
;
232 int rtt_unregister_sink(unsigned int channel_index
, rtt_sink_read read
,
235 struct rtt_sink_list
*prev_sink
;
237 LOG_DEBUG("rtt: Unregistering sink for channel %u", channel_index
);
239 if (channel_index
>= rtt
.sink_list_length
)
242 prev_sink
= rtt
.sink_list
[channel_index
];
244 for (struct rtt_sink_list
*sink
= rtt
.sink_list
[channel_index
]; sink
;
245 prev_sink
= sink
, sink
= sink
->next
) {
246 if (sink
->read
== read
&& sink
->user_data
== user_data
) {
248 if (sink
== rtt
.sink_list
[channel_index
])
249 rtt
.sink_list
[channel_index
] = sink
->next
;
251 prev_sink
->next
= sink
->next
;
262 int rtt_get_polling_interval(unsigned int *interval
)
267 *interval
= rtt
.polling_interval
;
272 int rtt_set_polling_interval(unsigned int interval
)
277 if (rtt
.polling_interval
!= interval
) {
278 target_unregister_timer_callback(&read_channel_callback
, NULL
);
279 target_register_timer_callback(&read_channel_callback
, interval
, 1,
283 rtt
.polling_interval
= interval
;
288 int rtt_write_channel(unsigned int channel_index
, const uint8_t *buffer
,
291 if (channel_index
>= rtt
.ctrl
.num_up_channels
) {
292 LOG_WARNING("rtt: Down-channel %u is not available", channel_index
);
296 return rtt
.source
.write(rtt
.target
, &rtt
.ctrl
, channel_index
, buffer
,
300 bool rtt_started(void)
305 bool rtt_configured(void)
307 return rtt
.configured
;
310 bool rtt_found_cb(void)
315 const struct rtt_control
*rtt_get_control(void)
320 int rtt_read_channel_info(unsigned int channel_index
,
321 enum rtt_channel_type type
, struct rtt_channel_info
*info
)
323 return rtt
.source
.read_channel_info(rtt
.target
, &rtt
.ctrl
,
324 channel_index
, type
, info
, NULL
);