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;
295 if (!rtos
->rtos_specific_params
)
302 rtos_free_threadlist(rtos
);
303 /* check scheduler */
304 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
306 /* get kernel_data symbol */
307 if (ERROR_OK
!= mqx_get_symbol(
308 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
312 /* read kernel_data */
313 if (ERROR_OK
!= mqx_get_member(
314 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
318 /* get task queue address */
319 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
320 /* get task queue size */
321 if (ERROR_OK
!= mqx_get_member(
322 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
323 "kernel_data->TD_LIST.SIZE", &task_queue_size
328 if (ERROR_OK
!= mqx_get_member(
329 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
330 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
335 /* setup threads info */
336 rtos
->thread_count
= task_queue_size
;
337 rtos
->current_thread
= 0;
338 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
339 if (NULL
== rtos
->thread_details
)
342 /* loop over each task and setup thread details,
343 the current_taskpool_addr is set to queue head
344 NOTE: debugging functions task create/destroy
345 might cause to show invalid data.
348 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
349 i
< (uint32_t)rtos
->thread_count
;
352 uint8_t task_name
[MQX_THREAD_NAME_LENGTH
+ 1];
353 uint32_t task_addr
= 0, task_template
= 0, task_state
= 0;
354 uint32_t task_name_addr
= 0, task_id
= 0, task_errno
= 0;
355 uint32_t state_index
= 0, state_max
= 0;
356 uint32_t extra_info_length
= 0;
357 char *state_name
= "unknown state";
359 /* set current taskpool address */
360 if (ERROR_OK
!= mqx_get_member(
361 rtos
, taskpool_addr
, MQX_TASK_OFFSET_NEXT
, 4,
362 "td_struct_ptr->NEXT", &taskpool_addr
366 /* get task address from taskpool */
367 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
368 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
369 if (ERROR_OK
!= mqx_get_member(
370 rtos
, task_addr
, MQX_TASK_OFFSET_TEMPLATE
, 4,
371 "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
375 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
376 if (ERROR_OK
!= mqx_get_member(
377 rtos
, task_template
, MQX_TASK_TEMPLATE_OFFSET_NAME
, 4,
378 "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
382 /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
383 if (ERROR_OK
!= mqx_get_member(
384 rtos
, task_name_addr
, 0, MQX_THREAD_NAME_LENGTH
,
385 "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
389 /* always terminate last character by force,
390 otherwise openocd might fail if task_name
391 has corrupted data */
392 task_name
[MQX_THREAD_NAME_LENGTH
] = '\0';
393 /* get value of 'td_struct_ptr->TASK_ID' */
394 if (ERROR_OK
!= mqx_get_member(
395 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
396 "td_struct_ptr->TASK_ID", &task_id
401 if (ERROR_OK
!= mqx_get_member(
402 rtos
, task_addr
, MQX_TASK_OFFSET_ERROR_CODE
, 4,
403 "td_struct_ptr->TASK_ERROR_CODE", &task_errno
407 /* get value of 'td_struct_ptr->STATE' */
408 if (ERROR_OK
!= mqx_get_member(
409 rtos
, task_addr
, MQX_TASK_OFFSET_STATE
, 4,
410 "td_struct_ptr->STATE", &task_state
414 task_state
&= MQX_TASK_STATE_MASK
;
415 /* and search for defined state */
416 state_max
= (sizeof(mqx_states
)/sizeof(struct mqx_state
));
417 for (state_index
= 0; (state_index
< state_max
); state_index
++) {
418 if (mqx_states
[state_index
].state
== task_state
) {
419 state_name
= mqx_states
[state_index
].name
;
424 /* setup thread details struct */
425 rtos
->thread_details
[i
].threadid
= task_id
;
426 rtos
->thread_details
[i
].exists
= true;
427 rtos
->thread_details
[i
].display_str
= NULL
;
428 /* set thread name */
429 rtos
->thread_details
[i
].thread_name_str
= malloc(strlen((void *)task_name
) + 1);
430 if (NULL
== rtos
->thread_details
[i
].thread_name_str
)
432 strcpy(rtos
->thread_details
[i
].thread_name_str
, (void *)task_name
);
433 /* set thread extra info
437 * calculate length as:
438 * state length + address length + errno length + formatter length
440 extra_info_length
+= strlen((void *)state_name
) + 8 + 8 + 8;
441 rtos
->thread_details
[i
].extra_info_str
= malloc(extra_info_length
+ 1);
442 if (NULL
== rtos
->thread_details
[i
].extra_info_str
)
445 rtos
->thread_details
[i
].extra_info_str
, extra_info_length
, "%s : 0x%"PRIx32
" : %" PRIu32
,
446 state_name
, task_addr
, task_errno
448 /* set active thread */
449 if (active_td_addr
== task_addr
)
450 rtos
->current_thread
= task_id
;
456 * API function, get info of selected thread
458 static int mqx_get_thread_reg_list(
464 int64_t stack_ptr
= 0;
465 uint32_t my_task_addr
= 0;
466 uint32_t task_queue_addr
= 0;
467 uint32_t task_queue_size
= 0;
468 uint32_t kernel_data_addr
= 0;
470 *hex_reg_list
= NULL
;
471 if (thread_id
== 0) {
472 LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id
);
475 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
477 /* get kernel_data symbol */
478 if (ERROR_OK
!= mqx_get_symbol(
479 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
483 /* read kernel_data */
484 if (ERROR_OK
!= mqx_get_member(
485 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
489 /* get task queue address */
490 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
491 /* get task queue size */
492 if (ERROR_OK
!= mqx_get_member(
493 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
494 "kernel_data->TD_LIST.SIZE", &task_queue_size
498 /* search for taskid */
500 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
501 i
< (uint32_t)rtos
->thread_count
;
504 uint32_t tmp_address
= 0, task_addr
= 0;
505 uint32_t task_id
= 0;
506 /* set current taskpool address */
507 tmp_address
= taskpool_addr
;
508 if (ERROR_OK
!= mqx_get_member(
509 rtos
, tmp_address
, MQX_TASK_OFFSET_NEXT
, 4,
510 "td_struct_ptr->NEXT", &taskpool_addr
514 /* get task address from taskpool */
515 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
516 /* get value of td_struct->TASK_ID */
517 if (ERROR_OK
!= mqx_get_member(
518 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
519 "td_struct_ptr->TASK_ID", &task_id
523 /* found taskid, break */
524 if (task_id
== thread_id
) {
525 my_task_addr
= task_addr
;
530 LOG_ERROR("MQX_RTOS - threadid %" PRId64
" does not match any task", thread_id
);
533 /* get task stack head address */
534 if (ERROR_OK
!= mqx_get_member(
535 rtos
, my_task_addr
, MQX_TASK_OFFSET_STACK
, 4, "task->STACK_PTR", &stack_ptr
539 return rtos_generic_stack_read(
540 rtos
->target
, ((struct mqx_params
*)rtos
->rtos_specific_params
)->stacking_info
, stack_ptr
, hex_reg_list
544 /* API function, export list of required symbols */
545 static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
547 *symbol_list
= malloc(sizeof(symbol_table_elem_t
) * ARRAY_SIZE(mqx_symbol_list
));
548 if (NULL
== *symbol_list
)
550 /* export required symbols */
551 for (int i
= 0; i
< (int)(ARRAY_SIZE(mqx_symbol_list
)); i
++)
552 (*symbol_list
)[i
].symbol_name
= mqx_symbol_list
[i
];
556 struct rtos_type mqx_rtos
= {
558 .detect_rtos
= mqx_detect_rtos
,
559 .create
= mqx_create
,
560 .update_threads
= mqx_update_threads
,
561 .get_thread_reg_list
= mqx_get_thread_reg_list
,
562 .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)