tcl: add get_bit & get_bitfield memory helper functions
[openocd.git] / 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 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)