1 /***************************************************************************
2 * Copyright (C) 2014 by Marian Cingel *
3 * cingel.marian@gmail.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, write to the *
17 * Free Software Foundation, Inc. *
18 ***************************************************************************/
25 #include <helper/time_support.h>
26 #include <jtag/jtag.h>
27 #include "target/target.h"
28 #include "target/target_type.h"
30 #include "helper/log.h"
31 #include "helper/types.h"
32 #include "rtos_mqx_stackings.h"
35 #define MQX_THREAD_NAME_LENGTH (255)
36 #define MQX_KERNEL_OFFSET_TDLIST (0x0108)
37 #define MQX_KERNEL_OFFSET_SYSTEM_TASK (0x0050)
38 #define MQX_KERNEL_OFFSET_ACTIVE_TASK (0x001C)
39 #define MQX_KERNEL_OFFSET_CAPABILITY (0x0000)
40 #define MQX_QUEUE_OFFSET_SIZE (0x0008)
41 #define MQX_TASK_OFFSET_STATE (0x0008)
42 #define MQX_TASK_OFFSET_ID (0x000c)
43 #define MQX_TASK_OFFSET_TEMPLATE (0x0068)
44 #define MQX_TASK_OFFSET_STACK (0x0014)
45 #define MQX_TASK_OFFSET_TDLIST (0x006C)
46 #define MQX_TASK_OFFSET_NEXT (0x0000)
47 #define MQX_TASK_TEMPLATE_OFFSET_NAME (0x0010)
48 #define MQX_TASK_OFFSET_ERROR_CODE (0x005C)
49 #define MQX_TASK_STATE_MASK (0xFFF)
53 mqx_VAL_mqx_kernel_data
,
54 mqx_VAL_MQX_init_struct
,
62 const char *target_name
;
63 const enum mqx_arch target_arch
;
64 const struct rtos_register_stacking
*stacking_info
;
73 static const struct mqx_state mqx_states
[] = {
75 { 0x0003, "BLOCKED" },
76 { 0x0005, "RCV_SPECIFIC_BLOCKED" },
77 { 0x0007, "RCV_ANY_BLOCKED" },
79 { 0x000B, "UNHANDLED_INT_BLOCKED" },
80 { 0x000D, "SEND_BLOCKED" },
81 { 0x000F, "BREAKPOINT_BLOCKED" },
82 { 0x0211, "IO_BLOCKED" },
83 { 0x0021, "SEM_BLOCKED" },
84 { 0x0223, "MUTEX_BLOCKED" },
85 { 0x0025, "EVENT_BLOCKED" },
86 { 0x0229, "TASK_QUEUE_BLOCKED" },
87 { 0x042B, "LWSEM_BLOCKED" },
88 { 0x042D, "LWEVENT_BLOCKED" },
91 static const char * const mqx_symbol_list
[] = {
97 static const struct mqx_params mqx_params_list
[] = {
98 { "cortex_m", mqx_arch_cortexm
, &rtos_mqx_arm_v7m_stacking
},
102 * Perform simple address check to avoid bus fault.
104 static int mqx_valid_address_check(
109 enum mqx_arch arch_type
= ((struct mqx_params
*)rtos
->rtos_specific_params
)->target_arch
;
110 const char * targetname
= ((struct mqx_params
*)rtos
->rtos_specific_params
)->target_name
;
112 /* Cortex M address range */
113 if (arch_type
== mqx_arch_cortexm
) {
115 /* code and sram area */
116 (address
&& address
<= 0x3FFFFFFFu
) ||
117 /* external ram area*/
118 (address
>= 0x6000000u
&& address
<= 0x9FFFFFFFu
)
124 LOG_ERROR("MQX RTOS - unknown architecture %s", targetname
);
129 * Wrapper of 'target_read_buffer' fn.
130 * Include address check.
132 static int mqx_target_read_buffer(
133 struct target
*target
,
139 int status
= mqx_valid_address_check(target
->rtos
, address
);
140 if (status
!= ERROR_OK
) {
141 LOG_WARNING("MQX RTOS - target address 0x%" PRIx32
" is not allowed to read", address
);
144 status
= target_read_buffer(target
, address
, size
, buffer
);
145 if (status
!= ERROR_OK
) {
146 LOG_ERROR("MQX RTOS - reading target address 0x%" PRIx32
" failed", address
);
153 * Get symbol address if present
155 static int mqx_get_symbol(
157 enum mqx_symbols symbol
,
161 /* TODO: additional check ?? */
162 (*(int *)result
) = (uint32_t)rtos
->symbols
[symbol
].address
;
167 * Get value of struct member by passing
168 * member offset, width and name (debug purpose)
170 static int mqx_get_member(
172 const uint32_t base_address
,
173 int32_t member_offset
,
174 int32_t member_width
,
175 const char *member_name
,
179 int status
= ERROR_FAIL
;
180 status
= mqx_target_read_buffer(
181 rtos
->target
, base_address
+ member_offset
, member_width
, result
183 if (status
!= ERROR_OK
)
184 LOG_WARNING("MQX RTOS - cannot read \"%s\" at address 0x%" PRIx32
,
185 member_name
, (uint32_t)(base_address
+ member_offset
));
190 * Check whether scheduler started
192 static int mqx_is_scheduler_running(
196 uint32_t kernel_data_symbol
= 0;
197 uint32_t kernel_data_addr
= 0;
198 uint32_t system_td_addr
= 0;
199 uint32_t active_td_addr
= 0;
200 uint32_t capability_value
= 0;
202 /* get '_mqx_kernel_data' symbol */
203 if (ERROR_OK
!= mqx_get_symbol(
204 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_symbol
208 /* get '_mqx_kernel_data' */
209 if (ERROR_OK
!= mqx_get_member(
210 rtos
, kernel_data_symbol
, 0, 4,
211 "_mqx_kernel_data", &kernel_data_addr
215 /* return if '_mqx_kernel_data' is NULL or default 0xFFFFFFFF */
216 if (0 == kernel_data_addr
|| (uint32_t)(-1) == kernel_data_addr
)
218 /* get kernel_data->ADDRESSING_CAPABILITY */
219 if (ERROR_OK
!= mqx_get_member(
220 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_CAPABILITY
, 4,
221 "kernel_data->ADDRESSING_CAPABILITY", (void *)&capability_value
225 /* check first member, the '_mqx_kernel_data->ADDRESSING_CAPABILITY'.
226 it supose to be set to value 8 */
227 if (capability_value
!= 8) {
228 LOG_WARNING("MQX RTOS - value of '_mqx_kernel_data->ADDRESSING_CAPABILITY' contains invalid value");
232 if (ERROR_OK
!= mqx_get_member(
233 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
234 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
238 /* active task is system task, scheduler has not not run yet */
239 system_td_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_SYSTEM_TASK
;
240 if (active_td_addr
== system_td_addr
) {
241 LOG_WARNING("MQX RTOS - scheduler does not run");
248 * API function, return 1 if MQX is present
250 static int mqx_detect_rtos(
251 struct target
*target
255 (target
->rtos
->symbols
!= NULL
) &&
256 (target
->rtos
->symbols
[mqx_VAL_mqx_kernel_data
].address
!= 0)
264 * API function, pass MQX extra info to context data
266 static int mqx_create(
267 struct target
*target
270 /* check target name against supported architectures */
271 int mqx_params_list_num
= (sizeof(mqx_params_list
)/sizeof(struct mqx_params
));
272 for (int i
= 0; i
< mqx_params_list_num
; i
++) {
273 if (0 == strcmp(mqx_params_list
[i
].target_name
, target
->type
->name
)) {
274 target
->rtos
->rtos_specific_params
= (void *)&mqx_params_list
[i
];
275 /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */
279 LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target
->type
->name
);
284 * API function, update list of threads
286 static int mqx_update_threads(
290 uint32_t task_queue_addr
= 0;
291 uint32_t kernel_data_addr
= 0;
292 uint16_t task_queue_size
= 0;
293 uint32_t active_td_addr
= 0;
296 rtos_free_threadlist(rtos
);
297 /* check scheduler */
298 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
300 /* get kernel_data symbol */
301 if (ERROR_OK
!= mqx_get_symbol(
302 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
306 /* read kernel_data */
307 if (ERROR_OK
!= mqx_get_member(
308 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
312 /* get task queue address */
313 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
314 /* get task queue size */
315 if (ERROR_OK
!= mqx_get_member(
316 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
317 "kernel_data->TD_LIST.SIZE", &task_queue_size
322 if (ERROR_OK
!= mqx_get_member(
323 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
324 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
329 /* setup threads info */
330 rtos
->thread_count
= task_queue_size
;
331 rtos
->current_thread
= 0;
332 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
333 if (NULL
== rtos
->thread_details
)
336 /* loop over each task and setup thread details,
337 the current_taskpool_addr is set to queue head
338 NOTE: debugging functions task create/destroy
339 might cause to show invalid data.
342 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
343 i
< (uint32_t)rtos
->thread_count
;
346 uint8_t task_name
[MQX_THREAD_NAME_LENGTH
+ 1];
347 uint32_t task_addr
= 0, task_template
= 0, task_state
= 0;
348 uint32_t task_name_addr
= 0, task_id
= 0, task_errno
= 0;
349 uint32_t state_index
= 0, state_max
= 0;
350 uint32_t extra_info_length
= 0;
351 char *state_name
= "unknown state";
353 /* set current taskpool address */
354 if (ERROR_OK
!= mqx_get_member(
355 rtos
, taskpool_addr
, MQX_TASK_OFFSET_NEXT
, 4,
356 "td_struct_ptr->NEXT", &taskpool_addr
360 /* get task address from taskpool */
361 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
362 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
363 if (ERROR_OK
!= mqx_get_member(
364 rtos
, task_addr
, MQX_TASK_OFFSET_TEMPLATE
, 4,
365 "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
369 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
370 if (ERROR_OK
!= mqx_get_member(
371 rtos
, task_template
, MQX_TASK_TEMPLATE_OFFSET_NAME
, 4,
372 "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
376 /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
377 if (ERROR_OK
!= mqx_get_member(
378 rtos
, task_name_addr
, 0, MQX_THREAD_NAME_LENGTH
,
379 "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
383 /* always terminate last character by force,
384 otherwise openocd might fail if task_name
385 has corrupted data */
386 task_name
[MQX_THREAD_NAME_LENGTH
] = '\0';
387 /* get value of 'td_struct_ptr->TASK_ID' */
388 if (ERROR_OK
!= mqx_get_member(
389 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
390 "td_struct_ptr->TASK_ID", &task_id
395 if (ERROR_OK
!= mqx_get_member(
396 rtos
, task_addr
, MQX_TASK_OFFSET_ERROR_CODE
, 4,
397 "td_struct_ptr->TASK_ERROR_CODE", &task_errno
401 /* get value of 'td_struct_ptr->STATE' */
402 if (ERROR_OK
!= mqx_get_member(
403 rtos
, task_addr
, MQX_TASK_OFFSET_STATE
, 4,
404 "td_struct_ptr->STATE", &task_state
408 task_state
&= MQX_TASK_STATE_MASK
;
409 /* and search for defined state */
410 state_max
= (sizeof(mqx_states
)/sizeof(struct mqx_state
));
411 for (state_index
= 0; (state_index
< state_max
); state_index
++) {
412 if (mqx_states
[state_index
].state
== task_state
) {
413 state_name
= mqx_states
[state_index
].name
;
418 /* setup thread details struct */
419 rtos
->thread_details
[i
].threadid
= task_id
;
420 rtos
->thread_details
[i
].exists
= true;
421 rtos
->thread_details
[i
].display_str
= NULL
;
422 /* set thread name */
423 rtos
->thread_details
[i
].thread_name_str
= malloc(strlen((void *)task_name
) + 1);
424 if (NULL
== rtos
->thread_details
[i
].thread_name_str
)
426 strcpy(rtos
->thread_details
[i
].thread_name_str
, (void *)task_name
);
427 /* set thread extra info
431 * calculate length as:
432 * state length + address length + errno length + formatter length
434 extra_info_length
+= strlen((void *)state_name
) + 8 + 8 + 8;
435 rtos
->thread_details
[i
].extra_info_str
= malloc(extra_info_length
+ 1);
436 if (NULL
== rtos
->thread_details
[i
].extra_info_str
)
439 rtos
->thread_details
[i
].extra_info_str
, extra_info_length
, "%s : 0x%"PRIx32
" : %" PRIu32
,
440 state_name
, task_addr
, task_errno
442 /* set active thread */
443 if (active_td_addr
== task_addr
)
444 rtos
->current_thread
= task_id
;
450 * API function, get info of selected thread
452 static int mqx_get_thread_reg_list(
458 int64_t stack_ptr
= 0;
459 uint32_t my_task_addr
= 0;
460 uint32_t task_queue_addr
= 0;
461 uint32_t task_queue_size
= 0;
462 uint32_t kernel_data_addr
= 0;
464 *hex_reg_list
= NULL
;
465 if (thread_id
== 0) {
466 LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id
);
469 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
471 /* get kernel_data symbol */
472 if (ERROR_OK
!= mqx_get_symbol(
473 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
477 /* read kernel_data */
478 if (ERROR_OK
!= mqx_get_member(
479 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
483 /* get task queue address */
484 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
485 /* get task queue size */
486 if (ERROR_OK
!= mqx_get_member(
487 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
488 "kernel_data->TD_LIST.SIZE", &task_queue_size
492 /* search for taskid */
494 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
495 i
< (uint32_t)rtos
->thread_count
;
498 uint32_t tmp_address
= 0, task_addr
= 0;
499 uint32_t task_id
= 0;
500 /* set current taskpool address */
501 tmp_address
= taskpool_addr
;
502 if (ERROR_OK
!= mqx_get_member(
503 rtos
, tmp_address
, MQX_TASK_OFFSET_NEXT
, 4,
504 "td_struct_ptr->NEXT", &taskpool_addr
508 /* get task address from taskpool */
509 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
510 /* get value of td_struct->TASK_ID */
511 if (ERROR_OK
!= mqx_get_member(
512 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
513 "td_struct_ptr->TASK_ID", &task_id
517 /* found taskid, break */
518 if (task_id
== thread_id
) {
519 my_task_addr
= task_addr
;
524 LOG_ERROR("MQX_RTOS - threadid %" PRId64
" does not match any task", thread_id
);
527 /* get task stack head address */
528 if (ERROR_OK
!= mqx_get_member(
529 rtos
, my_task_addr
, MQX_TASK_OFFSET_STACK
, 4, "task->STACK_PTR", &stack_ptr
533 return rtos_generic_stack_read(
534 rtos
->target
, ((struct mqx_params
*)rtos
->rtos_specific_params
)->stacking_info
, stack_ptr
, hex_reg_list
538 /* API function, export list of required symbols */
539 static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
541 *symbol_list
= malloc(sizeof(symbol_table_elem_t
) * ARRAY_SIZE(mqx_symbol_list
));
542 if (NULL
== *symbol_list
)
544 /* export required symbols */
545 for (int i
= 0; i
< (int)(ARRAY_SIZE(mqx_symbol_list
)); i
++)
546 (*symbol_list
)[i
].symbol_name
= mqx_symbol_list
[i
];
550 struct rtos_type mqx_rtos
= {
552 .detect_rtos
= mqx_detect_rtos
,
553 .create
= mqx_create
,
554 .update_threads
= mqx_update_threads
,
555 .get_thread_reg_list
= mqx_get_thread_reg_list
,
556 .get_symbol_list_to_lookup
= mqx_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)