jtag: Add an option to ignore the bypass bit
[fw/openocd] / src / rtt / rtt.c
1 /*
2  * Copyright (C) 2016-2020 by Marc Schink <dev@zapb.de>
3  *
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.
8  *
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.
13  *
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/>.
16  */
17
18 #include <stdint.h>
19 #include <stdbool.h>
20 #include <string.h>
21
22 #include <helper/log.h>
23 #include <helper/list.h>
24 #include <target/target.h>
25 #include <target/rtt.h>
26
27 #include "rtt.h"
28
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;
48
49         struct rtt_sink_list **sink_list;
50         size_t sink_list_length;
51
52         unsigned int polling_interval;
53 } rtt;
54
55 int rtt_init(void)
56 {
57         rtt.sink_list_length = 1;
58         rtt.sink_list = calloc(rtt.sink_list_length,
59                 sizeof(struct rtt_sink_list *));
60
61         if (!rtt.sink_list)
62                 return ERROR_FAIL;
63
64         rtt.sink_list[0] = NULL;
65         rtt.started = false;
66
67         rtt.polling_interval = 100;
68
69         return ERROR_OK;
70 }
71
72 int rtt_exit(void)
73 {
74         free(rtt.sink_list);
75
76         return ERROR_OK;
77 }
78
79 static int read_channel_callback(void *user_data)
80 {
81         int ret;
82
83         ret = rtt.source.read(rtt.target, &rtt.ctrl, rtt.sink_list,
84                 rtt.sink_list_length, NULL);
85
86         if (ret != ERROR_OK) {
87                 target_unregister_timer_callback(&read_channel_callback, NULL);
88                 rtt.source.stop(rtt.target, NULL);
89                 return ret;
90         }
91
92         return ERROR_OK;
93 }
94
95 int rtt_setup(target_addr_t address, size_t size, const char *id)
96 {
97         size_t id_length = strlen(id);
98
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;
102         }
103
104         rtt.addr = address;
105         rtt.size = size;
106         strncpy(rtt.id, id, id_length + 1);
107         rtt.changed = true;
108         rtt.configured = true;
109
110         return ERROR_OK;
111 }
112
113 int rtt_register_source(const struct rtt_source source,
114                 struct target *target)
115 {
116         if (!source.find_cb || !source.read_cb || !source.read_channel_info)
117                 return ERROR_FAIL;
118
119         if (!source.start || !source.stop)
120                 return ERROR_FAIL;
121
122         if (!source.read || !source.write)
123                 return ERROR_FAIL;
124
125         rtt.source = source;
126         rtt.target = target;
127
128         return ERROR_OK;
129 }
130
131 int rtt_start(void)
132 {
133         int ret;
134         target_addr_t addr = rtt.addr;
135
136         if (rtt.started)
137                 return ERROR_OK;
138
139         if (!rtt.found_cb || rtt.changed) {
140                 rtt.source.find_cb(rtt.target, &addr, rtt.size, rtt.id,
141                         &rtt.found_cb, NULL);
142
143                 rtt.changed = false;
144
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;
152                 }
153         }
154
155         ret = rtt.source.read_cb(rtt.target, rtt.ctrl.address, &rtt.ctrl, NULL);
156
157         if (ret != ERROR_OK)
158                 return ret;
159
160         ret = rtt.source.start(rtt.target, &rtt.ctrl, NULL);
161
162         if (ret != ERROR_OK)
163                 return ret;
164
165         target_register_timer_callback(&read_channel_callback,
166                 rtt.polling_interval, 1, NULL);
167         rtt.started = true;
168
169         return ERROR_OK;
170 }
171
172 int rtt_stop(void)
173 {
174         int ret;
175
176         if (!rtt.configured) {
177                 LOG_ERROR("rtt: Not configured");
178                 return ERROR_FAIL;
179         }
180
181         target_unregister_timer_callback(&read_channel_callback, NULL);
182         rtt.started = false;
183
184         ret = rtt.source.stop(rtt.target, NULL);
185
186         if (ret != ERROR_OK)
187                 return ret;
188
189         return ERROR_OK;
190 }
191
192 static int adjust_sink_list(size_t length)
193 {
194         struct rtt_sink_list **tmp;
195
196         if (length <= rtt.sink_list_length)
197                 return ERROR_OK;
198
199         tmp = realloc(rtt.sink_list, sizeof(struct rtt_sink_list *) * length);
200
201         if (!tmp)
202                 return ERROR_FAIL;
203
204         for (size_t i = rtt.sink_list_length; i < length; i++)
205                 tmp[i] = NULL;
206
207         rtt.sink_list = tmp;
208         rtt.sink_list_length = length;
209
210         return ERROR_OK;
211 }
212
213 int rtt_register_sink(unsigned int channel_index, rtt_sink_read read,
214                 void *user_data)
215 {
216         struct rtt_sink_list *tmp;
217
218         if (channel_index >= rtt.sink_list_length) {
219                 if (adjust_sink_list(channel_index + 1) != ERROR_OK)
220                         return ERROR_FAIL;
221         }
222
223         LOG_DEBUG("rtt: Registering sink for channel %u", channel_index);
224
225         tmp = malloc(sizeof(struct rtt_sink_list));
226
227         if (!tmp)
228                 return ERROR_FAIL;
229
230         tmp->read = read;
231         tmp->user_data = user_data;
232         tmp->next = rtt.sink_list[channel_index];
233
234         rtt.sink_list[channel_index] = tmp;
235
236         return ERROR_OK;
237 }
238
239 int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read,
240                 void *user_data)
241 {
242         struct rtt_sink_list *prev_sink;
243
244         LOG_DEBUG("rtt: Unregistering sink for channel %u", channel_index);
245
246         if (channel_index >= rtt.sink_list_length)
247                 return ERROR_FAIL;
248
249         prev_sink = rtt.sink_list[channel_index];
250
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) {
254
255                         if (sink == rtt.sink_list[channel_index])
256                                 rtt.sink_list[channel_index] = sink->next;
257                         else
258                                 prev_sink->next = sink->next;
259
260                         free(sink);
261
262                         return ERROR_OK;
263                 }
264         }
265
266         return ERROR_OK;
267 }
268
269 int rtt_get_polling_interval(unsigned int *interval)
270 {
271         if (!interval)
272                 return ERROR_FAIL;
273
274         *interval = rtt.polling_interval;
275
276         return ERROR_OK;
277 }
278
279 int rtt_set_polling_interval(unsigned int interval)
280 {
281         if (!interval)
282                 return ERROR_FAIL;
283
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);
288         }
289
290         rtt.polling_interval = interval;
291
292         return ERROR_OK;
293 }
294
295 int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
296                 size_t *length)
297 {
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;
301         }
302
303         return rtt.source.write(rtt.target, &rtt.ctrl, channel_index, buffer,
304                 length, NULL);
305 }
306
307 bool rtt_started(void)
308 {
309         return rtt.started;
310 }
311
312 bool rtt_configured(void)
313 {
314         return rtt.configured;
315 }
316
317 bool rtt_found_cb(void)
318 {
319         return rtt.found_cb;
320 }
321
322 const struct rtt_control *rtt_get_control(void)
323 {
324         return &rtt.ctrl;
325 }
326
327 int rtt_read_channel_info(unsigned int channel_index,
328         enum rtt_channel_type type, struct rtt_channel_info *info)
329 {
330         return rtt.source.read_channel_info(rtt.target, &rtt.ctrl,
331                 channel_index, type, info, NULL);
332 }