1 /***************************************************************************
2 * Copyright (C) 2016 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/time_support.h>
24 #include <jtag/jtag.h>
25 #include "target/target.h"
26 #include "target/target_type.h"
28 #include "helper/log.h"
29 #include "helper/types.h"
30 #include "rtos/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 */
73 static const char * const uCOS_III_symbol_list
[] = {
79 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
80 "openocd_OS_TCB_StkPtr_offset",
81 "openocd_OS_TCB_NamePtr_offset",
82 "openocd_OS_TCB_TaskState_offset",
83 "openocd_OS_TCB_Prio_offset",
84 "openocd_OS_TCB_DbgPrevPtr_offset",
85 "openocd_OS_TCB_DbgNextPtr_offset",
89 enum uCOS_III_symbol_values
{
90 uCOS_III_VAL_OSRunning
,
91 uCOS_III_VAL_OSTCBCurPtr
,
92 uCOS_III_VAL_OSTaskDbgListPtr
,
93 uCOS_III_VAL_OSTaskQty
,
95 /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
96 uCOS_III_VAL_OS_TCB_StkPtr_offset
,
97 uCOS_III_VAL_OS_TCB_NamePtr_offset
,
98 uCOS_III_VAL_OS_TCB_TaskState_offset
,
99 uCOS_III_VAL_OS_TCB_Prio_offset
,
100 uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset
,
101 uCOS_III_VAL_OS_TCB_DbgNextPtr_offset
,
104 static const char * const uCOS_III_thread_state_list
[] = {
112 "Pend Timeout Suspended",
115 static int uCOS_III_find_or_create_thread(struct rtos
*rtos
, symbol_address_t thread_address
,
116 threadid_t
*threadid
)
118 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
121 for (thread_index
= 0; thread_index
< params
->num_threads
; thread_index
++)
122 if (params
->threads
[thread_index
] == thread_address
)
125 if (params
->num_threads
== UCOS_III_MAX_THREADS
) {
126 LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS");
130 params
->threads
[thread_index
] = thread_address
;
131 params
->num_threads
++;
133 *threadid
= thread_index
+ params
->threadid_start
;
137 static int uCOS_III_find_thread_address(struct rtos
*rtos
, threadid_t threadid
,
138 symbol_address_t
*thread_address
)
140 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
143 thread_index
= threadid
- params
->threadid_start
;
144 if (thread_index
>= params
->num_threads
) {
145 LOG_ERROR("uCOS-III: failed to find thread address");
149 *thread_address
= params
->threads
[thread_index
];
153 static int uCOS_III_find_last_thread_address(struct rtos
*rtos
, symbol_address_t
*thread_address
)
155 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
158 /* read the thread list head */
159 symbol_address_t thread_list_address
= 0;
161 retval
= target_read_memory(rtos
->target
,
162 rtos
->symbols
[uCOS_III_VAL_OSTaskDbgListPtr
].address
,
163 params
->pointer_width
,
165 (void *)&thread_list_address
);
166 if (retval
!= ERROR_OK
) {
167 LOG_ERROR("uCOS-III: failed to read thread list address");
171 /* advance to end of thread list */
173 *thread_address
= thread_list_address
;
175 retval
= target_read_memory(rtos
->target
,
176 thread_list_address
+ params
->thread_next_offset
,
177 params
->pointer_width
,
179 (void *)&thread_list_address
);
180 if (retval
!= ERROR_OK
) {
181 LOG_ERROR("uCOS-III: failed to read next thread address");
184 } while (thread_list_address
!= 0);
189 static int uCOS_III_update_thread_offsets(struct rtos
*rtos
)
191 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
193 if (params
->thread_offsets_updated
)
196 const struct thread_offset_map
{
197 enum uCOS_III_symbol_values symbol_value
;
198 symbol_address_t
*thread_offset
;
199 } thread_offset_maps
[] = {
201 uCOS_III_VAL_OS_TCB_StkPtr_offset
,
202 ¶ms
->thread_stack_offset
,
205 uCOS_III_VAL_OS_TCB_NamePtr_offset
,
206 ¶ms
->thread_name_offset
,
209 uCOS_III_VAL_OS_TCB_TaskState_offset
,
210 ¶ms
->thread_state_offset
,
213 uCOS_III_VAL_OS_TCB_Prio_offset
,
214 ¶ms
->thread_priority_offset
,
217 uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset
,
218 ¶ms
->thread_prev_offset
,
221 uCOS_III_VAL_OS_TCB_DbgNextPtr_offset
,
222 ¶ms
->thread_next_offset
,
226 for (size_t i
= 0; i
< ARRAY_SIZE(thread_offset_maps
); i
++) {
227 const struct thread_offset_map
*thread_offset_map
= &thread_offset_maps
[i
];
229 int retval
= target_read_memory(rtos
->target
,
230 rtos
->symbols
[thread_offset_map
->symbol_value
].address
,
231 params
->pointer_width
,
233 (void *)thread_offset_map
->thread_offset
);
234 if (retval
!= ERROR_OK
) {
235 LOG_ERROR("uCOS-III: failed to read thread offset");
240 params
->thread_offsets_updated
= true;
244 static int uCOS_III_detect_rtos(struct target
*target
)
246 return target
->rtos
->symbols
!= NULL
&&
247 target
->rtos
->symbols
[uCOS_III_VAL_OSRunning
].address
!= 0;
250 static int uCOS_III_reset_handler(struct target
*target
, enum target_reset_mode reset_mode
, void *priv
)
252 struct uCOS_III_params
*params
= target
->rtos
->rtos_specific_params
;
254 params
->thread_offsets_updated
= false;
255 params
->num_threads
= 0;
260 static int uCOS_III_create(struct target
*target
)
262 struct uCOS_III_params
*params
;
264 for (size_t i
= 0; i
< ARRAY_SIZE(uCOS_III_params_list
); i
++)
265 if (strcmp(uCOS_III_params_list
[i
].target_name
, target
->type
->name
) == 0) {
266 params
= malloc(sizeof(*params
) +
267 UCOS_III_MAX_THREADS
* sizeof(*params
->threads
));
268 if (params
== NULL
) {
269 LOG_ERROR("uCOS-III: out of memory");
273 memcpy(params
, &uCOS_III_params_list
[i
], sizeof(uCOS_III_params_list
[i
]));
274 target
->rtos
->rtos_specific_params
= (void *)params
;
276 target_register_reset_callback(uCOS_III_reset_handler
, NULL
);
281 LOG_ERROR("uCOS-III: target not supported: %s", target
->type
->name
);
285 static int uCOS_III_update_threads(struct rtos
*rtos
)
287 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
290 /* free previous thread details */
291 rtos_free_threadlist(rtos
);
293 /* verify RTOS is running */
294 uint8_t rtos_running
;
296 retval
= target_read_u8(rtos
->target
,
297 rtos
->symbols
[uCOS_III_VAL_OSRunning
].address
,
299 if (retval
!= ERROR_OK
) {
300 LOG_ERROR("uCOS-III: failed to read RTOS running");
305 rtos
->thread_details
= calloc(1, sizeof(struct thread_detail
));
306 if (rtos
->thread_details
== NULL
) {
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_OSTCBCurPtr
].address
,
331 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_OSTaskQty
].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
== NULL
) {
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
,
373 &thread_detail
->threadid
);
374 if (retval
!= ERROR_OK
) {
375 LOG_ERROR("uCOS-III: failed to find or create thread");
379 if (thread_address
== current_thread_address
)
380 rtos
->current_thread
= thread_detail
->threadid
;
382 thread_detail
->exists
= true;
384 /* read thread name */
385 symbol_address_t thread_name_address
= 0;
387 retval
= target_read_memory(rtos
->target
,
388 thread_address
+ params
->thread_name_offset
,
389 params
->pointer_width
,
391 (void *)&thread_name_address
);
392 if (retval
!= ERROR_OK
) {
393 LOG_ERROR("uCOS-III: failed to name address");
397 retval
= target_read_buffer(rtos
->target
,
399 sizeof(thread_str_buffer
),
400 (void *)thread_str_buffer
);
401 if (retval
!= ERROR_OK
) {
402 LOG_ERROR("uCOS-III: failed to read thread name");
406 thread_str_buffer
[sizeof(thread_str_buffer
) - 1] = '\0';
407 thread_detail
->thread_name_str
= strdup(thread_str_buffer
);
409 /* read thread extra info */
410 uint8_t thread_state
;
411 uint8_t thread_priority
;
413 retval
= target_read_u8(rtos
->target
,
414 thread_address
+ params
->thread_state_offset
,
416 if (retval
!= ERROR_OK
) {
417 LOG_ERROR("uCOS-III: failed to read thread state");
421 retval
= target_read_u8(rtos
->target
,
422 thread_address
+ params
->thread_priority_offset
,
424 if (retval
!= ERROR_OK
) {
425 LOG_ERROR("uCOS-III: failed to read thread priority");
429 const char *thread_state_str
;
431 if (thread_state
< ARRAY_SIZE(uCOS_III_thread_state_list
))
432 thread_state_str
= uCOS_III_thread_state_list
[thread_state
];
434 thread_state_str
= "Unknown";
436 snprintf(thread_str_buffer
, sizeof(thread_str_buffer
), "State: %s, Priority: %d",
437 thread_state_str
, thread_priority
);
438 thread_detail
->extra_info_str
= strdup(thread_str_buffer
);
440 /* read previous thread address */
441 retval
= target_read_memory(rtos
->target
,
442 thread_address
+ params
->thread_prev_offset
,
443 params
->pointer_width
,
445 (void *)&thread_address
);
446 if (retval
!= ERROR_OK
) {
447 LOG_ERROR("uCOS-III: failed to read previous thread address");
455 static int uCOS_III_get_thread_reg_list(struct rtos
*rtos
, threadid_t threadid
, char **hex_reg_list
)
457 struct uCOS_III_params
*params
= rtos
->rtos_specific_params
;
460 /* find thread address for threadid */
461 symbol_address_t thread_address
= 0;
463 retval
= uCOS_III_find_thread_address(rtos
, threadid
, &thread_address
);
464 if (retval
!= ERROR_OK
) {
465 LOG_ERROR("uCOS-III: failed to find thread address");
469 /* read thread stack address */
470 symbol_address_t stack_address
= 0;
472 retval
= target_read_memory(rtos
->target
,
473 thread_address
+ params
->thread_stack_offset
,
474 params
->pointer_width
,
476 (void *)&stack_address
);
477 if (retval
!= ERROR_OK
) {
478 LOG_ERROR("uCOS-III: failed to read stack address");
482 return rtos_generic_stack_read(rtos
->target
,
483 params
->stacking_info
,
488 static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
490 *symbol_list
= calloc(ARRAY_SIZE(uCOS_III_symbol_list
), sizeof(symbol_table_elem_t
));
491 if (*symbol_list
== NULL
) {
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)