jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / rtos / riot.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2015 by Daniel Krebs *
5 * Daniel Krebs - github@daniel-krebs.net *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <helper/time_support.h>
13 #include <jtag/jtag.h>
14 #include "target/target.h"
15 #include "target/target_type.h"
16 #include "rtos.h"
17 #include "helper/log.h"
18 #include "helper/types.h"
19 #include "target/armv7m.h"
20 #include "rtos_riot_stackings.h"
21
22 static bool riot_detect_rtos(struct target *target);
23 static int riot_create(struct target *target);
24 static int riot_update_threads(struct rtos *rtos);
25 static int riot_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
26 struct rtos_reg **reg_list, int *num_regs);
27 static int riot_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
28
29 struct riot_thread_state {
30 int value;
31 const char *desc;
32 };
33
34 /* refer RIOT sched.h */
35 static const struct riot_thread_state riot_thread_states[] = {
36 { 0, "Stopped" },
37 { 1, "Zombie" },
38 { 2, "Sleeping" },
39 { 3, "Blocked mutex" },
40 { 4, "Blocked receive" },
41 { 5, "Blocked send" },
42 { 6, "Blocked reply" },
43 { 7, "Blocked any flag" },
44 { 8, "Blocked all flags" },
45 { 9, "Blocked mbox" },
46 { 10, "Blocked condition" },
47 { 11, "Running" },
48 { 12, "Pending" },
49 };
50 #define RIOT_NUM_STATES ARRAY_SIZE(riot_thread_states)
51
52 struct riot_params {
53 const char *target_name;
54 unsigned char thread_sp_offset;
55 unsigned char thread_status_offset;
56 };
57
58 static const struct riot_params riot_params_list[] = {
59 {
60 "cortex_m", /* target_name */
61 0x00, /* thread_sp_offset */
62 0x04, /* thread_status_offset */
63 },
64 { /* STLink */
65 "hla_target", /* target_name */
66 0x00, /* thread_sp_offset */
67 0x04, /* thread_status_offset */
68 }
69 };
70 #define RIOT_NUM_PARAMS ARRAY_SIZE(riot_params_list)
71
72 /* Initialize in riot_create() depending on architecture */
73 static const struct rtos_register_stacking *stacking_info;
74
75 enum riot_symbol_values {
76 RIOT_THREADS_BASE = 0,
77 RIOT_NUM_THREADS,
78 RIOT_ACTIVE_PID,
79 RIOT_MAX_THREADS,
80 RIOT_NAME_OFFSET,
81 };
82
83 struct riot_symbol {
84 const char *const name;
85 bool optional;
86 };
87
88 /* refer RIOT core/sched.c */
89 static struct riot_symbol const riot_symbol_list[] = {
90 {"sched_threads", false},
91 {"sched_num_threads", false},
92 {"sched_active_pid", false},
93 {"max_threads", false},
94 {"_tcb_name_offset", true},
95 {NULL, false}
96 };
97
98 const struct rtos_type riot_rtos = {
99 .name = "RIOT",
100 .detect_rtos = riot_detect_rtos,
101 .create = riot_create,
102 .update_threads = riot_update_threads,
103 .get_thread_reg_list = riot_get_thread_reg_list,
104 .get_symbol_list_to_lookup = riot_get_symbol_list_to_lookup,
105 };
106
107 static int riot_update_threads(struct rtos *rtos)
108 {
109 int retval;
110 int tasks_found = 0;
111 const struct riot_params *param;
112
113 if (!rtos)
114 return ERROR_FAIL;
115
116 if (!rtos->rtos_specific_params)
117 return ERROR_FAIL;
118
119 param = (const struct riot_params *)rtos->rtos_specific_params;
120
121 if (!rtos->symbols) {
122 LOG_ERROR("No symbols for RIOT");
123 return ERROR_FAIL;
124 }
125
126 if (rtos->symbols[RIOT_THREADS_BASE].address == 0) {
127 LOG_ERROR("Can't find symbol `%s`",
128 riot_symbol_list[RIOT_THREADS_BASE].name);
129 return ERROR_FAIL;
130 }
131
132 /* wipe out previous thread details if any */
133 rtos_free_threadlist(rtos);
134
135 /* Reset values */
136 rtos->current_thread = 0;
137 rtos->thread_count = 0;
138
139 /* read the current thread id */
140 int16_t active_pid = 0;
141 retval = target_read_u16(rtos->target,
142 rtos->symbols[RIOT_ACTIVE_PID].address,
143 (uint16_t *)&active_pid);
144 if (retval != ERROR_OK) {
145 LOG_ERROR("Can't read symbol `%s`",
146 riot_symbol_list[RIOT_ACTIVE_PID].name);
147 return retval;
148 }
149 rtos->current_thread = active_pid;
150
151 /* read the current thread count
152 * It's `int` in RIOT, but this is Cortex M* only anyway */
153 int32_t thread_count = 0;
154 retval = target_read_u16(rtos->target,
155 rtos->symbols[RIOT_NUM_THREADS].address,
156 (uint16_t *)&thread_count);
157 if (retval != ERROR_OK) {
158 LOG_ERROR("Can't read symbol `%s`",
159 riot_symbol_list[RIOT_NUM_THREADS].name);
160 return retval;
161 }
162
163 /* read the maximum number of threads */
164 uint8_t max_threads = 0;
165 retval = target_read_u8(rtos->target,
166 rtos->symbols[RIOT_MAX_THREADS].address,
167 &max_threads);
168 if (retval != ERROR_OK) {
169 LOG_ERROR("Can't read symbol `%s`",
170 riot_symbol_list[RIOT_MAX_THREADS].name);
171 return retval;
172 }
173 if (thread_count > max_threads) {
174 LOG_ERROR("Thread count is invalid");
175 return ERROR_FAIL;
176 }
177 rtos->thread_count = thread_count;
178
179 /* Base address of thread array */
180 uint32_t threads_base = rtos->symbols[RIOT_THREADS_BASE].address;
181
182 /* Try to get the offset of tcb_t::name, if absent RIOT wasn't compiled
183 * with DEVELHELP, so there are no thread names */
184 uint8_t name_offset = 0;
185 if (rtos->symbols[RIOT_NAME_OFFSET].address != 0) {
186 retval = target_read_u8(rtos->target,
187 rtos->symbols[RIOT_NAME_OFFSET].address,
188 &name_offset);
189 if (retval != ERROR_OK) {
190 LOG_ERROR("Can't read symbol `%s`",
191 riot_symbol_list[RIOT_NAME_OFFSET].name);
192 return retval;
193 }
194 }
195
196 /* Allocate memory for thread description */
197 rtos->thread_details = calloc(thread_count, sizeof(struct thread_detail));
198 if (!rtos->thread_details) {
199 LOG_ERROR("RIOT: out of memory");
200 return ERROR_FAIL;
201 }
202
203 /* Buffer for thread names, maximum to display is 32 */
204 char buffer[32];
205
206 for (unsigned int i = 0; i < max_threads; i++) {
207 if (tasks_found == rtos->thread_count)
208 break;
209
210 /* get pointer to tcb_t */
211 uint32_t tcb_pointer = 0;
212 retval = target_read_u32(rtos->target,
213 threads_base + (i * 4),
214 &tcb_pointer);
215 if (retval != ERROR_OK) {
216 LOG_ERROR("Can't parse `%s`",
217 riot_symbol_list[RIOT_THREADS_BASE].name);
218 goto error;
219 }
220
221 if (tcb_pointer == 0) {
222 /* PID unused */
223 continue;
224 }
225
226 /* Index is PID */
227 rtos->thread_details[tasks_found].threadid = i;
228
229 /* read thread state */
230 uint8_t status = 0;
231 retval = target_read_u8(rtos->target,
232 tcb_pointer + param->thread_status_offset,
233 &status);
234 if (retval != ERROR_OK) {
235 LOG_ERROR("Can't parse `%s`",
236 riot_symbol_list[RIOT_THREADS_BASE].name);
237 goto error;
238 }
239
240 /* Search for state */
241 unsigned int k;
242 for (k = 0; k < RIOT_NUM_STATES; k++) {
243 if (riot_thread_states[k].value == status)
244 break;
245 }
246
247 /* Copy state string */
248 if (k >= RIOT_NUM_STATES) {
249 rtos->thread_details[tasks_found].extra_info_str =
250 strdup("unknown state");
251 } else {
252 rtos->thread_details[tasks_found].extra_info_str =
253 strdup(riot_thread_states[k].desc);
254 }
255
256 if (!rtos->thread_details[tasks_found].extra_info_str) {
257 LOG_ERROR("RIOT: out of memory");
258 retval = ERROR_FAIL;
259 goto error;
260 }
261
262 /* Thread names are only available if compiled with DEVELHELP */
263 if (name_offset != 0) {
264 uint32_t name_pointer = 0;
265 retval = target_read_u32(rtos->target,
266 tcb_pointer + name_offset,
267 &name_pointer);
268 if (retval != ERROR_OK) {
269 LOG_ERROR("Can't parse `%s`",
270 riot_symbol_list[RIOT_THREADS_BASE].name);
271 goto error;
272 }
273
274 /* read thread name */
275 retval = target_read_buffer(rtos->target,
276 name_pointer,
277 sizeof(buffer),
278 (uint8_t *)&buffer);
279 if (retval != ERROR_OK) {
280 LOG_ERROR("Can't parse `%s`",
281 riot_symbol_list[RIOT_THREADS_BASE].name);
282 goto error;
283 }
284
285 /* Make sure the string in the buffer terminates */
286 if (buffer[sizeof(buffer) - 1] != 0)
287 buffer[sizeof(buffer) - 1] = 0;
288
289 /* Copy thread name */
290 rtos->thread_details[tasks_found].thread_name_str =
291 strdup(buffer);
292
293 } else {
294 rtos->thread_details[tasks_found].thread_name_str =
295 strdup("Enable DEVELHELP to see task names");
296 }
297
298 if (!rtos->thread_details[tasks_found].thread_name_str) {
299 LOG_ERROR("RIOT: out of memory");
300 retval = ERROR_FAIL;
301 goto error;
302 }
303
304 rtos->thread_details[tasks_found].exists = true;
305
306 tasks_found++;
307 }
308
309 return ERROR_OK;
310
311 error:
312 rtos_free_threadlist(rtos);
313 return retval;
314 }
315
316 static int riot_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
317 struct rtos_reg **reg_list, int *num_regs)
318 {
319 int retval;
320 const struct riot_params *param;
321
322 if (!rtos)
323 return ERROR_FAIL;
324
325 if (thread_id == 0)
326 return ERROR_FAIL;
327
328 if (!rtos->rtos_specific_params)
329 return ERROR_FAIL;
330
331 param = (const struct riot_params *)rtos->rtos_specific_params;
332
333 /* find the thread with given thread id */
334 uint32_t threads_base = rtos->symbols[RIOT_THREADS_BASE].address;
335 uint32_t tcb_pointer = 0;
336 retval = target_read_u32(rtos->target,
337 threads_base + (thread_id * 4),
338 &tcb_pointer);
339 if (retval != ERROR_OK) {
340 LOG_ERROR("Can't parse `%s`", riot_symbol_list[RIOT_THREADS_BASE].name);
341 return retval;
342 }
343
344 /* read stack pointer for that thread */
345 uint32_t stackptr = 0;
346 retval = target_read_u32(rtos->target,
347 tcb_pointer + param->thread_sp_offset,
348 &stackptr);
349 if (retval != ERROR_OK) {
350 LOG_ERROR("Can't parse `%s`", riot_symbol_list[RIOT_THREADS_BASE].name);
351 return retval;
352 }
353
354 return rtos_generic_stack_read(rtos->target,
355 stacking_info,
356 stackptr,
357 reg_list,
358 num_regs);
359 }
360
361 static int riot_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
362 {
363 *symbol_list = calloc(ARRAY_SIZE(riot_symbol_list), sizeof(struct symbol_table_elem));
364
365 if (!*symbol_list) {
366 LOG_ERROR("RIOT: out of memory");
367 return ERROR_FAIL;
368 }
369
370 for (unsigned int i = 0; i < ARRAY_SIZE(riot_symbol_list); i++) {
371 (*symbol_list)[i].symbol_name = riot_symbol_list[i].name;
372 (*symbol_list)[i].optional = riot_symbol_list[i].optional;
373 }
374
375 return ERROR_OK;
376 }
377
378 static bool riot_detect_rtos(struct target *target)
379 {
380 if ((target->rtos->symbols) &&
381 (target->rtos->symbols[RIOT_THREADS_BASE].address != 0)) {
382 /* looks like RIOT */
383 return true;
384 }
385 return false;
386 }
387
388 static int riot_create(struct target *target)
389 {
390 unsigned int i = 0;
391
392 /* lookup if target is supported by RIOT */
393 while ((i < RIOT_NUM_PARAMS) &&
394 (strcmp(riot_params_list[i].target_name, target->type->name) != 0)) {
395 i++;
396 }
397 if (i >= RIOT_NUM_PARAMS) {
398 LOG_ERROR("Could not find target in RIOT compatibility list");
399 return ERROR_FAIL;
400 }
401
402 target->rtos->rtos_specific_params = (void *)&riot_params_list[i];
403 target->rtos->current_thread = 0;
404 target->rtos->thread_details = NULL;
405
406 /* Stacking is different depending on architecture */
407 struct armv7m_common *armv7m_target = target_to_armv7m(target);
408
409 if (armv7m_target->arm.arch == ARM_ARCH_V6M)
410 stacking_info = &rtos_riot_cortex_m0_stacking;
411 else if (is_armv7m(armv7m_target))
412 stacking_info = &rtos_riot_cortex_m34_stacking;
413 else {
414 LOG_ERROR("No stacking info for architecture");
415 return ERROR_FAIL;
416 }
417 return ERROR_OK;
418 }

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)