HACKING: add chapter on checkpatch
[fw/openocd] / src / rtt / tcl.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /*
4  * Copyright (C) 2019-2020 by Marc Schink <dev@zapb.de>
5  */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include <helper/log.h>
12 #include <target/rtt.h>
13
14 #include "rtt.h"
15
16 #define CHANNEL_NAME_SIZE       128
17
18 COMMAND_HANDLER(handle_rtt_setup_command)
19 {
20 struct rtt_source source;
21
22         if (CMD_ARGC != 3)
23                 return ERROR_COMMAND_SYNTAX_ERROR;
24
25         source.find_cb = &target_rtt_find_control_block;
26         source.read_cb = &target_rtt_read_control_block;
27         source.start = &target_rtt_start;
28         source.stop = &target_rtt_stop;
29         source.read = &target_rtt_read_callback;
30         source.write = &target_rtt_write_callback;
31         source.read_channel_info = &target_rtt_read_channel_info;
32
33         target_addr_t address;
34         uint32_t size;
35
36         COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[0], address);
37         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
38
39         rtt_register_source(source, get_current_target(CMD_CTX));
40
41         if (rtt_setup(address, size, CMD_ARGV[2]) != ERROR_OK)
42                 return ERROR_FAIL;
43
44         return ERROR_OK;
45 }
46
47 COMMAND_HANDLER(handle_rtt_start_command)
48 {
49         if (CMD_ARGC > 0)
50                 return ERROR_COMMAND_SYNTAX_ERROR;
51
52         if (!rtt_configured()) {
53                 command_print(CMD, "RTT is not configured");
54                 return ERROR_FAIL;
55         }
56
57         return rtt_start();
58 }
59
60 COMMAND_HANDLER(handle_rtt_stop_command)
61 {
62         if (CMD_ARGC > 0)
63                 return ERROR_COMMAND_SYNTAX_ERROR;
64
65         return rtt_stop();
66 }
67
68 COMMAND_HANDLER(handle_rtt_polling_interval_command)
69 {
70         if (CMD_ARGC == 0) {
71                 int ret;
72                 unsigned int interval;
73
74                 ret = rtt_get_polling_interval(&interval);
75
76                 if (ret != ERROR_OK) {
77                         command_print(CMD, "Failed to get polling interval");
78                         return ret;
79                 }
80
81                 command_print(CMD, "%u ms", interval);
82         } else if (CMD_ARGC == 1) {
83                 int ret;
84                 unsigned int interval;
85
86                 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], interval);
87                 ret = rtt_set_polling_interval(interval);
88
89                 if (ret != ERROR_OK) {
90                         command_print(CMD, "Failed to set polling interval");
91                         return ret;
92                 }
93         } else {
94                 return ERROR_COMMAND_SYNTAX_ERROR;
95         }
96
97         return ERROR_OK;
98 }
99
100 COMMAND_HANDLER(handle_rtt_channels_command)
101 {
102         int ret;
103         char channel_name[CHANNEL_NAME_SIZE];
104         const struct rtt_control *ctrl;
105         struct rtt_channel_info info;
106
107         if (!rtt_found_cb()) {
108                 command_print(CMD, "rtt: Control block not available");
109                 return ERROR_FAIL;
110         }
111
112         ctrl = rtt_get_control();
113
114         command_print(CMD, "Channels: up=%u, down=%u", ctrl->num_up_channels,
115                 ctrl->num_down_channels);
116
117         command_print(CMD, "Up-channels:");
118
119         info.name = channel_name;
120         info.name_length = sizeof(channel_name);
121
122         for (unsigned int i = 0; i < ctrl->num_up_channels; i++) {
123                 ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info);
124
125                 if (ret != ERROR_OK)
126                         return ret;
127
128                 if (!info.size)
129                         continue;
130
131                 command_print(CMD, "%u: %s %u %u", i, info.name, info.size,
132                         info.flags);
133         }
134
135         command_print(CMD, "Down-channels:");
136
137         for (unsigned int i = 0; i < ctrl->num_down_channels; i++) {
138                 ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, &info);
139
140                 if (ret != ERROR_OK)
141                         return ret;
142
143                 if (!info.size)
144                         continue;
145
146                 command_print(CMD, "%u: %s %u %u", i, info.name, info.size,
147                         info.flags);
148         }
149
150         return ERROR_OK;
151 }
152
153 static int jim_channel_list(Jim_Interp *interp, int argc,
154         Jim_Obj * const *argv)
155 {
156         Jim_Obj *list;
157         Jim_Obj *channel_list;
158         char channel_name[CHANNEL_NAME_SIZE];
159         const struct rtt_control *ctrl;
160         struct rtt_channel_info info;
161
162         if (!rtt_found_cb()) {
163                 Jim_SetResultFormatted(interp, "rtt: Control block not available");
164                 return ERROR_FAIL;
165         }
166
167         ctrl = rtt_get_control();
168
169         info.name = channel_name;
170         info.name_length = sizeof(channel_name);
171
172         list = Jim_NewListObj(interp, NULL, 0);
173         channel_list = Jim_NewListObj(interp, NULL, 0);
174
175         for (unsigned int i = 0; i < ctrl->num_up_channels; i++) {
176                 int ret;
177                 Jim_Obj *tmp;
178
179                 ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info);
180
181                 if (ret != ERROR_OK)
182                         return ret;
183
184                 if (!info.size)
185                         continue;
186
187                 tmp = Jim_NewListObj(interp, NULL, 0);
188
189                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
190                         "name", -1));
191                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
192                         info.name, -1));
193
194                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
195                         "size", -1));
196                 Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
197                         info.size));
198
199                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
200                         "flags", -1));
201                 Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
202                         info.flags));
203
204                 Jim_ListAppendElement(interp, channel_list, tmp);
205         }
206
207         Jim_ListAppendElement(interp, list, channel_list);
208
209         channel_list = Jim_NewListObj(interp, NULL, 0);
210
211         for (unsigned int i = 0; i < ctrl->num_down_channels; i++) {
212                 int ret;
213                 Jim_Obj *tmp;
214
215                 ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, &info);
216
217                 if (ret != ERROR_OK)
218                         return ret;
219
220                 if (!info.size)
221                         continue;
222
223                 tmp = Jim_NewListObj(interp, NULL, 0);
224
225                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
226                         "name", -1));
227                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
228                         info.name, -1));
229
230                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
231                         "size", -1));
232                 Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
233                         info.size));
234
235                 Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
236                         "flags", -1));
237                 Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
238                         info.flags));
239
240                 Jim_ListAppendElement(interp, channel_list, tmp);
241         }
242
243         Jim_ListAppendElement(interp, list, channel_list);
244         Jim_SetResult(interp, list);
245
246         return JIM_OK;
247 }
248
249 static const struct command_registration rtt_subcommand_handlers[] = {
250         {
251                 .name = "setup",
252                 .handler = handle_rtt_setup_command,
253                 .mode = COMMAND_ANY,
254                 .help = "setup RTT",
255                 .usage = "<address> <size> <ID>"
256         },
257         {
258                 .name = "start",
259                 .handler = handle_rtt_start_command,
260                 .mode = COMMAND_EXEC,
261                 .help = "start RTT",
262                 .usage = ""
263         },
264         {
265                 .name = "stop",
266                 .handler = handle_rtt_stop_command,
267                 .mode = COMMAND_EXEC,
268                 .help = "stop RTT",
269                 .usage = ""
270         },
271         {
272                 .name = "polling_interval",
273                 .handler = handle_rtt_polling_interval_command,
274                 .mode = COMMAND_EXEC,
275                 .help = "show or set polling interval in ms",
276                 .usage = "[interval]"
277         },
278         {
279                 .name = "channels",
280                 .handler = handle_rtt_channels_command,
281                 .mode = COMMAND_EXEC,
282                 .help = "list available channels",
283                 .usage = ""
284         },
285         {
286                 .name = "channellist",
287                 .jim_handler = jim_channel_list,
288                 .mode = COMMAND_EXEC,
289                 .help = "list available channels",
290                 .usage = ""
291         },
292         COMMAND_REGISTRATION_DONE
293 };
294
295 const struct command_registration rtt_target_command_handlers[] = {
296         {
297                 .name = "rtt",
298                 .mode = COMMAND_EXEC,
299                 .help = "RTT target commands",
300                 .usage = "",
301                 .chain = rtt_subcommand_handlers
302         },
303         COMMAND_REGISTRATION_DONE
304 };