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 size_t threadid_start
;
33 const struct rtos_register_stacking
*stacking_info
;
36 struct ucos_iii_private
{
37 const struct ucos_iii_params
*params
;
38 symbol_address_t thread_stack_offset
;
39 symbol_address_t thread_name_offset
;
40 symbol_address_t thread_state_offset
;
41 symbol_address_t thread_priority_offset
;
42 symbol_address_t thread_prev_offset
;
43 symbol_address_t thread_next_offset
;
44 bool thread_offsets_updated
;
46 symbol_address_t threads
[UCOS_III_MAX_THREADS
];
49 static const struct ucos_iii_params ucos_iii_params_list
[] = {
51 .target_name
= "cortex_m",
52 .pointer_width
= sizeof(uint32_t),
54 .stacking_info
= &rtos_ucos_iii_cortex_m_stacking
,
57 .target_name
= "esirisc",
58 .pointer_width
= sizeof(uint32_t),
60 .stacking_info
= &rtos_ucos_iii_esi_risc_stacking
,
64 static const char * const ucos_iii_symbol_list
[] = {
70 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
71 "openocd_OS_TCB_StkPtr_offset",
72 "openocd_OS_TCB_NamePtr_offset",
73 "openocd_OS_TCB_TaskState_offset",
74 "openocd_OS_TCB_Prio_offset",
75 "openocd_OS_TCB_DbgPrevPtr_offset",
76 "openocd_OS_TCB_DbgNextPtr_offset",
80 enum ucos_iii_symbol_values
{
81 UCOS_III_VAL_OS_RUNNING
,
82 UCOS_III_VAL_OS_TCB_CUR_PTR
,
83 UCOS_III_VAL_OS_TASK_DBG_LIST_PTR
,
84 UCOS_III_VAL_OS_TASK_QTY
,
86 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
87 UCOS_III_VAL_OS_TCB_STK_PTR_OFFSET
,
88 UCOS_III_VAL_OS_TCB_NAME_PTR_OFFSET
,
89 UCOS_III_VAL_OS_TCB_TASK_STATE_OFFSET
,
90 UCOS_III_VAL_OS_TCB_PRIO_OFFSET
,
91 UCOS_III_VAL_OS_TCB_DBG_PREV_PTR_OFFSET
,
92 UCOS_III_VAL_OS_TCB_DBG_NEXT_PTR_OFFSET
,
95 static const char * const ucos_iii_thread_state_list
[] = {
103 "Pend Timeout Suspended",
106 static int ucos_iii_find_or_create_thread(struct rtos
*rtos
, symbol_address_t thread_address
,
107 threadid_t
*threadid
)
109 struct ucos_iii_private
*params
= rtos
->rtos_specific_params
;
112 for (thread_index
= 0; thread_index
< params
->num_threads
; thread_index
++)
113 if (params
->threads
[thread_index
] == thread_address
)
116 if (params
->num_threads
== UCOS_III_MAX_THREADS
) {
117 LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS");
121 params
->threads
[thread_index
] = thread_address
;
122 params
->num_threads
++;
124 *threadid
= thread_index
+ params
->params
->threadid_start
;
128 static int ucos_iii_find_thread_address(struct rtos
*rtos
, threadid_t threadid
,
129 symbol_address_t
*thread_address
)
131 struct ucos_iii_private
*params
= rtos
->rtos_specific_params
;
134 thread_index
= threadid
- params
->params
->threadid_start
;
135 if (thread_index
>= params
->num_threads
) {
136 LOG_ERROR("uCOS-III: failed to find thread address");
140 *thread_address
= params
->threads
[thread_index
];
144 static int ucos_iii_find_last_thread_address(struct rtos
*rtos
, symbol_address_t
*thread_address
)
146 struct ucos_iii_private
*params
= rtos
->rtos_specific_params
;
149 /* read the thread list head */
150 symbol_address_t thread_list_address
= 0;
152 retval
= target_read_memory(rtos
->target
,
153 rtos
->symbols
[UCOS_III_VAL_OS_TASK_DBG_LIST_PTR
].address
,
154 params
->params
->pointer_width
,
156 (void *)&thread_list_address
);
157 if (retval
!= ERROR_OK
) {
158 LOG_ERROR("uCOS-III: failed to read thread list address");
162 /* advance to end of thread list */
164 *thread_address
= thread_list_address
;
166 retval
= target_read_memory(rtos
->target
,
167 thread_list_address
+ params
->thread_next_offset
,
168 params
->params
->pointer_width
,
170 (void *)&thread_list_address
);
171 if (retval
!= ERROR_OK
) {
172 LOG_ERROR("uCOS-III: failed to read next thread address");
175 } while (thread_list_address
!= 0);
180 static int ucos_iii_update_thread_offsets(struct rtos
*rtos
)
182 struct ucos_iii_private
*params
= rtos
->rtos_specific_params
;
184 if (params
->thread_offsets_updated
)
187 const struct thread_offset_map
{
188 enum ucos_iii_symbol_values symbol_value
;
189 symbol_address_t
*thread_offset
;
190 } thread_offset_maps
[] = {
192 UCOS_III_VAL_OS_TCB_STK_PTR_OFFSET
,
193 ¶ms
->thread_stack_offset
,
196 UCOS_III_VAL_OS_TCB_NAME_PTR_OFFSET
,
197 ¶ms
->thread_name_offset
,
200 UCOS_III_VAL_OS_TCB_TASK_STATE_OFFSET
,
201 ¶ms
->thread_state_offset
,
204 UCOS_III_VAL_OS_TCB_PRIO_OFFSET
,
205 ¶ms
->thread_priority_offset
,
208 UCOS_III_VAL_OS_TCB_DBG_PREV_PTR_OFFSET
,
209 ¶ms
->thread_prev_offset
,
212 UCOS_III_VAL_OS_TCB_DBG_NEXT_PTR_OFFSET
,
213 ¶ms
->thread_next_offset
,
217 for (size_t i
= 0; i
< ARRAY_SIZE(thread_offset_maps
); i
++) {
218 const struct thread_offset_map
*thread_offset_map
= &thread_offset_maps
[i
];
220 int retval
= target_read_memory(rtos
->target
,
221 rtos
->symbols
[thread_offset_map
->symbol_value
].address
,
222 params
->params
->pointer_width
,
224 (void *)thread_offset_map
->thread_offset
);
225 if (retval
!= ERROR_OK
) {
226 LOG_ERROR("uCOS-III: failed to read thread offset");
231 params
->thread_offsets_updated
= true;
235 static bool ucos_iii_detect_rtos(struct target
*target
)
237 return target
->rtos
->symbols
&&
238 target
->rtos
->symbols
[UCOS_III_VAL_OS_RUNNING
].address
!= 0;
241 static int ucos_iii_reset_handler(struct target
*target
, enum target_reset_mode reset_mode
, void *priv
)
243 struct ucos_iii_private
*params
= target
->rtos
->rtos_specific_params
;
245 params
->thread_offsets_updated
= false;
246 params
->num_threads
= 0;
251 static int ucos_iii_create(struct target
*target
)
253 struct ucos_iii_private
*params
;
255 for (size_t i
= 0; i
< ARRAY_SIZE(ucos_iii_params_list
); i
++)
256 if (strcmp(ucos_iii_params_list
[i
].target_name
, target
->type
->name
) == 0) {
257 params
= calloc(1, sizeof(*params
));
259 LOG_ERROR("uCOS-III: out of memory");
263 params
->params
= &ucos_iii_params_list
[i
];
264 target
->rtos
->rtos_specific_params
= (void *)params
;
266 target_register_reset_callback(ucos_iii_reset_handler
, NULL
);
271 LOG_ERROR("uCOS-III: target not supported: %s", target
->type
->name
);
275 static int ucos_iii_update_threads(struct rtos
*rtos
)
277 struct ucos_iii_private
*params
= rtos
->rtos_specific_params
;
280 if (!rtos
->symbols
) {
281 LOG_ERROR("uCOS-III: symbol list not loaded");
285 /* free previous thread details */
286 rtos_free_threadlist(rtos
);
288 /* verify RTOS is running */
289 uint8_t rtos_running
;
291 retval
= target_read_u8(rtos
->target
,
292 rtos
->symbols
[UCOS_III_VAL_OS_RUNNING
].address
,
294 if (retval
!= ERROR_OK
) {
295 LOG_ERROR("uCOS-III: failed to read RTOS running");
299 if (rtos_running
!= 1 && rtos_running
!= 0) {
300 LOG_ERROR("uCOS-III: invalid RTOS running value");
305 rtos
->thread_details
= calloc(1, sizeof(struct thread_detail
));
306 if (!rtos
->thread_details
) {
307 LOG_ERROR("uCOS-III: out of memory");
311 rtos
->thread_count
= 1;
312 rtos
->thread_details
->threadid
= 0;
313 rtos
->thread_details
->exists
= true;
314 rtos
->current_thread
= 0;
319 /* update thread offsets */
320 retval
= ucos_iii_update_thread_offsets(rtos
);
321 if (retval
!= ERROR_OK
) {
322 LOG_ERROR("uCOS-III: failed to update thread offsets");
326 /* read current thread address */
327 symbol_address_t current_thread_address
= 0;
329 retval
= target_read_memory(rtos
->target
,
330 rtos
->symbols
[UCOS_III_VAL_OS_TCB_CUR_PTR
].address
,
331 params
->params
->pointer_width
,
333 (void *)¤t_thread_address
);
334 if (retval
!= ERROR_OK
) {
335 LOG_ERROR("uCOS-III: failed to read current thread address");
339 /* read number of tasks */
340 retval
= target_read_u16(rtos
->target
,
341 rtos
->symbols
[UCOS_III_VAL_OS_TASK_QTY
].address
,
342 (void *)&rtos
->thread_count
);
343 if (retval
!= ERROR_OK
) {
344 LOG_ERROR("uCOS-III: failed to read thread count");
348 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
349 if (!rtos
->thread_details
) {
350 LOG_ERROR("uCOS-III: out of memory");
355 * uC/OS-III adds tasks in LIFO order; advance to the end of the
356 * list and work backwards to preserve the intended order.
358 symbol_address_t thread_address
= 0;
360 retval
= ucos_iii_find_last_thread_address(rtos
, &thread_address
);
361 if (retval
!= ERROR_OK
) {
362 LOG_ERROR("uCOS-III: failed to find last thread address");
366 for (int i
= 0; i
< rtos
->thread_count
; i
++) {
367 struct thread_detail
*thread_detail
= &rtos
->thread_details
[i
];
368 char thread_str_buffer
[UCOS_III_MAX_STRLEN
+ 1];
370 /* find or create new threadid */
371 retval
= ucos_iii_find_or_create_thread(rtos
, thread_address
, &thread_detail
->threadid
);
372 if (retval
!= ERROR_OK
) {
373 LOG_ERROR("uCOS-III: failed to find or create thread");
377 if (thread_address
== current_thread_address
)
378 rtos
->current_thread
= thread_detail
->threadid
;
380 thread_detail
->exists
= true;
382 /* read thread name */
383 symbol_address_t thread_name_address
= 0;
385 retval
= target_read_memory(rtos
->target
,
386 thread_address
+ params
->thread_name_offset
,
387 params
->params
->pointer_width
,
389 (void *)&thread_name_address
);
390 if (retval
!= ERROR_OK
) {
391 LOG_ERROR("uCOS-III: failed to name address");
395 retval
= target_read_buffer(rtos
->target
,
397 sizeof(thread_str_buffer
),
398 (void *)thread_str_buffer
);
399 if (retval
!= ERROR_OK
) {
400 LOG_ERROR("uCOS-III: failed to read thread name");
404 thread_str_buffer
[sizeof(thread_str_buffer
) - 1] = '\0';
405 thread_detail
->thread_name_str
= strdup(thread_str_buffer
);
407 /* read thread extra info */
408 uint8_t thread_state
;
409 uint8_t thread_priority
;
411 retval
= target_read_u8(rtos
->target
,
412 thread_address
+ params
->thread_state_offset
,
414 if (retval
!= ERROR_OK
) {
415 LOG_ERROR("uCOS-III: failed to read thread state");
419 retval
= target_read_u8(rtos
->target
,
420 thread_address
+ params
->thread_priority_offset
,
422 if (retval
!= ERROR_OK
) {
423 LOG_ERROR("uCOS-III: failed to read thread priority");
427 const char *thread_state_str
;
429 if (thread_state
< ARRAY_SIZE(ucos_iii_thread_state_list
))
430 thread_state_str
= ucos_iii_thread_state_list
[thread_state
];
432 thread_state_str
= "Unknown";
434 snprintf(thread_str_buffer
, sizeof(thread_str_buffer
), "State: %s, Priority: %d",
435 thread_state_str
, thread_priority
);
436 thread_detail
->extra_info_str
= strdup(thread_str_buffer
);
438 /* read previous thread address */
439 retval
= target_read_memory(rtos
->target
,
440 thread_address
+ params
->thread_prev_offset
,
441 params
->params
->pointer_width
,
443 (void *)&thread_address
);
444 if (retval
!= ERROR_OK
) {
445 LOG_ERROR("uCOS-III: failed to read previous thread address");
453 static int ucos_iii_get_thread_reg_list(struct rtos
*rtos
, threadid_t threadid
,
454 struct rtos_reg
**reg_list
, int *num_regs
)
456 struct ucos_iii_private
*params
= rtos
->rtos_specific_params
;
459 /* find thread address for threadid */
460 symbol_address_t thread_address
= 0;
462 retval
= ucos_iii_find_thread_address(rtos
, threadid
, &thread_address
);
463 if (retval
!= ERROR_OK
) {
464 LOG_ERROR("uCOS-III: failed to find thread address");
468 /* read thread stack address */
469 symbol_address_t stack_address
= 0;
471 retval
= target_read_memory(rtos
->target
,
472 thread_address
+ params
->thread_stack_offset
,
473 params
->params
->pointer_width
,
475 (void *)&stack_address
);
476 if (retval
!= ERROR_OK
) {
477 LOG_ERROR("uCOS-III: failed to read stack address");
481 return rtos_generic_stack_read(rtos
->target
,
482 params
->params
->stacking_info
,
488 static int ucos_iii_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
490 *symbol_list
= calloc(ARRAY_SIZE(ucos_iii_symbol_list
), sizeof(struct symbol_table_elem
));
492 LOG_ERROR("uCOS-III: out of memory");
496 for (size_t i
= 0; i
< ARRAY_SIZE(ucos_iii_symbol_list
); i
++)
497 (*symbol_list
)[i
].symbol_name
= ucos_iii_symbol_list
[i
];
502 const struct rtos_type ucos_iii_rtos
= {
504 .detect_rtos
= ucos_iii_detect_rtos
,
505 .create
= ucos_iii_create
,
506 .update_threads
= ucos_iii_update_threads
,
507 .get_thread_reg_list
= ucos_iii_get_thread_reg_list
,
508 .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)