1 /***************************************************************************
2 * Copyright (C) 2017 by Square, Inc. *
3 * Steven Stallion <stallion@squareup.com> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
23 #include <helper/log.h>
24 #include <helper/time_support.h>
25 #include <helper/types.h>
26 #include <rtos/rtos.h>
27 #include <target/target.h>
28 #include <target/target_type.h>
30 #include "rtos_ucos_iii_stackings.h"
32 #ifndef UCOS_III_MAX_STRLEN
33 #define UCOS_III_MAX_STRLEN 64
36 #ifndef UCOS_III_MAX_THREADS
37 #define UCOS_III_MAX_THREADS 256
40 struct uCOS_III_params
{
41 const char *target_name
;
42 const unsigned char pointer_width
;
43 symbol_address_t thread_stack_offset
;
44 symbol_address_t thread_name_offset
;
45 symbol_address_t thread_state_offset
;
46 symbol_address_t thread_priority_offset
;
47 symbol_address_t thread_prev_offset
;
48 symbol_address_t thread_next_offset
;
49 bool thread_offsets_updated
;
50 size_t threadid_start
;
51 const struct rtos_register_stacking
*stacking_info
;
53 symbol_address_t threads
[];
56 static const struct uCOS_III_params uCOS_III_params_list
[] = {
58 "cortex_m", /* target_name */
59 sizeof(uint32_t), /* pointer_width */
60 0, /* thread_stack_offset */
61 0, /* thread_name_offset */
62 0, /* thread_state_offset */
63 0, /* thread_priority_offset */
64 0, /* thread_prev_offset */
65 0, /* thread_next_offset */
66 false, /* thread_offsets_updated */
67 1, /* threadid_start */
68 &rtos_uCOS_III_Cortex_M_stacking
, /* stacking_info */
72 "esirisc", /* target_name */
73 sizeof(uint32_t), /* pointer_width */
74 0, /* thread_stack_offset */
75 0, /* thread_name_offset */
76 0, /* thread_state_offset */
77 0, /* thread_priority_offset */
78 0, /* thread_prev_offset */
79 0, /* thread_next_offset */
80 false, /* thread_offsets_updated */
81 1, /* threadid_start */
82 &rtos_uCOS_III_eSi_RISC_stacking
, /* stacking_info */
87 static const char * const uCOS_III_symbol_list
[] = {
93 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
94 "openocd_OS_TCB_StkPtr_offset",
95 "openocd_OS_TCB_NamePtr_offset",
96 "openocd_OS_TCB_TaskState_offset",
97 "openocd_OS_TCB_Prio_offset",
98 "openocd_OS_TCB_DbgPrevPtr_offset",
99 "openocd_OS_TCB_DbgNextPtr_offset",
103 enum uCOS_III_symbol_values
{
104 uCOS_III_VAL_OSRunning
,
105 uCOS_III_VAL_OSTCBCurPtr
,
106 uCOS_III_VAL_OSTaskDbgListPtr
,
107 uCOS_III_VAL_OSTaskQty
,
109 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
110 uCOS_III_VAL_OS_TCB_StkPtr_offset
,
111 uCOS_III_VAL_OS_TCB_NamePtr_offset
,
112 uCOS_III_VAL_OS_TCB_TaskState_offset
,
113 uCOS_III_VAL_OS_TCB_Prio_offset
,
114 uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset
,
115 uCOS_III_VAL_OS_TCB_DbgNextPtr_offset
,
118 static const char * const uCOS_III_thread_state_list
[] = {
126 "Pend Timeout Suspended",
129 static int uCOS_III_find_or_create_thread(struct rtos
*rtos
, symbol_address_t thread_address
,
130 threadid_t
*threadid
)
132 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
135 for (thread_index
= 0; thread_index
< params
->num_threads
; thread_index
++)
136 if (params
->threads
[thread_index
] == thread_address
)
139 if (params
->num_threads
== UCOS_III_MAX_THREADS
) {
140 LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS");
144 params
->threads
[thread_index
] = thread_address
;
145 params
->num_threads
++;
147 *threadid
= thread_index
+ params
->threadid_start
;
151 static int uCOS_III_find_thread_address(struct rtos
*rtos
, threadid_t threadid
,
152 symbol_address_t
*thread_address
)
154 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
157 thread_index
= threadid
- params
->threadid_start
;
158 if (thread_index
>= params
->num_threads
) {
159 LOG_ERROR("uCOS-III: failed to find thread address");
163 *thread_address
= params
->threads
[thread_index
];
167 static int uCOS_III_find_last_thread_address(struct rtos
*rtos
, symbol_address_t
*thread_address
)
169 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
172 /* read the thread list head */
173 symbol_address_t thread_list_address
= 0;
175 retval
= target_read_memory(rtos
->target
,
176 rtos
->symbols
[uCOS_III_VAL_OSTaskDbgListPtr
].address
,
177 params
->pointer_width
,
179 (void *)&thread_list_address
);
180 if (retval
!= ERROR_OK
) {
181 LOG_ERROR("uCOS-III: failed to read thread list address");
185 /* advance to end of thread list */
187 *thread_address
= thread_list_address
;
189 retval
= target_read_memory(rtos
->target
,
190 thread_list_address
+ params
->thread_next_offset
,
191 params
->pointer_width
,
193 (void *)&thread_list_address
);
194 if (retval
!= ERROR_OK
) {
195 LOG_ERROR("uCOS-III: failed to read next thread address");
198 } while (thread_list_address
!= 0);
203 static int uCOS_III_update_thread_offsets(struct rtos
*rtos
)
205 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
207 if (params
->thread_offsets_updated
)
210 const struct thread_offset_map
{
211 enum uCOS_III_symbol_values symbol_value
;
212 symbol_address_t
*thread_offset
;
213 } thread_offset_maps
[] = {
215 uCOS_III_VAL_OS_TCB_StkPtr_offset
,
216 ¶ms
->thread_stack_offset
,
219 uCOS_III_VAL_OS_TCB_NamePtr_offset
,
220 ¶ms
->thread_name_offset
,
223 uCOS_III_VAL_OS_TCB_TaskState_offset
,
224 ¶ms
->thread_state_offset
,
227 uCOS_III_VAL_OS_TCB_Prio_offset
,
228 ¶ms
->thread_priority_offset
,
231 uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset
,
232 ¶ms
->thread_prev_offset
,
235 uCOS_III_VAL_OS_TCB_DbgNextPtr_offset
,
236 ¶ms
->thread_next_offset
,
240 for (size_t i
= 0; i
< ARRAY_SIZE(thread_offset_maps
); i
++) {
241 const struct thread_offset_map
*thread_offset_map
= &thread_offset_maps
[i
];
243 int retval
= target_read_memory(rtos
->target
,
244 rtos
->symbols
[thread_offset_map
->symbol_value
].address
,
245 params
->pointer_width
,
247 (void *)thread_offset_map
->thread_offset
);
248 if (retval
!= ERROR_OK
) {
249 LOG_ERROR("uCOS-III: failed to read thread offset");
254 params
->thread_offsets_updated
= true;
258 static bool uCOS_III_detect_rtos(struct target
*target
)
260 return target
->rtos
->symbols
!= NULL
&&
261 target
->rtos
->symbols
[uCOS_III_VAL_OSRunning
].address
!= 0;
264 static int uCOS_III_reset_handler(struct target
*target
, enum target_reset_mode reset_mode
, void *priv
)
266 struct uCOS_III_params
*params
= target
->rtos
->rtos_specific_params
;
268 params
->thread_offsets_updated
= false;
269 params
->num_threads
= 0;
274 static int uCOS_III_create(struct target
*target
)
276 struct uCOS_III_params
*params
;
278 for (size_t i
= 0; i
< ARRAY_SIZE(uCOS_III_params_list
); i
++)
279 if (strcmp(uCOS_III_params_list
[i
].target_name
, target
->type
->name
) == 0) {
280 params
= malloc(sizeof(*params
) + (UCOS_III_MAX_THREADS
* sizeof(*params
->threads
)));
281 if (params
== NULL
) {
282 LOG_ERROR("uCOS-III: out of memory");
286 memcpy(params
, &uCOS_III_params_list
[i
], sizeof(uCOS_III_params_list
[i
]));
287 target
->rtos
->rtos_specific_params
= (void *)params
;
289 target_register_reset_callback(uCOS_III_reset_handler
, NULL
);
294 LOG_ERROR("uCOS-III: target not supported: %s", target
->type
->name
);
298 static int uCOS_III_update_threads(struct rtos
*rtos
)
300 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
303 if (rtos
->symbols
== NULL
) {
304 LOG_ERROR("uCOS-III: symbol list not loaded");
308 /* free previous thread details */
309 rtos_free_threadlist(rtos
);
311 /* verify RTOS is running */
312 uint8_t rtos_running
;
314 retval
= target_read_u8(rtos
->target
,
315 rtos
->symbols
[uCOS_III_VAL_OSRunning
].address
,
317 if (retval
!= ERROR_OK
) {
318 LOG_ERROR("uCOS-III: failed to read RTOS running");
322 if (rtos_running
!= 1 && rtos_running
!= 0) {
323 LOG_ERROR("uCOS-III: invalid RTOS running value");
328 rtos
->thread_details
= calloc(1, sizeof(struct thread_detail
));
329 if (rtos
->thread_details
== NULL
) {
330 LOG_ERROR("uCOS-III: out of memory");
334 rtos
->thread_count
= 1;
335 rtos
->thread_details
->threadid
= 0;
336 rtos
->thread_details
->exists
= true;
337 rtos
->current_thread
= 0;
342 /* update thread offsets */
343 retval
= uCOS_III_update_thread_offsets(rtos
);
344 if (retval
!= ERROR_OK
) {
345 LOG_ERROR("uCOS-III: failed to update thread offsets");
349 /* read current thread address */
350 symbol_address_t current_thread_address
= 0;
352 retval
= target_read_memory(rtos
->target
,
353 rtos
->symbols
[uCOS_III_VAL_OSTCBCurPtr
].address
,
354 params
->pointer_width
,
356 (void *)¤t_thread_address
);
357 if (retval
!= ERROR_OK
) {
358 LOG_ERROR("uCOS-III: failed to read current thread address");
362 /* read number of tasks */
363 retval
= target_read_u16(rtos
->target
,
364 rtos
->symbols
[uCOS_III_VAL_OSTaskQty
].address
,
365 (void *)&rtos
->thread_count
);
366 if (retval
!= ERROR_OK
) {
367 LOG_ERROR("uCOS-III: failed to read thread count");
371 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
372 if (rtos
->thread_details
== NULL
) {
373 LOG_ERROR("uCOS-III: out of memory");
378 * uC/OS-III adds tasks in LIFO order; advance to the end of the
379 * list and work backwards to preserve the intended order.
381 symbol_address_t thread_address
= 0;
383 retval
= uCOS_III_find_last_thread_address(rtos
, &thread_address
);
384 if (retval
!= ERROR_OK
) {
385 LOG_ERROR("uCOS-III: failed to find last thread address");
389 for (int i
= 0; i
< rtos
->thread_count
; i
++) {
390 struct thread_detail
*thread_detail
= &rtos
->thread_details
[i
];
391 char thread_str_buffer
[UCOS_III_MAX_STRLEN
+ 1];
393 /* find or create new threadid */
394 retval
= uCOS_III_find_or_create_thread(rtos
, thread_address
, &thread_detail
->threadid
);
395 if (retval
!= ERROR_OK
) {
396 LOG_ERROR("uCOS-III: failed to find or create thread");
400 if (thread_address
== current_thread_address
)
401 rtos
->current_thread
= thread_detail
->threadid
;
403 thread_detail
->exists
= true;
405 /* read thread name */
406 symbol_address_t thread_name_address
= 0;
408 retval
= target_read_memory(rtos
->target
,
409 thread_address
+ params
->thread_name_offset
,
410 params
->pointer_width
,
412 (void *)&thread_name_address
);
413 if (retval
!= ERROR_OK
) {
414 LOG_ERROR("uCOS-III: failed to name address");
418 retval
= target_read_buffer(rtos
->target
,
420 sizeof(thread_str_buffer
),
421 (void *)thread_str_buffer
);
422 if (retval
!= ERROR_OK
) {
423 LOG_ERROR("uCOS-III: failed to read thread name");
427 thread_str_buffer
[sizeof(thread_str_buffer
) - 1] = '\0';
428 thread_detail
->thread_name_str
= strdup(thread_str_buffer
);
430 /* read thread extra info */
431 uint8_t thread_state
;
432 uint8_t thread_priority
;
434 retval
= target_read_u8(rtos
->target
,
435 thread_address
+ params
->thread_state_offset
,
437 if (retval
!= ERROR_OK
) {
438 LOG_ERROR("uCOS-III: failed to read thread state");
442 retval
= target_read_u8(rtos
->target
,
443 thread_address
+ params
->thread_priority_offset
,
445 if (retval
!= ERROR_OK
) {
446 LOG_ERROR("uCOS-III: failed to read thread priority");
450 const char *thread_state_str
;
452 if (thread_state
< ARRAY_SIZE(uCOS_III_thread_state_list
))
453 thread_state_str
= uCOS_III_thread_state_list
[thread_state
];
455 thread_state_str
= "Unknown";
457 snprintf(thread_str_buffer
, sizeof(thread_str_buffer
), "State: %s, Priority: %d",
458 thread_state_str
, thread_priority
);
459 thread_detail
->extra_info_str
= strdup(thread_str_buffer
);
461 /* read previous thread address */
462 retval
= target_read_memory(rtos
->target
,
463 thread_address
+ params
->thread_prev_offset
,
464 params
->pointer_width
,
466 (void *)&thread_address
);
467 if (retval
!= ERROR_OK
) {
468 LOG_ERROR("uCOS-III: failed to read previous thread address");
476 static int uCOS_III_get_thread_reg_list(struct rtos
*rtos
, threadid_t threadid
,
477 struct rtos_reg
**reg_list
, int *num_regs
)
479 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
482 /* find thread address for threadid */
483 symbol_address_t thread_address
= 0;
485 retval
= uCOS_III_find_thread_address(rtos
, threadid
, &thread_address
);
486 if (retval
!= ERROR_OK
) {
487 LOG_ERROR("uCOS-III: failed to find thread address");
491 /* read thread stack address */
492 symbol_address_t stack_address
= 0;
494 retval
= target_read_memory(rtos
->target
,
495 thread_address
+ params
->thread_stack_offset
,
496 params
->pointer_width
,
498 (void *)&stack_address
);
499 if (retval
!= ERROR_OK
) {
500 LOG_ERROR("uCOS-III: failed to read stack address");
504 return rtos_generic_stack_read(rtos
->target
,
505 params
->stacking_info
,
511 static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
513 *symbol_list
= calloc(ARRAY_SIZE(uCOS_III_symbol_list
), sizeof(symbol_table_elem_t
));
514 if (*symbol_list
== NULL
) {
515 LOG_ERROR("uCOS-III: out of memory");
519 for (size_t i
= 0; i
< ARRAY_SIZE(uCOS_III_symbol_list
); i
++)
520 (*symbol_list
)[i
].symbol_name
= uCOS_III_symbol_list
[i
];
525 const struct rtos_type uCOS_III_rtos
= {
527 .detect_rtos
= uCOS_III_detect_rtos
,
528 .create
= uCOS_III_create
,
529 .update_threads
= uCOS_III_update_threads
,
530 .get_thread_reg_list
= uCOS_III_get_thread_reg_list
,
531 .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)