jtag/drivers/ftdi: Use correct command error
[openocd.git] / src / rtt / rtt.c
blobe31e75410de8ca6d069a9a46e4213e11190c4f4a
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /*
4 * Copyright (C) 2016-2020 by Marc Schink <dev@zapb.de>
5 */
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
11 #include <stdint.h>
12 #include <stdbool.h>
13 #include <string.h>
15 #include <helper/log.h>
16 #include <helper/list.h>
17 #include <target/target.h>
18 #include <target/rtt.h>
20 #include "rtt.h"
22 static struct {
23 struct rtt_source source;
24 /** Control block. */
25 struct rtt_control ctrl;
26 struct target *target;
27 /** Start address to search for the control block. */
28 target_addr_t addr;
29 /** Size of the control block search area. */
30 size_t size;
31 /** Control block identifier. */
32 char id[RTT_CB_MAX_ID_LENGTH];
33 /** Whether RTT is configured. */
34 bool configured;
35 /** Whether RTT is started. */
36 bool started;
37 /** Whether configuration changed. */
38 bool changed;
39 /** Whether the control block was found. */
40 bool found_cb;
42 struct rtt_sink_list **sink_list;
43 size_t sink_list_length;
45 unsigned int polling_interval;
46 } rtt;
48 int rtt_init(void)
50 rtt.sink_list_length = 1;
51 rtt.sink_list = calloc(rtt.sink_list_length,
52 sizeof(struct rtt_sink_list *));
54 if (!rtt.sink_list)
55 return ERROR_FAIL;
57 rtt.sink_list[0] = NULL;
58 rtt.started = false;
60 rtt.polling_interval = 100;
62 return ERROR_OK;
65 int rtt_exit(void)
67 free(rtt.sink_list);
69 return ERROR_OK;
72 static int read_channel_callback(void *user_data)
74 int ret;
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);
82 return ret;
85 return ERROR_OK;
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;
97 rtt.addr = address;
98 rtt.size = size;
99 strncpy(rtt.id, id, id_length + 1);
100 rtt.changed = true;
101 rtt.configured = true;
103 return ERROR_OK;
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)
110 return ERROR_FAIL;
112 if (!source.start || !source.stop)
113 return ERROR_FAIL;
115 if (!source.read || !source.write)
116 return ERROR_FAIL;
118 rtt.source = source;
119 rtt.target = target;
121 return ERROR_OK;
124 int rtt_start(void)
126 int ret;
127 target_addr_t addr = rtt.addr;
129 if (rtt.started)
130 return ERROR_OK;
132 if (!rtt.found_cb || rtt.changed) {
133 rtt.source.find_cb(rtt.target, &addr, rtt.size, rtt.id,
134 &rtt.found_cb, NULL);
136 rtt.changed = false;
138 if (rtt.found_cb) {
139 LOG_INFO("rtt: Control block found at 0x%" TARGET_PRIxADDR,
140 addr);
141 rtt.ctrl.address = addr;
142 } else {
143 LOG_INFO("rtt: No control block found");
144 return ERROR_OK;
148 ret = rtt.source.read_cb(rtt.target, rtt.ctrl.address, &rtt.ctrl, NULL);
150 if (ret != ERROR_OK)
151 return ret;
153 ret = rtt.source.start(rtt.target, &rtt.ctrl, NULL);
155 if (ret != ERROR_OK)
156 return ret;
158 target_register_timer_callback(&read_channel_callback,
159 rtt.polling_interval, 1, NULL);
160 rtt.started = true;
162 return ERROR_OK;
165 int rtt_stop(void)
167 int ret;
169 if (!rtt.configured) {
170 LOG_ERROR("rtt: Not configured");
171 return ERROR_FAIL;
174 target_unregister_timer_callback(&read_channel_callback, NULL);
175 rtt.started = false;
177 ret = rtt.source.stop(rtt.target, NULL);
179 if (ret != ERROR_OK)
180 return ret;
182 return ERROR_OK;
185 static int adjust_sink_list(size_t length)
187 struct rtt_sink_list **tmp;
189 if (length <= rtt.sink_list_length)
190 return ERROR_OK;
192 tmp = realloc(rtt.sink_list, sizeof(struct rtt_sink_list *) * length);
194 if (!tmp)
195 return ERROR_FAIL;
197 for (size_t i = rtt.sink_list_length; i < length; i++)
198 tmp[i] = NULL;
200 rtt.sink_list = tmp;
201 rtt.sink_list_length = length;
203 return ERROR_OK;
206 int rtt_register_sink(unsigned int channel_index, rtt_sink_read read,
207 void *user_data)
209 struct rtt_sink_list *tmp;
211 if (channel_index >= rtt.sink_list_length) {
212 if (adjust_sink_list(channel_index + 1) != ERROR_OK)
213 return ERROR_FAIL;
216 LOG_DEBUG("rtt: Registering sink for channel %u", channel_index);
218 tmp = malloc(sizeof(struct rtt_sink_list));
220 if (!tmp)
221 return ERROR_FAIL;
223 tmp->read = read;
224 tmp->user_data = user_data;
225 tmp->next = rtt.sink_list[channel_index];
227 rtt.sink_list[channel_index] = tmp;
229 return ERROR_OK;
232 int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read,
233 void *user_data)
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)
240 return ERROR_FAIL;
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;
250 else
251 prev_sink->next = sink->next;
253 free(sink);
255 return ERROR_OK;
259 return ERROR_OK;
262 int rtt_get_polling_interval(unsigned int *interval)
264 if (!interval)
265 return ERROR_FAIL;
267 *interval = rtt.polling_interval;
269 return ERROR_OK;
272 int rtt_set_polling_interval(unsigned int interval)
274 if (!interval)
275 return ERROR_FAIL;
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,
280 NULL);
283 rtt.polling_interval = interval;
285 return ERROR_OK;
288 int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
289 size_t *length)
291 if (channel_index >= rtt.ctrl.num_up_channels) {
292 LOG_WARNING("rtt: Down-channel %u is not available", channel_index);
293 return ERROR_OK;
296 return rtt.source.write(rtt.target, &rtt.ctrl, channel_index, buffer,
297 length, NULL);
300 bool rtt_started(void)
302 return rtt.started;
305 bool rtt_configured(void)
307 return rtt.configured;
310 bool rtt_found_cb(void)
312 return rtt.found_cb;
315 const struct rtt_control *rtt_get_control(void)
317 return &rtt.ctrl;
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);