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