jtag: remove file driver.h
[openocd.git] / src / rtt / rtt.c
blobbf3cca51b20ba43df19dabcf0e6752a5d1a7d87d
1 /*
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/>.
18 #include <stdint.h>
19 #include <stdbool.h>
20 #include <string.h>
22 #include <helper/log.h>
23 #include <helper/list.h>
24 #include <target/target.h>
25 #include <target/rtt.h>
27 #include "rtt.h"
29 static struct {
30 struct rtt_source source;
31 /** Control block. */
32 struct rtt_control ctrl;
33 struct target *target;
34 /** Start address to search for the control block. */
35 target_addr_t addr;
36 /** Size of the control block search area. */
37 size_t size;
38 /** Control block identifier. */
39 char id[RTT_CB_MAX_ID_LENGTH];
40 /** Whether RTT is configured. */
41 bool configured;
42 /** Whether RTT is started. */
43 bool started;
44 /** Whether configuration changed. */
45 bool changed;
46 /** Whether the control block was found. */
47 bool found_cb;
49 struct rtt_sink_list **sink_list;
50 size_t sink_list_length;
52 unsigned int polling_interval;
53 } rtt;
55 int rtt_init(void)
57 rtt.sink_list_length = 1;
58 rtt.sink_list = calloc(rtt.sink_list_length,
59 sizeof(struct rtt_sink_list *));
61 if (!rtt.sink_list)
62 return ERROR_FAIL;
64 rtt.sink_list[0] = NULL;
65 rtt.started = false;
67 rtt.polling_interval = 100;
69 return ERROR_OK;
72 int rtt_exit(void)
74 free(rtt.sink_list);
76 return ERROR_OK;
79 static int read_channel_callback(void *user_data)
81 int ret;
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);
89 return ret;
92 return ERROR_OK;
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;
104 rtt.addr = address;
105 rtt.size = size;
106 strncpy(rtt.id, id, id_length + 1);
107 rtt.changed = true;
108 rtt.configured = true;
110 return ERROR_OK;
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)
117 return ERROR_FAIL;
119 if (!source.start || !source.stop)
120 return ERROR_FAIL;
122 if (!source.read || !source.write)
123 return ERROR_FAIL;
125 rtt.source = source;
126 rtt.target = target;
128 return ERROR_OK;
131 int rtt_start(void)
133 int ret;
134 target_addr_t addr = rtt.addr;
136 if (rtt.started)
137 return ERROR_OK;
139 if (!rtt.found_cb || rtt.changed) {
140 rtt.source.find_cb(rtt.target, &addr, rtt.size, rtt.id,
141 &rtt.found_cb, NULL);
143 rtt.changed = false;
145 if (rtt.found_cb) {
146 LOG_INFO("rtt: Control block found at 0x%" TARGET_PRIxADDR,
147 addr);
148 rtt.ctrl.address = addr;
149 } else {
150 LOG_INFO("rtt: No control block found");
151 return ERROR_OK;
155 ret = rtt.source.read_cb(rtt.target, rtt.ctrl.address, &rtt.ctrl, NULL);
157 if (ret != ERROR_OK)
158 return ret;
160 ret = rtt.source.start(rtt.target, &rtt.ctrl, NULL);
162 if (ret != ERROR_OK)
163 return ret;
165 target_register_timer_callback(&read_channel_callback,
166 rtt.polling_interval, 1, NULL);
167 rtt.started = true;
169 return ERROR_OK;
172 int rtt_stop(void)
174 int ret;
176 if (!rtt.configured) {
177 LOG_ERROR("rtt: Not configured");
178 return ERROR_FAIL;
181 target_unregister_timer_callback(&read_channel_callback, NULL);
182 rtt.started = false;
184 ret = rtt.source.stop(rtt.target, NULL);
186 if (ret != ERROR_OK)
187 return ret;
189 return ERROR_OK;
192 static int adjust_sink_list(size_t length)
194 struct rtt_sink_list **tmp;
196 if (length <= rtt.sink_list_length)
197 return ERROR_OK;
199 tmp = realloc(rtt.sink_list, sizeof(struct rtt_sink_list *) * length);
201 if (!tmp)
202 return ERROR_FAIL;
204 for (size_t i = rtt.sink_list_length; i < length; i++)
205 tmp[i] = NULL;
207 rtt.sink_list = tmp;
208 rtt.sink_list_length = length;
210 return ERROR_OK;
213 int rtt_register_sink(unsigned int channel_index, rtt_sink_read read,
214 void *user_data)
216 struct rtt_sink_list *tmp;
218 if (channel_index >= rtt.sink_list_length) {
219 if (adjust_sink_list(channel_index + 1) != ERROR_OK)
220 return ERROR_FAIL;
223 LOG_DEBUG("rtt: Registering sink for channel %u", channel_index);
225 tmp = malloc(sizeof(struct rtt_sink_list));
227 if (!tmp)
228 return ERROR_FAIL;
230 tmp->read = read;
231 tmp->user_data = user_data;
232 tmp->next = rtt.sink_list[channel_index];
234 rtt.sink_list[channel_index] = tmp;
236 return ERROR_OK;
239 int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read,
240 void *user_data)
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)
247 return ERROR_FAIL;
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;
257 else
258 prev_sink->next = sink->next;
260 free(sink);
262 return ERROR_OK;
266 return ERROR_OK;
269 int rtt_get_polling_interval(unsigned int *interval)
271 if (!interval)
272 return ERROR_FAIL;
274 *interval = rtt.polling_interval;
276 return ERROR_OK;
279 int rtt_set_polling_interval(unsigned int interval)
281 if (!interval)
282 return ERROR_FAIL;
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,
287 NULL);
290 rtt.polling_interval = interval;
292 return ERROR_OK;
295 int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
296 size_t *length)
298 if (channel_index >= rtt.ctrl.num_up_channels) {
299 LOG_WARNING("rtt: Down-channel %u is not available", channel_index);
300 return ERROR_OK;
303 return rtt.source.write(rtt.target, &rtt.ctrl, channel_index, buffer,
304 length, NULL);
307 bool rtt_started(void)
309 return rtt.started;
312 bool rtt_configured(void)
314 return rtt.configured;
317 bool rtt_found_cb(void)
319 return rtt.found_cb;
322 const struct rtt_control *rtt_get_control(void)
324 return &rtt.ctrl;
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);