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 /* free previous thread details */
304 rtos_free_threadlist(rtos
);
306 /* verify RTOS is running */
307 uint8_t rtos_running
;
309 retval
= target_read_u8(rtos
->target
,
310 rtos
->symbols
[uCOS_III_VAL_OSRunning
].address
,
312 if (retval
!= ERROR_OK
) {
313 LOG_ERROR("uCOS-III: failed to read RTOS running");
317 if (rtos_running
!= 1 && rtos_running
!= 0) {
318 LOG_ERROR("uCOS-III: invalid RTOS running value");
323 rtos
->thread_details
= calloc(1, sizeof(struct thread_detail
));
324 if (rtos
->thread_details
== NULL
) {
325 LOG_ERROR("uCOS-III: out of memory");
329 rtos
->thread_count
= 1;
330 rtos
->thread_details
->threadid
= 0;
331 rtos
->thread_details
->exists
= true;
332 rtos
->current_thread
= 0;
337 /* update thread offsets */
338 retval
= uCOS_III_update_thread_offsets(rtos
);
339 if (retval
!= ERROR_OK
) {
340 LOG_ERROR("uCOS-III: failed to update thread offsets");
344 /* read current thread address */
345 symbol_address_t current_thread_address
= 0;
347 retval
= target_read_memory(rtos
->target
,
348 rtos
->symbols
[uCOS_III_VAL_OSTCBCurPtr
].address
,
349 params
->pointer_width
,
351 (void *)¤t_thread_address
);
352 if (retval
!= ERROR_OK
) {
353 LOG_ERROR("uCOS-III: failed to read current thread address");
357 /* read number of tasks */
358 retval
= target_read_u16(rtos
->target
,
359 rtos
->symbols
[uCOS_III_VAL_OSTaskQty
].address
,
360 (void *)&rtos
->thread_count
);
361 if (retval
!= ERROR_OK
) {
362 LOG_ERROR("uCOS-III: failed to read thread count");
366 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
367 if (rtos
->thread_details
== NULL
) {
368 LOG_ERROR("uCOS-III: out of memory");
373 * uC/OS-III adds tasks in LIFO order; advance to the end of the
374 * list and work backwards to preserve the intended order.
376 symbol_address_t thread_address
= 0;
378 retval
= uCOS_III_find_last_thread_address(rtos
, &thread_address
);
379 if (retval
!= ERROR_OK
) {
380 LOG_ERROR("uCOS-III: failed to find last thread address");
384 for (int i
= 0; i
< rtos
->thread_count
; i
++) {
385 struct thread_detail
*thread_detail
= &rtos
->thread_details
[i
];
386 char thread_str_buffer
[UCOS_III_MAX_STRLEN
+ 1];
388 /* find or create new threadid */
389 retval
= uCOS_III_find_or_create_thread(rtos
, thread_address
, &thread_detail
->threadid
);
390 if (retval
!= ERROR_OK
) {
391 LOG_ERROR("uCOS-III: failed to find or create thread");
395 if (thread_address
== current_thread_address
)
396 rtos
->current_thread
= thread_detail
->threadid
;
398 thread_detail
->exists
= true;
400 /* read thread name */
401 symbol_address_t thread_name_address
= 0;
403 retval
= target_read_memory(rtos
->target
,
404 thread_address
+ params
->thread_name_offset
,
405 params
->pointer_width
,
407 (void *)&thread_name_address
);
408 if (retval
!= ERROR_OK
) {
409 LOG_ERROR("uCOS-III: failed to name address");
413 retval
= target_read_buffer(rtos
->target
,
415 sizeof(thread_str_buffer
),
416 (void *)thread_str_buffer
);
417 if (retval
!= ERROR_OK
) {
418 LOG_ERROR("uCOS-III: failed to read thread name");
422 thread_str_buffer
[sizeof(thread_str_buffer
) - 1] = '\0';
423 thread_detail
->thread_name_str
= strdup(thread_str_buffer
);
425 /* read thread extra info */
426 uint8_t thread_state
;
427 uint8_t thread_priority
;
429 retval
= target_read_u8(rtos
->target
,
430 thread_address
+ params
->thread_state_offset
,
432 if (retval
!= ERROR_OK
) {
433 LOG_ERROR("uCOS-III: failed to read thread state");
437 retval
= target_read_u8(rtos
->target
,
438 thread_address
+ params
->thread_priority_offset
,
440 if (retval
!= ERROR_OK
) {
441 LOG_ERROR("uCOS-III: failed to read thread priority");
445 const char *thread_state_str
;
447 if (thread_state
< ARRAY_SIZE(uCOS_III_thread_state_list
))
448 thread_state_str
= uCOS_III_thread_state_list
[thread_state
];
450 thread_state_str
= "Unknown";
452 snprintf(thread_str_buffer
, sizeof(thread_str_buffer
), "State: %s, Priority: %d",
453 thread_state_str
, thread_priority
);
454 thread_detail
->extra_info_str
= strdup(thread_str_buffer
);
456 /* read previous thread address */
457 retval
= target_read_memory(rtos
->target
,
458 thread_address
+ params
->thread_prev_offset
,
459 params
->pointer_width
,
461 (void *)&thread_address
);
462 if (retval
!= ERROR_OK
) {
463 LOG_ERROR("uCOS-III: failed to read previous thread address");
471 static int uCOS_III_get_thread_reg_list(struct rtos
*rtos
, threadid_t threadid
,
472 struct rtos_reg
**reg_list
, int *num_regs
)
474 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
477 /* find thread address for threadid */
478 symbol_address_t thread_address
= 0;
480 retval
= uCOS_III_find_thread_address(rtos
, threadid
, &thread_address
);
481 if (retval
!= ERROR_OK
) {
482 LOG_ERROR("uCOS-III: failed to find thread address");
486 /* read thread stack address */
487 symbol_address_t stack_address
= 0;
489 retval
= target_read_memory(rtos
->target
,
490 thread_address
+ params
->thread_stack_offset
,
491 params
->pointer_width
,
493 (void *)&stack_address
);
494 if (retval
!= ERROR_OK
) {
495 LOG_ERROR("uCOS-III: failed to read stack address");
499 return rtos_generic_stack_read(rtos
->target
,
500 params
->stacking_info
,
506 static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
508 *symbol_list
= calloc(ARRAY_SIZE(uCOS_III_symbol_list
), sizeof(symbol_table_elem_t
));
509 if (*symbol_list
== NULL
) {
510 LOG_ERROR("uCOS-III: out of memory");
514 for (size_t i
= 0; i
< ARRAY_SIZE(uCOS_III_symbol_list
); i
++)
515 (*symbol_list
)[i
].symbol_name
= uCOS_III_symbol_list
[i
];
520 const struct rtos_type uCOS_III_rtos
= {
522 .detect_rtos
= uCOS_III_detect_rtos
,
523 .create
= uCOS_III_create
,
524 .update_threads
= uCOS_III_update_threads
,
525 .get_thread_reg_list
= uCOS_III_get_thread_reg_list
,
526 .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)