OpenOCD
rtt/rtt.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /*
4  * Copyright (C) 2016-2020 by Marc Schink <dev@zapb.de>
5  */
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include <stdint.h>
12 #include <stdbool.h>
13 #include <string.h>
14 
15 #include <helper/log.h>
16 #include <helper/list.h>
17 #include <target/target.h>
18 #include <target/rtt.h>
19 
20 #include "rtt.h"
21 
22 static struct {
23  struct rtt_source source;
25  struct rtt_control ctrl;
26  struct target *target;
30  size_t size;
34  bool configured;
36  bool started;
38  bool changed;
40  bool found_cb;
41 
44 
45  unsigned int polling_interval;
46 } rtt;
47 
48 int rtt_init(void)
49 {
50  rtt.sink_list_length = 1;
51  rtt.sink_list = calloc(rtt.sink_list_length,
52  sizeof(struct rtt_sink_list *));
53 
54  if (!rtt.sink_list)
55  return ERROR_FAIL;
56 
57  rtt.sink_list[0] = NULL;
58  rtt.started = false;
59 
60  rtt.polling_interval = 100;
61 
62  return ERROR_OK;
63 }
64 
65 int rtt_exit(void)
66 {
67  free(rtt.sink_list);
68 
69  return ERROR_OK;
70 }
71 
73 {
74  int ret;
75 
76  ret = rtt.source.read(rtt.target, &rtt.ctrl, rtt.sink_list,
77  rtt.sink_list_length, NULL);
78 
79  if (ret != ERROR_OK) {
81  rtt.source.stop(rtt.target, NULL);
82  return ret;
83  }
84 
85  return ERROR_OK;
86 }
87 
88 int rtt_setup(target_addr_t address, size_t size, const char *id)
89 {
90  size_t id_length = strlen(id);
91 
92  if (!id_length || id_length >= RTT_CB_MAX_ID_LENGTH) {
93  LOG_ERROR("rtt: Invalid control block ID");
95  }
96 
97  rtt.addr = address;
98  rtt.size = size;
99  strncpy(rtt.id, id, id_length + 1);
100  rtt.changed = true;
101  rtt.configured = true;
102 
103  return ERROR_OK;
104 }
105 
107  struct target *target)
108 {
110  return ERROR_FAIL;
111 
112  if (!source.start || !source.stop)
113  return ERROR_FAIL;
114 
115  if (!source.read || !source.write)
116  return ERROR_FAIL;
117 
118  rtt.source = source;
119  rtt.target = target;
120 
121  return ERROR_OK;
122 }
123 
124 int rtt_start(void)
125 {
126  int ret;
127  target_addr_t addr = rtt.addr;
128 
129  if (rtt.started)
130  return ERROR_OK;
131 
132  if (!rtt.found_cb || rtt.changed) {
133  rtt.source.find_cb(rtt.target, &addr, rtt.size, rtt.id,
134  &rtt.found_cb, NULL);
135 
136  rtt.changed = false;
137 
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;
145  }
146  }
147 
148  ret = rtt.source.read_cb(rtt.target, rtt.ctrl.address, &rtt.ctrl, NULL);
149 
150  if (ret != ERROR_OK)
151  return ret;
152 
153  ret = rtt.source.start(rtt.target, &rtt.ctrl, NULL);
154 
155  if (ret != ERROR_OK)
156  return ret;
157 
159  rtt.polling_interval, 1, NULL);
160  rtt.started = true;
161 
162  return ERROR_OK;
163 }
164 
165 int rtt_stop(void)
166 {
167  int ret;
168 
169  if (!rtt.configured) {
170  LOG_ERROR("rtt: Not configured");
171  return ERROR_FAIL;
172  }
173 
175  rtt.started = false;
176 
177  ret = rtt.source.stop(rtt.target, NULL);
178 
179  if (ret != ERROR_OK)
180  return ret;
181 
182  return ERROR_OK;
183 }
184 
185 static int adjust_sink_list(size_t length)
186 {
187  struct rtt_sink_list **tmp;
188 
189  if (length <= rtt.sink_list_length)
190  return ERROR_OK;
191 
192  tmp = realloc(rtt.sink_list, sizeof(struct rtt_sink_list *) * length);
193 
194  if (!tmp)
195  return ERROR_FAIL;
196 
197  for (size_t i = rtt.sink_list_length; i < length; i++)
198  tmp[i] = NULL;
199 
200  rtt.sink_list = tmp;
201  rtt.sink_list_length = length;
202 
203  return ERROR_OK;
204 }
205 
206 int rtt_register_sink(unsigned int channel_index, rtt_sink_read read,
207  void *user_data)
208 {
209  struct rtt_sink_list *tmp;
210 
211  if (channel_index >= rtt.sink_list_length) {
212  if (adjust_sink_list(channel_index + 1) != ERROR_OK)
213  return ERROR_FAIL;
214  }
215 
216  LOG_DEBUG("rtt: Registering sink for channel %u", channel_index);
217 
218  tmp = malloc(sizeof(struct rtt_sink_list));
219 
220  if (!tmp)
221  return ERROR_FAIL;
222 
223  tmp->read = read;
224  tmp->user_data = user_data;
225  tmp->next = rtt.sink_list[channel_index];
226 
227  rtt.sink_list[channel_index] = tmp;
228 
229  return ERROR_OK;
230 }
231 
232 int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read,
233  void *user_data)
234 {
235  struct rtt_sink_list *prev_sink;
236 
237  LOG_DEBUG("rtt: Unregistering sink for channel %u", channel_index);
238 
239  if (channel_index >= rtt.sink_list_length)
240  return ERROR_FAIL;
241 
242  prev_sink = rtt.sink_list[channel_index];
243 
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) {
247 
248  if (sink == rtt.sink_list[channel_index])
249  rtt.sink_list[channel_index] = sink->next;
250  else
251  prev_sink->next = sink->next;
252 
253  free(sink);
254 
255  return ERROR_OK;
256  }
257  }
258 
259  return ERROR_OK;
260 }
261 
262 int rtt_get_polling_interval(unsigned int *interval)
263 {
264  if (!interval)
265  return ERROR_FAIL;
266 
267  *interval = rtt.polling_interval;
268 
269  return ERROR_OK;
270 }
271 
272 int rtt_set_polling_interval(unsigned int interval)
273 {
274  if (!interval)
275  return ERROR_FAIL;
276 
277  if (rtt.polling_interval != interval) {
280  NULL);
281  }
282 
283  rtt.polling_interval = interval;
284 
285  return ERROR_OK;
286 }
287 
288 int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
289  size_t *length)
290 {
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;
294  }
295 
296  return rtt.source.write(rtt.target, &rtt.ctrl, channel_index, buffer,
297  length, NULL);
298 }
299 
300 bool rtt_started(void)
301 {
302  return rtt.started;
303 }
304 
305 bool rtt_configured(void)
306 {
307  return rtt.configured;
308 }
309 
310 bool rtt_found_cb(void)
311 {
312  return rtt.found_cb;
313 }
314 
315 const struct rtt_control *rtt_get_control(void)
316 {
317  return &rtt.ctrl;
318 }
319 
320 int rtt_read_channel_info(unsigned int channel_index,
322 {
323  return rtt.source.read_channel_info(rtt.target, &rtt.ctrl,
324  channel_index, type, info, NULL);
325 }
#define ERROR_COMMAND_ARGUMENT_INVALID
Definition: command.h:404
uint8_t type
Definition: esp_usb_jtag.c:0
uint8_t length
Definition: esp_usb_jtag.c:1
#define LOG_WARNING(expr ...)
Definition: log.h:129
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
bool changed
Whether configuration changed.
Definition: rtt/rtt.c:38
int rtt_stop(void)
Stop Real-Time Transfer (RTT).
Definition: rtt/rtt.c:165
target_addr_t addr
Start address to search for the control block.
Definition: rtt/rtt.c:28
bool found_cb
Whether the control block was found.
Definition: rtt/rtt.c:40
unsigned int polling_interval
Definition: rtt/rtt.c:45
struct target * target
Definition: rtt/rtt.c:26
bool started
Whether RTT is started.
Definition: rtt/rtt.c:36
int rtt_start(void)
Start Real-Time Transfer (RTT).
Definition: rtt/rtt.c:124
bool configured
Whether RTT is configured.
Definition: rtt/rtt.c:34
struct rtt_control ctrl
Control block.
Definition: rtt/rtt.c:25
int rtt_register_sink(unsigned int channel_index, rtt_sink_read read, void *user_data)
Register an RTT sink.
Definition: rtt/rtt.c:206
bool rtt_configured(void)
Get whether RTT is configured.
Definition: rtt/rtt.c:305
bool rtt_found_cb(void)
Get whether RTT control block was found.
Definition: rtt/rtt.c:310
struct rtt_sink_list ** sink_list
Definition: rtt/rtt.c:42
int rtt_set_polling_interval(unsigned int interval)
Set the polling interval.
Definition: rtt/rtt.c:272
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read, void *user_data)
Unregister an RTT sink.
Definition: rtt/rtt.c:232
static struct @55 rtt
int rtt_init(void)
Initialize Real-Time Transfer (RTT).
Definition: rtt/rtt.c:48
bool rtt_started(void)
Get whether RTT is started.
Definition: rtt/rtt.c:300
int rtt_register_source(const struct rtt_source source, struct target *target)
Register an RTT source for a target.
Definition: rtt/rtt.c:106
int rtt_exit(void)
Shutdown Real-Time Transfer (RTT).
Definition: rtt/rtt.c:65
static int adjust_sink_list(size_t length)
Definition: rtt/rtt.c:185
const struct rtt_control * rtt_get_control(void)
Get the RTT control block.
Definition: rtt/rtt.c:315
int rtt_get_polling_interval(unsigned int *interval)
Get the polling interval.
Definition: rtt/rtt.c:262
int rtt_setup(target_addr_t address, size_t size, const char *id)
Setup RTT.
Definition: rtt/rtt.c:88
size_t sink_list_length
Definition: rtt/rtt.c:43
int rtt_read_channel_info(unsigned int channel_index, enum rtt_channel_type type, struct rtt_channel_info *info)
Read channel information.
Definition: rtt/rtt.c:320
static int read_channel_callback(void *user_data)
Definition: rtt/rtt.c:72
struct rtt_source source
Definition: rtt/rtt.c:23
int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer, size_t *length)
Write to an RTT channel.
Definition: rtt/rtt.c:288
#define RTT_CB_MAX_ID_LENGTH
Control block ID length in bytes, including the trailing null-terminator.
Definition: rtt/rtt.h:19
int(* rtt_sink_read)(unsigned int channel, const uint8_t *buffer, size_t length, void *user_data)
Definition: rtt/rtt.h:80
rtt_channel_type
Channel type.
Definition: rtt/rtt.h:91
RTT channel information.
Definition: rtt/rtt.h:65
RTT control block.
Definition: rtt/rtt.h:31
struct rtt_sink_list * next
Definition: rtt/rtt.h:87
rtt_sink_read read
Definition: rtt/rtt.h:84
void * user_data
Definition: rtt/rtt.h:85
RTT source.
Definition: rtt/rtt.h:119
rtt_source_find_ctrl_block find_cb
Definition: rtt/rtt.h:120
rtt_source_start start
Definition: rtt/rtt.h:123
rtt_source_stop stop
Definition: rtt/rtt.h:124
rtt_source_write write
Definition: rtt/rtt.h:126
rtt_source_read_ctrl_block read_cb
Definition: rtt/rtt.h:121
rtt_source_read_channel_info read_channel_info
Definition: rtt/rtt.h:122
rtt_source_read read
Definition: rtt/rtt.h:125
Definition: target.h:116
int target_unregister_timer_callback(int(*callback)(void *priv), void *priv)
Definition: target.c:1748
int target_register_timer_callback(int(*callback)(void *priv), unsigned int time_ms, enum target_timer_type type, void *priv)
The period is very approximate, the callback can happen much more often or much more rarely than spec...
Definition: target.c:1658
uint64_t target_addr_t
Definition: types.h:335
#define TARGET_PRIxADDR
Definition: types.h:340
static struct ublast_lowlevel_priv info
#define NULL
Definition: usb.h:16