jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / rtos / embKernel.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2011 by Broadcom Corporation *
5 * Evan Hunter - ehunter@broadcom.com *
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 "rtos_embkernel_stackings.h"
20
21 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
22
23 static bool embkernel_detect_rtos(struct target *target);
24 static int embkernel_create(struct target *target);
25 static int embkernel_update_threads(struct rtos *rtos);
26 static int embkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
27 struct rtos_reg **reg_list, int *num_regs);
28 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
29
30 const struct rtos_type embkernel_rtos = {
31 .name = "embKernel",
32 .detect_rtos = embkernel_detect_rtos,
33 .create = embkernel_create,
34 .update_threads = embkernel_update_threads,
35 .get_thread_reg_list =
36 embkernel_get_thread_reg_list,
37 .get_symbol_list_to_lookup = embkernel_get_symbol_list_to_lookup,
38 };
39
40 enum {
41 SYMBOL_ID_S_CURRENT_TASK = 0,
42 SYMBOL_ID_S_LIST_READY = 1,
43 SYMBOL_ID_S_LIST_SLEEP = 2,
44 SYMBOL_ID_S_LIST_SUSPENDED = 3,
45 SYMBOL_ID_S_MAX_PRIORITIES = 4,
46 SYMBOL_ID_S_CURRENT_TASK_COUNT = 5,
47 };
48
49 static const char * const embkernel_symbol_list[] = {
50 "Rtos::sCurrentTask",
51 "Rtos::sListReady",
52 "Rtos::sListSleep",
53 "Rtos::sListSuspended",
54 "Rtos::sMaxPriorities",
55 "Rtos::sCurrentTaskCount",
56 NULL };
57
58 struct embkernel_params {
59 const char *target_name;
60 const unsigned char pointer_width;
61 const unsigned char thread_count_width;
62 const unsigned char rtos_list_size;
63 const unsigned char thread_stack_offset;
64 const unsigned char thread_name_offset;
65 const unsigned char thread_priority_offset;
66 const unsigned char thread_priority_width;
67 const unsigned char iterable_next_offset;
68 const unsigned char iterable_task_owner_offset;
69 const struct rtos_register_stacking *stacking_info;
70 };
71
72 static const struct embkernel_params embkernel_params_list[] = {
73 {
74 "cortex_m", /* target_name */
75 4, /* pointer_width */
76 4, /* thread_count_width */
77 8, /*rtos_list_size */
78 0, /*thread_stack_offset */
79 4, /*thread_name_offset */
80 8, /*thread_priority_offset */
81 4, /*thread_priority_width */
82 4, /*iterable_next_offset */
83 12, /*iterable_task_owner_offset */
84 &rtos_embkernel_cortex_m_stacking, /* stacking_info*/
85 },
86 { "hla_target", /* target_name */
87 4, /* pointer_width */
88 4, /* thread_count_width */
89 8, /*rtos_list_size */
90 0, /*thread_stack_offset */
91 4, /*thread_name_offset */
92 8, /*thread_priority_offset */
93 4, /*thread_priority_width */
94 4, /*iterable_next_offset */
95 12, /*iterable_task_owner_offset */
96 &rtos_embkernel_cortex_m_stacking, /* stacking_info */
97 }
98 };
99
100 static bool embkernel_detect_rtos(struct target *target)
101 {
102 if (target->rtos->symbols) {
103 if (target->rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address != 0)
104 return true;
105 }
106 return false;
107 }
108
109 static int embkernel_create(struct target *target)
110 {
111 size_t i = 0;
112 while ((i < ARRAY_SIZE(embkernel_params_list)) &&
113 (strcmp(embkernel_params_list[i].target_name, target->type->name) != 0))
114 i++;
115
116 if (i >= ARRAY_SIZE(embkernel_params_list)) {
117 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
118 "list", target->type->name);
119 return -1;
120 }
121
122 target->rtos->rtos_specific_params = (void *) &embkernel_params_list[i];
123 return 0;
124 }
125
126 static int embkernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embkernel_params *param,
127 struct thread_detail *details, const char *state_str)
128 {
129 int64_t task = 0;
130 int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width,
131 (uint8_t *) &task);
132 if (retval != ERROR_OK)
133 return retval;
134 details->threadid = (threadid_t) task;
135 details->exists = true;
136
137 int64_t name_ptr = 0;
138 retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width,
139 (uint8_t *) &name_ptr);
140 if (retval != ERROR_OK)
141 return retval;
142
143 details->thread_name_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
144 if (name_ptr) {
145 retval = target_read_buffer(rtos->target, name_ptr, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE,
146 (uint8_t *) details->thread_name_str);
147 if (retval != ERROR_OK)
148 return retval;
149 details->thread_name_str[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE - 1] = 0;
150 } else {
151 snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task);
152 }
153
154 int64_t priority = 0;
155 retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width,
156 (uint8_t *) &priority);
157 if (retval != ERROR_OK)
158 return retval;
159 details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
160 if (task == rtos->current_thread) {
161 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u",
162 (unsigned int) priority);
163 } else {
164 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u",
165 state_str, (unsigned int) priority);
166 }
167
168 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
169 (unsigned int)task, details->thread_name_str);
170 return 0;
171 }
172
173 static int embkernel_update_threads(struct rtos *rtos)
174 {
175 /* int i = 0; */
176 int retval;
177 const struct embkernel_params *param;
178
179 if (!rtos)
180 return -1;
181
182 if (!rtos->rtos_specific_params)
183 return -3;
184
185 if (!rtos->symbols) {
186 LOG_ERROR("No symbols for embKernel");
187 return -4;
188 }
189
190 if (rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address == 0) {
191 LOG_ERROR("Don't have the thread list head");
192 return -2;
193 }
194
195 /* wipe out previous thread details if any */
196 rtos_free_threadlist(rtos);
197
198 param = (const struct embkernel_params *) rtos->rtos_specific_params;
199
200 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address, param->pointer_width,
201 (uint8_t *) &rtos->current_thread);
202 if (retval != ERROR_OK) {
203 LOG_ERROR("Error reading current thread in embKernel thread list");
204 return retval;
205 }
206
207 int64_t max_used_priority = 0;
208 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_MAX_PRIORITIES].address, param->pointer_width,
209 (uint8_t *) &max_used_priority);
210 if (retval != ERROR_OK)
211 return retval;
212
213 int thread_list_size = 0;
214 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_CURRENT_TASK_COUNT].address,
215 param->thread_count_width, (uint8_t *) &thread_list_size);
216
217 if (retval != ERROR_OK) {
218 LOG_ERROR("Could not read embKernel thread count from target");
219 return retval;
220 }
221
222 /* create space for new thread details */
223 rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
224 if (!rtos->thread_details) {
225 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
226 return ERROR_FAIL;
227 }
228
229 int thread_idx = 0;
230 /* Look for ready tasks */
231 for (int pri = 0; pri < max_used_priority; pri++) {
232 /* Get first item in queue */
233 int64_t iterable = 0;
234 retval = target_read_buffer(rtos->target,
235 rtos->symbols[SYMBOL_ID_S_LIST_READY].address + (pri * param->rtos_list_size), param->pointer_width,
236 (uint8_t *) &iterable);
237 if (retval != ERROR_OK)
238 return retval;
239 for (; iterable && thread_idx < thread_list_size; thread_idx++) {
240 /* Get info from this iterable item */
241 retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Ready");
242 if (retval != ERROR_OK)
243 return retval;
244 /* Get next iterable item */
245 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
246 (uint8_t *) &iterable);
247 if (retval != ERROR_OK)
248 return retval;
249 }
250 }
251 /* Look for sleeping tasks */
252 int64_t iterable = 0;
253 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_LIST_SLEEP].address, param->pointer_width,
254 (uint8_t *) &iterable);
255 if (retval != ERROR_OK)
256 return retval;
257 for (; iterable && thread_idx < thread_list_size; thread_idx++) {
258 /*Get info from this iterable item */
259 retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Sleeping");
260 if (retval != ERROR_OK)
261 return retval;
262 /*Get next iterable item */
263 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
264 (uint8_t *) &iterable);
265 if (retval != ERROR_OK)
266 return retval;
267 }
268
269 /* Look for suspended tasks */
270 iterable = 0;
271 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_LIST_SUSPENDED].address, param->pointer_width,
272 (uint8_t *) &iterable);
273 if (retval != ERROR_OK)
274 return retval;
275 for (; iterable && thread_idx < thread_list_size; thread_idx++) {
276 /* Get info from this iterable item */
277 retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Suspended");
278 if (retval != ERROR_OK)
279 return retval;
280 /*Get next iterable item */
281 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
282 (uint8_t *) &iterable);
283 if (retval != ERROR_OK)
284 return retval;
285 }
286
287 rtos->thread_count = 0;
288 rtos->thread_count = thread_idx;
289 LOG_OUTPUT("Found %u tasks\n", (unsigned int)thread_idx);
290 return 0;
291 }
292
293 static int embkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
294 struct rtos_reg **reg_list, int *num_regs)
295 {
296 int retval;
297 const struct embkernel_params *param;
298 int64_t stack_ptr = 0;
299
300 if (!rtos)
301 return -1;
302
303 if (thread_id == 0)
304 return -2;
305
306 if (!rtos->rtos_specific_params)
307 return -1;
308
309 param = (const struct embkernel_params *) rtos->rtos_specific_params;
310
311 /* Read the stack pointer */
312 retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width,
313 (uint8_t *) &stack_ptr);
314 if (retval != ERROR_OK) {
315 LOG_ERROR("Error reading stack frame from embKernel thread");
316 return retval;
317 }
318
319 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, reg_list, num_regs);
320 }
321
322 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
323 {
324 unsigned int i;
325 *symbol_list = calloc(ARRAY_SIZE(embkernel_symbol_list), sizeof(struct symbol_table_elem));
326
327 for (i = 0; i < ARRAY_SIZE(embkernel_symbol_list); i++)
328 (*symbol_list)[i].symbol_name = embkernel_symbol_list[i];
329
330 return 0;
331 }

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)