1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Square, Inc. *
5 * Steven Stallion <stallion@squareup.com> *
6 ***************************************************************************/
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>
19 #include "rtos_ucos_iii_stackings.h"
21 #ifndef UCOS_III_MAX_STRLEN
22 #define UCOS_III_MAX_STRLEN 64
25 #ifndef UCOS_III_MAX_THREADS
26 #define UCOS_III_MAX_THREADS 256
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
;
42 symbol_address_t threads
[];
45 static const struct ucos_iii_params ucos_iii_params_list
[] = {
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 */
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 */
76 static const char * const ucos_iii_symbol_list
[] = {
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",
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
,
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
,
107 static const char * const ucos_iii_thread_state_list
[] = {
115 "Pend Timeout Suspended",
118 static int ucos_iii_find_or_create_thread(struct rtos
*rtos
, symbol_address_t thread_address
,
119 threadid_t
*threadid
)
121 struct ucos_iii_params
*params
= rtos
->rtos_specific_params
;
124 for (thread_index
= 0; thread_index
< params
->num_threads
; thread_index
++)
125 if (params
->threads
[thread_index
] == thread_address
)
128 if (params
->num_threads
== UCOS_III_MAX_THREADS
) {
129 LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS");
133 params
->threads
[thread_index
] = thread_address
;
134 params
->num_threads
++;
136 *threadid
= thread_index
+ params
->threadid_start
;
140 static int ucos_iii_find_thread_address(struct rtos
*rtos
, threadid_t threadid
,
141 symbol_address_t
*thread_address
)
143 struct ucos_iii_params
*params
= rtos
->rtos_specific_params
;
146 thread_index
= threadid
- params
->threadid_start
;
147 if (thread_index
>= params
->num_threads
) {
148 LOG_ERROR("uCOS-III: failed to find thread address");
152 *thread_address
= params
->threads
[thread_index
];
156 static int ucos_iii_find_last_thread_address(struct rtos
*rtos
, symbol_address_t
*thread_address
)
158 struct ucos_iii_params
*params
= rtos
->rtos_specific_params
;
161 /* read the thread list head */
162 symbol_address_t thread_list_address
= 0;
164 retval
= target_read_memory(rtos
->target
,
165 rtos
->symbols
[UCOS_III_VAL_OS_TASK_DBG_LIST_PTR
].address
,
166 params
->pointer_width
,
168 (void *)&thread_list_address
);
169 if (retval
!= ERROR_OK
) {
170 LOG_ERROR("uCOS-III: failed to read thread list address");
174 /* advance to end of thread list */
176 *thread_address
= thread_list_address
;
178 retval
= target_read_memory(rtos
->target
,
179 thread_list_address
+ params
->thread_next_offset
,
180 params
->pointer_width
,
182 (void *)&thread_list_address
);
183 if (retval
!= ERROR_OK
) {
184 LOG_ERROR("uCOS-III: failed to read next thread address");
187 } while (thread_list_address
!= 0);
192 static int ucos_iii_update_thread_offsets(struct rtos
*rtos
)
194 struct ucos_iii_params
*params
= rtos
->rtos_specific_params
;
196 if (params
->thread_offsets_updated
)
199 const struct thread_offset_map
{
200 enum ucos_iii_symbol_values symbol_value
;
201 symbol_address_t
*thread_offset
;
202 } thread_offset_maps
[] = {
204 UCOS_III_VAL_OS_TCB_STK_PTR_OFFSET
,
205 ¶ms
->thread_stack_offset
,
208 UCOS_III_VAL_OS_TCB_NAME_PTR_OFFSET
,
209 ¶ms
->thread_name_offset
,
212 UCOS_III_VAL_OS_TCB_TASK_STATE_OFFSET
,
213 ¶ms
->thread_state_offset
,
216 UCOS_III_VAL_OS_TCB_PRIO_OFFSET
,
217 ¶ms
->thread_priority_offset
,
220 UCOS_III_VAL_OS_TCB_DBG_PREV_PTR_OFFSET
,
221 ¶ms
->thread_prev_offset
,
224 UCOS_III_VAL_OS_TCB_DBG_NEXT_PTR_OFFSET
,
225 ¶ms
->thread_next_offset
,
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
];
232 int retval
= target_read_memory(rtos
->target
,
233 rtos
->symbols
[thread_offset_map
->symbol_value
].address
,
234 params
->pointer_width
,
236 (void *)thread_offset_map
->thread_offset
);
237 if (retval
!= ERROR_OK
) {
238 LOG_ERROR("uCOS-III: failed to read thread offset");
243 params
->thread_offsets_updated
= true;
247 static bool ucos_iii_detect_rtos(struct target
*target
)
249 return target
->rtos
->symbols
&&
250 target
->rtos
->symbols
[UCOS_III_VAL_OS_RUNNING
].address
!= 0;
253 static int ucos_iii_reset_handler(struct target
*target
, enum target_reset_mode reset_mode
, void *priv
)
255 struct ucos_iii_params
*params
= target
->rtos
->rtos_specific_params
;
257 params
->thread_offsets_updated
= false;
258 params
->num_threads
= 0;
263 static int ucos_iii_create(struct target
*target
)
265 struct ucos_iii_params
*params
;
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
)));
271 LOG_ERROR("uCOS-III: out of memory");
275 memcpy(params
, &ucos_iii_params_list
[i
], sizeof(ucos_iii_params_list
[i
]));
276 target
->rtos
->rtos_specific_params
= (void *)params
;
278 target_register_reset_callback(ucos_iii_reset_handler
, NULL
);
283 LOG_ERROR("uCOS-III: target not supported: %s", target
->type
->name
);
287 static int ucos_iii_update_threads(struct rtos
*rtos
)
289 struct ucos_iii_params
*params
= rtos
->rtos_specific_params
;
292 if (!rtos
->symbols
) {
293 LOG_ERROR("uCOS-III: symbol list not loaded");
297 /* free previous thread details */
298 rtos_free_threadlist(rtos
);
300 /* verify RTOS is running */
301 uint8_t rtos_running
;
303 retval
= target_read_u8(rtos
->target
,
304 rtos
->symbols
[UCOS_III_VAL_OS_RUNNING
].address
,
306 if (retval
!= ERROR_OK
) {
307 LOG_ERROR("uCOS-III: failed to read RTOS running");
311 if (rtos_running
!= 1 && rtos_running
!= 0) {
312 LOG_ERROR("uCOS-III: invalid RTOS running value");
317 rtos
->thread_details
= calloc(1, sizeof(struct thread_detail
));
318 if (!rtos
->thread_details
) {
319 LOG_ERROR("uCOS-III: out of memory");
323 rtos
->thread_count
= 1;
324 rtos
->thread_details
->threadid
= 0;
325 rtos
->thread_details
->exists
= true;
326 rtos
->current_thread
= 0;
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");
338 /* read current thread address */
339 symbol_address_t current_thread_address
= 0;
341 retval
= target_read_memory(rtos
->target
,
342 rtos
->symbols
[UCOS_III_VAL_OS_TCB_CUR_PTR
].address
,
343 params
->pointer_width
,
345 (void *)¤t_thread_address
);
346 if (retval
!= ERROR_OK
) {
347 LOG_ERROR("uCOS-III: failed to read current thread address");
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");
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");
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.
370 symbol_address_t thread_address
= 0;
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");
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];
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");
389 if (thread_address
== current_thread_address
)
390 rtos
->current_thread
= thread_detail
->threadid
;
392 thread_detail
->exists
= true;
394 /* read thread name */
395 symbol_address_t thread_name_address
= 0;
397 retval
= target_read_memory(rtos
->target
,
398 thread_address
+ params
->thread_name_offset
,
399 params
->pointer_width
,
401 (void *)&thread_name_address
);
402 if (retval
!= ERROR_OK
) {
403 LOG_ERROR("uCOS-III: failed to name address");
407 retval
= target_read_buffer(rtos
->target
,
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");
416 thread_str_buffer
[sizeof(thread_str_buffer
) - 1] = '\0';
417 thread_detail
->thread_name_str
= strdup(thread_str_buffer
);
419 /* read thread extra info */
420 uint8_t thread_state
;
421 uint8_t thread_priority
;
423 retval
= target_read_u8(rtos
->target
,
424 thread_address
+ params
->thread_state_offset
,
426 if (retval
!= ERROR_OK
) {
427 LOG_ERROR("uCOS-III: failed to read thread state");
431 retval
= target_read_u8(rtos
->target
,
432 thread_address
+ params
->thread_priority_offset
,
434 if (retval
!= ERROR_OK
) {
435 LOG_ERROR("uCOS-III: failed to read thread priority");
439 const char *thread_state_str
;
441 if (thread_state
< ARRAY_SIZE(ucos_iii_thread_state_list
))
442 thread_state_str
= ucos_iii_thread_state_list
[thread_state
];
444 thread_state_str
= "Unknown";
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
);
450 /* read previous thread address */
451 retval
= target_read_memory(rtos
->target
,
452 thread_address
+ params
->thread_prev_offset
,
453 params
->pointer_width
,
455 (void *)&thread_address
);
456 if (retval
!= ERROR_OK
) {
457 LOG_ERROR("uCOS-III: failed to read previous thread address");
465 static int ucos_iii_get_thread_reg_list(struct rtos
*rtos
, threadid_t threadid
,
466 struct rtos_reg
**reg_list
, int *num_regs
)
468 struct ucos_iii_params
*params
= rtos
->rtos_specific_params
;
471 /* find thread address for threadid */
472 symbol_address_t thread_address
= 0;
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");
480 /* read thread stack address */
481 symbol_address_t stack_address
= 0;
483 retval
= target_read_memory(rtos
->target
,
484 thread_address
+ params
->thread_stack_offset
,
485 params
->pointer_width
,
487 (void *)&stack_address
);
488 if (retval
!= ERROR_OK
) {
489 LOG_ERROR("uCOS-III: failed to read stack address");
493 return rtos_generic_stack_read(rtos
->target
,
494 params
->stacking_info
,
500 static int ucos_iii_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
502 *symbol_list
= calloc(ARRAY_SIZE(ucos_iii_symbol_list
), sizeof(struct symbol_table_elem
));
504 LOG_ERROR("uCOS-III: out of memory");
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
];
514 const struct rtos_type ucos_iii_rtos
= {
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
,
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)