rtos: remove config.h includes from stackings headers
[openocd.git] / src / rtos / uCOS-III.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2017 by Square, Inc. *
5 * Steven Stallion <stallion@squareup.com> *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <helper/log.h>
13 #include <helper/time_support.h>
14 #include <helper/types.h>
15 #include <rtos/rtos.h>
16 #include <target/target.h>
17 #include <target/target_type.h>
18
19 #include "rtos_ucos_iii_stackings.h"
20
21 #ifndef UCOS_III_MAX_STRLEN
22 #define UCOS_III_MAX_STRLEN 64
23 #endif
24
25 #ifndef UCOS_III_MAX_THREADS
26 #define UCOS_III_MAX_THREADS 256
27 #endif
28
29 struct ucos_iii_params {
30 const char *target_name;
31 const unsigned char pointer_width;
32 symbol_address_t thread_stack_offset;
33 symbol_address_t thread_name_offset;
34 symbol_address_t thread_state_offset;
35 symbol_address_t thread_priority_offset;
36 symbol_address_t thread_prev_offset;
37 symbol_address_t thread_next_offset;
38 bool thread_offsets_updated;
39 size_t threadid_start;
40 const struct rtos_register_stacking *stacking_info;
41 size_t num_threads;
42 symbol_address_t threads[];
43 };
44
45 static const struct ucos_iii_params ucos_iii_params_list[] = {
46 {
47 "cortex_m", /* target_name */
48 sizeof(uint32_t), /* pointer_width */
49 0, /* thread_stack_offset */
50 0, /* thread_name_offset */
51 0, /* thread_state_offset */
52 0, /* thread_priority_offset */
53 0, /* thread_prev_offset */
54 0, /* thread_next_offset */
55 false, /* thread_offsets_updated */
56 1, /* threadid_start */
57 &rtos_ucos_iii_cortex_m_stacking, /* stacking_info */
58 0, /* num_threads */
59 },
60 {
61 "esirisc", /* target_name */
62 sizeof(uint32_t), /* pointer_width */
63 0, /* thread_stack_offset */
64 0, /* thread_name_offset */
65 0, /* thread_state_offset */
66 0, /* thread_priority_offset */
67 0, /* thread_prev_offset */
68 0, /* thread_next_offset */
69 false, /* thread_offsets_updated */
70 1, /* threadid_start */
71 &rtos_ucos_iii_esi_risc_stacking, /* stacking_info */
72 0, /* num_threads */
73 },
74 };
75
76 static const char * const ucos_iii_symbol_list[] = {
77 "OSRunning",
78 "OSTCBCurPtr",
79 "OSTaskDbgListPtr",
80 "OSTaskQty",
81
82 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
83 "openocd_OS_TCB_StkPtr_offset",
84 "openocd_OS_TCB_NamePtr_offset",
85 "openocd_OS_TCB_TaskState_offset",
86 "openocd_OS_TCB_Prio_offset",
87 "openocd_OS_TCB_DbgPrevPtr_offset",
88 "openocd_OS_TCB_DbgNextPtr_offset",
89 NULL
90 };
91
92 enum ucos_iii_symbol_values {
93 UCOS_III_VAL_OS_RUNNING,
94 UCOS_III_VAL_OS_TCB_CUR_PTR,
95 UCOS_III_VAL_OS_TASK_DBG_LIST_PTR,
96 UCOS_III_VAL_OS_TASK_QTY,
97
98 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
99 UCOS_III_VAL_OS_TCB_STK_PTR_OFFSET,
100 UCOS_III_VAL_OS_TCB_NAME_PTR_OFFSET,
101 UCOS_III_VAL_OS_TCB_TASK_STATE_OFFSET,
102 UCOS_III_VAL_OS_TCB_PRIO_OFFSET,
103 UCOS_III_VAL_OS_TCB_DBG_PREV_PTR_OFFSET,
104 UCOS_III_VAL_OS_TCB_DBG_NEXT_PTR_OFFSET,
105 };
106
107 static const char * const ucos_iii_thread_state_list[] = {
108 "Ready",
109 "Delay",
110 "Pend",
111 "Pend Timeout",
112 "Suspended",
113 "Delay Suspended",
114 "Pend Suspended",
115 "Pend Timeout Suspended",
116 };
117
118 static int ucos_iii_find_or_create_thread(struct rtos *rtos, symbol_address_t thread_address,
119 threadid_t *threadid)
120 {
121 struct ucos_iii_params *params = rtos->rtos_specific_params;
122 size_t thread_index;
123
124 for (thread_index = 0; thread_index < params->num_threads; thread_index++)
125 if (params->threads[thread_index] == thread_address)
126 goto found;
127
128 if (params->num_threads == UCOS_III_MAX_THREADS) {
129 LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS");
130 return ERROR_FAIL;
131 }
132
133 params->threads[thread_index] = thread_address;
134 params->num_threads++;
135 found:
136 *threadid = thread_index + params->threadid_start;
137 return ERROR_OK;
138 }
139
140 static int ucos_iii_find_thread_address(struct rtos *rtos, threadid_t threadid,
141 symbol_address_t *thread_address)
142 {
143 struct ucos_iii_params *params = rtos->rtos_specific_params;
144 size_t thread_index;
145
146 thread_index = threadid - params->threadid_start;
147 if (thread_index >= params->num_threads) {
148 LOG_ERROR("uCOS-III: failed to find thread address");
149 return ERROR_FAIL;
150 }
151
152 *thread_address = params->threads[thread_index];
153 return ERROR_OK;
154 }
155
156 static int ucos_iii_find_last_thread_address(struct rtos *rtos, symbol_address_t *thread_address)
157 {
158 struct ucos_iii_params *params = rtos->rtos_specific_params;
159 int retval;
160
161 /* read the thread list head */
162 symbol_address_t thread_list_address = 0;
163
164 retval = target_read_memory(rtos->target,
165 rtos->symbols[UCOS_III_VAL_OS_TASK_DBG_LIST_PTR].address,
166 params->pointer_width,
167 1,
168 (void *)&thread_list_address);
169 if (retval != ERROR_OK) {
170 LOG_ERROR("uCOS-III: failed to read thread list address");
171 return retval;
172 }
173
174 /* advance to end of thread list */
175 do {
176 *thread_address = thread_list_address;
177
178 retval = target_read_memory(rtos->target,
179 thread_list_address + params->thread_next_offset,
180 params->pointer_width,
181 1,
182 (void *)&thread_list_address);
183 if (retval != ERROR_OK) {
184 LOG_ERROR("uCOS-III: failed to read next thread address");
185 return retval;
186 }
187 } while (thread_list_address != 0);
188
189 return ERROR_OK;
190 }
191
192 static int ucos_iii_update_thread_offsets(struct rtos *rtos)
193 {
194 struct ucos_iii_params *params = rtos->rtos_specific_params;
195
196 if (params->thread_offsets_updated)
197 return ERROR_OK;
198
199 const struct thread_offset_map {
200 enum ucos_iii_symbol_values symbol_value;
201 symbol_address_t *thread_offset;
202 } thread_offset_maps[] = {
203 {
204 UCOS_III_VAL_OS_TCB_STK_PTR_OFFSET,
205 &params->thread_stack_offset,
206 },
207 {
208 UCOS_III_VAL_OS_TCB_NAME_PTR_OFFSET,
209 &params->thread_name_offset,
210 },
211 {
212 UCOS_III_VAL_OS_TCB_TASK_STATE_OFFSET,
213 &params->thread_state_offset,
214 },
215 {
216 UCOS_III_VAL_OS_TCB_PRIO_OFFSET,
217 &params->thread_priority_offset,
218 },
219 {
220 UCOS_III_VAL_OS_TCB_DBG_PREV_PTR_OFFSET,
221 &params->thread_prev_offset,
222 },
223 {
224 UCOS_III_VAL_OS_TCB_DBG_NEXT_PTR_OFFSET,
225 &params->thread_next_offset,
226 },
227 };
228
229 for (size_t i = 0; i < ARRAY_SIZE(thread_offset_maps); i++) {
230 const struct thread_offset_map *thread_offset_map = &thread_offset_maps[i];
231
232 int retval = target_read_memory(rtos->target,
233 rtos->symbols[thread_offset_map->symbol_value].address,
234 params->pointer_width,
235 1,
236 (void *)thread_offset_map->thread_offset);
237 if (retval != ERROR_OK) {
238 LOG_ERROR("uCOS-III: failed to read thread offset");
239 return retval;
240 }
241 }
242
243 params->thread_offsets_updated = true;
244 return ERROR_OK;
245 }
246
247 static bool ucos_iii_detect_rtos(struct target *target)
248 {
249 return target->rtos->symbols &&
250 target->rtos->symbols[UCOS_III_VAL_OS_RUNNING].address != 0;
251 }
252
253 static int ucos_iii_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv)
254 {
255 struct ucos_iii_params *params = target->rtos->rtos_specific_params;
256
257 params->thread_offsets_updated = false;
258 params->num_threads = 0;
259
260 return ERROR_OK;
261 }
262
263 static int ucos_iii_create(struct target *target)
264 {
265 struct ucos_iii_params *params;
266
267 for (size_t i = 0; i < ARRAY_SIZE(ucos_iii_params_list); i++)
268 if (strcmp(ucos_iii_params_list[i].target_name, target->type->name) == 0) {
269 params = malloc(sizeof(*params) + (UCOS_III_MAX_THREADS * sizeof(*params->threads)));
270 if (!params) {
271 LOG_ERROR("uCOS-III: out of memory");
272 return ERROR_FAIL;
273 }
274
275 memcpy(params, &ucos_iii_params_list[i], sizeof(ucos_iii_params_list[i]));
276 target->rtos->rtos_specific_params = (void *)params;
277
278 target_register_reset_callback(ucos_iii_reset_handler, NULL);
279
280 return ERROR_OK;
281 }
282
283 LOG_ERROR("uCOS-III: target not supported: %s", target->type->name);
284 return ERROR_FAIL;
285 }
286
287 static int ucos_iii_update_threads(struct rtos *rtos)
288 {
289 struct ucos_iii_params *params = rtos->rtos_specific_params;
290 int retval;
291
292 if (!rtos->symbols) {
293 LOG_ERROR("uCOS-III: symbol list not loaded");
294 return ERROR_FAIL;
295 }
296
297 /* free previous thread details */
298 rtos_free_threadlist(rtos);
299
300 /* verify RTOS is running */
301 uint8_t rtos_running;
302
303 retval = target_read_u8(rtos->target,
304 rtos->symbols[UCOS_III_VAL_OS_RUNNING].address,
305 &rtos_running);
306 if (retval != ERROR_OK) {
307 LOG_ERROR("uCOS-III: failed to read RTOS running");
308 return retval;
309 }
310
311 if (rtos_running != 1 && rtos_running != 0) {
312 LOG_ERROR("uCOS-III: invalid RTOS running value");
313 return ERROR_FAIL;
314 }
315
316 if (!rtos_running) {
317 rtos->thread_details = calloc(1, sizeof(struct thread_detail));
318 if (!rtos->thread_details) {
319 LOG_ERROR("uCOS-III: out of memory");
320 return ERROR_FAIL;
321 }
322
323 rtos->thread_count = 1;
324 rtos->thread_details->threadid = 0;
325 rtos->thread_details->exists = true;
326 rtos->current_thread = 0;
327
328 return ERROR_OK;
329 }
330
331 /* update thread offsets */
332 retval = ucos_iii_update_thread_offsets(rtos);
333 if (retval != ERROR_OK) {
334 LOG_ERROR("uCOS-III: failed to update thread offsets");
335 return retval;
336 }
337
338 /* read current thread address */
339 symbol_address_t current_thread_address = 0;
340
341 retval = target_read_memory(rtos->target,
342 rtos->symbols[UCOS_III_VAL_OS_TCB_CUR_PTR].address,
343 params->pointer_width,
344 1,
345 (void *)&current_thread_address);
346 if (retval != ERROR_OK) {
347 LOG_ERROR("uCOS-III: failed to read current thread address");
348 return retval;
349 }
350
351 /* read number of tasks */
352 retval = target_read_u16(rtos->target,
353 rtos->symbols[UCOS_III_VAL_OS_TASK_QTY].address,
354 (void *)&rtos->thread_count);
355 if (retval != ERROR_OK) {
356 LOG_ERROR("uCOS-III: failed to read thread count");
357 return retval;
358 }
359
360 rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
361 if (!rtos->thread_details) {
362 LOG_ERROR("uCOS-III: out of memory");
363 return ERROR_FAIL;
364 }
365
366 /*
367 * uC/OS-III adds tasks in LIFO order; advance to the end of the
368 * list and work backwards to preserve the intended order.
369 */
370 symbol_address_t thread_address = 0;
371
372 retval = ucos_iii_find_last_thread_address(rtos, &thread_address);
373 if (retval != ERROR_OK) {
374 LOG_ERROR("uCOS-III: failed to find last thread address");
375 return retval;
376 }
377
378 for (int i = 0; i < rtos->thread_count; i++) {
379 struct thread_detail *thread_detail = &rtos->thread_details[i];
380 char thread_str_buffer[UCOS_III_MAX_STRLEN + 1];
381
382 /* find or create new threadid */
383 retval = ucos_iii_find_or_create_thread(rtos, thread_address, &thread_detail->threadid);
384 if (retval != ERROR_OK) {
385 LOG_ERROR("uCOS-III: failed to find or create thread");
386 return retval;
387 }
388
389 if (thread_address == current_thread_address)
390 rtos->current_thread = thread_detail->threadid;
391
392 thread_detail->exists = true;
393
394 /* read thread name */
395 symbol_address_t thread_name_address = 0;
396
397 retval = target_read_memory(rtos->target,
398 thread_address + params->thread_name_offset,
399 params->pointer_width,
400 1,
401 (void *)&thread_name_address);
402 if (retval != ERROR_OK) {
403 LOG_ERROR("uCOS-III: failed to name address");
404 return retval;
405 }
406
407 retval = target_read_buffer(rtos->target,
408 thread_name_address,
409 sizeof(thread_str_buffer),
410 (void *)thread_str_buffer);
411 if (retval != ERROR_OK) {
412 LOG_ERROR("uCOS-III: failed to read thread name");
413 return retval;
414 }
415
416 thread_str_buffer[sizeof(thread_str_buffer) - 1] = '\0';
417 thread_detail->thread_name_str = strdup(thread_str_buffer);
418
419 /* read thread extra info */
420 uint8_t thread_state;
421 uint8_t thread_priority;
422
423 retval = target_read_u8(rtos->target,
424 thread_address + params->thread_state_offset,
425 &thread_state);
426 if (retval != ERROR_OK) {
427 LOG_ERROR("uCOS-III: failed to read thread state");
428 return retval;
429 }
430
431 retval = target_read_u8(rtos->target,
432 thread_address + params->thread_priority_offset,
433 &thread_priority);
434 if (retval != ERROR_OK) {
435 LOG_ERROR("uCOS-III: failed to read thread priority");
436 return retval;
437 }
438
439 const char *thread_state_str;
440
441 if (thread_state < ARRAY_SIZE(ucos_iii_thread_state_list))
442 thread_state_str = ucos_iii_thread_state_list[thread_state];
443 else
444 thread_state_str = "Unknown";
445
446 snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d",
447 thread_state_str, thread_priority);
448 thread_detail->extra_info_str = strdup(thread_str_buffer);
449
450 /* read previous thread address */
451 retval = target_read_memory(rtos->target,
452 thread_address + params->thread_prev_offset,
453 params->pointer_width,
454 1,
455 (void *)&thread_address);
456 if (retval != ERROR_OK) {
457 LOG_ERROR("uCOS-III: failed to read previous thread address");
458 return retval;
459 }
460 }
461
462 return ERROR_OK;
463 }
464
465 static int ucos_iii_get_thread_reg_list(struct rtos *rtos, threadid_t threadid,
466 struct rtos_reg **reg_list, int *num_regs)
467 {
468 struct ucos_iii_params *params = rtos->rtos_specific_params;
469 int retval;
470
471 /* find thread address for threadid */
472 symbol_address_t thread_address = 0;
473
474 retval = ucos_iii_find_thread_address(rtos, threadid, &thread_address);
475 if (retval != ERROR_OK) {
476 LOG_ERROR("uCOS-III: failed to find thread address");
477 return retval;
478 }
479
480 /* read thread stack address */
481 symbol_address_t stack_address = 0;
482
483 retval = target_read_memory(rtos->target,
484 thread_address + params->thread_stack_offset,
485 params->pointer_width,
486 1,
487 (void *)&stack_address);
488 if (retval != ERROR_OK) {
489 LOG_ERROR("uCOS-III: failed to read stack address");
490 return retval;
491 }
492
493 return rtos_generic_stack_read(rtos->target,
494 params->stacking_info,
495 stack_address,
496 reg_list,
497 num_regs);
498 }
499
500 static int ucos_iii_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
501 {
502 *symbol_list = calloc(ARRAY_SIZE(ucos_iii_symbol_list), sizeof(struct symbol_table_elem));
503 if (!*symbol_list) {
504 LOG_ERROR("uCOS-III: out of memory");
505 return ERROR_FAIL;
506 }
507
508 for (size_t i = 0; i < ARRAY_SIZE(ucos_iii_symbol_list); i++)
509 (*symbol_list)[i].symbol_name = ucos_iii_symbol_list[i];
510
511 return ERROR_OK;
512 }
513
514 const struct rtos_type ucos_iii_rtos = {
515 .name = "uCOS-III",
516 .detect_rtos = ucos_iii_detect_rtos,
517 .create = ucos_iii_create,
518 .update_threads = ucos_iii_update_threads,
519 .get_thread_reg_list = ucos_iii_get_thread_reg_list,
520 .get_symbol_list_to_lookup = ucos_iii_get_symbol_list_to_lookup,
521 };

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)