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%X 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%X 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%X", member_name
, base_address
+ member_offset
);
189 * Check whether scheduler started
191 static int mqx_is_scheduler_running(
195 uint32_t kernel_data_symbol
= 0;
196 uint32_t kernel_data_addr
= 0;
197 uint32_t system_td_addr
= 0;
198 uint32_t active_td_addr
= 0;
199 uint32_t capability_value
= 0;
201 /* get '_mqx_kernel_data' symbol */
202 if (ERROR_OK
!= mqx_get_symbol(
203 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_symbol
207 /* get '_mqx_kernel_data' */
208 if (ERROR_OK
!= mqx_get_member(
209 rtos
, kernel_data_symbol
, 0, 4,
210 "_mqx_kernel_data", &kernel_data_addr
214 /* return if '_mqx_kernel_data' is NULL or default 0xFFFFFFFF */
215 if (0 == kernel_data_addr
|| (uint32_t)(-1) == kernel_data_addr
)
217 /* get kernel_data->ADDRESSING_CAPABILITY */
218 if (ERROR_OK
!= mqx_get_member(
219 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_CAPABILITY
, 4,
220 "kernel_data->ADDRESSING_CAPABILITY", (void *)&capability_value
224 /* check first member, the '_mqx_kernel_data->ADDRESSING_CAPABILITY'.
225 it supose to be set to value 8 */
226 if (capability_value
!= 8) {
227 LOG_WARNING("MQX RTOS - value of '_mqx_kernel_data->ADDRESSING_CAPABILITY' contains invalid value");
231 if (ERROR_OK
!= mqx_get_member(
232 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
233 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
237 /* active task is system task, scheduler has not not run yet */
238 system_td_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_SYSTEM_TASK
;
239 if (active_td_addr
== system_td_addr
) {
240 LOG_WARNING("MQX RTOS - scheduler does not run");
247 * API function, return 1 if MQX is present
249 static int mqx_detect_rtos(
250 struct target
*target
254 (target
->rtos
->symbols
!= NULL
) &&
255 (target
->rtos
->symbols
[mqx_VAL_mqx_kernel_data
].address
!= 0)
263 * API function, pass MQX extra info to context data
265 static int mqx_create(
266 struct target
*target
269 /* check target name against supported architectures */
270 int mqx_params_list_num
= (sizeof(mqx_params_list
)/sizeof(struct mqx_params
));
271 for (int i
= 0; i
< mqx_params_list_num
; i
++) {
272 if (0 == strcmp(mqx_params_list
[i
].target_name
, target
->type
->name
)) {
273 target
->rtos
->rtos_specific_params
= (void *)&mqx_params_list
[i
];
274 /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */
278 LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target
->type
->name
);
283 * API function, update list of threads
285 static int mqx_update_threads(
289 uint32_t task_queue_addr
= 0;
290 uint32_t kernel_data_addr
= 0;
291 uint16_t task_queue_size
= 0;
292 uint32_t active_td_addr
= 0;
295 rtos_free_threadlist(rtos
);
296 /* check scheduler */
297 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
299 /* get kernel_data symbol */
300 if (ERROR_OK
!= mqx_get_symbol(
301 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
305 /* read kernel_data */
306 if (ERROR_OK
!= mqx_get_member(
307 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
311 /* get task queue address */
312 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
313 /* get task queue size */
314 if (ERROR_OK
!= mqx_get_member(
315 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
316 "kernel_data->TD_LIST.SIZE", &task_queue_size
321 if (ERROR_OK
!= mqx_get_member(
322 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
323 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
328 /* setup threads info */
329 rtos
->thread_count
= task_queue_size
;
330 rtos
->current_thread
= 0;
331 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
332 if (NULL
== rtos
->thread_details
)
335 /* loop over each task and setup thread details,
336 the current_taskpool_addr is set to queue head
337 NOTE: debugging functions task create/destroy
338 might cause to show invalid data.
341 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
342 i
< (uint32_t)rtos
->thread_count
;
345 uint8_t task_name
[MQX_THREAD_NAME_LENGTH
+ 1];
346 uint32_t task_addr
= 0, task_template
= 0, task_state
= 0;
347 uint32_t task_name_addr
= 0, task_id
= 0, task_errno
= 0;
348 uint32_t state_index
= 0, state_max
= 0;
349 uint32_t extra_info_length
= 0;
350 char *state_name
= "unknown state";
352 /* set current taskpool address */
353 if (ERROR_OK
!= mqx_get_member(
354 rtos
, taskpool_addr
, MQX_TASK_OFFSET_NEXT
, 4,
355 "td_struct_ptr->NEXT", &taskpool_addr
359 /* get task address from taskpool */
360 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
361 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
362 if (ERROR_OK
!= mqx_get_member(
363 rtos
, task_addr
, MQX_TASK_OFFSET_TEMPLATE
, 4,
364 "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
368 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
369 if (ERROR_OK
!= mqx_get_member(
370 rtos
, task_template
, MQX_TASK_TEMPLATE_OFFSET_NAME
, 4,
371 "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
375 /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
376 if (ERROR_OK
!= mqx_get_member(
377 rtos
, task_name_addr
, 0, MQX_THREAD_NAME_LENGTH
,
378 "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
382 /* always terminate last character by force,
383 otherwise openocd might fail if task_name
384 has corrupted data */
385 task_name
[MQX_THREAD_NAME_LENGTH
] = '\0';
386 /* get value of 'td_struct_ptr->TASK_ID' */
387 if (ERROR_OK
!= mqx_get_member(
388 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
389 "td_struct_ptr->TASK_ID", &task_id
394 if (ERROR_OK
!= mqx_get_member(
395 rtos
, task_addr
, MQX_TASK_OFFSET_ERROR_CODE
, 4,
396 "td_struct_ptr->TASK_ERROR_CODE", &task_errno
400 /* get value of 'td_struct_ptr->STATE' */
401 if (ERROR_OK
!= mqx_get_member(
402 rtos
, task_addr
, MQX_TASK_OFFSET_STATE
, 4,
403 "td_struct_ptr->STATE", &task_state
407 task_state
&= MQX_TASK_STATE_MASK
;
408 /* and search for defined state */
409 state_max
= (sizeof(mqx_states
)/sizeof(struct mqx_state
));
410 for (state_index
= 0; (state_index
< state_max
); state_index
++) {
411 if (mqx_states
[state_index
].state
== task_state
) {
412 state_name
= mqx_states
[state_index
].name
;
417 /* setup thread details struct */
418 rtos
->thread_details
[i
].threadid
= task_id
;
419 rtos
->thread_details
[i
].exists
= true;
420 rtos
->thread_details
[i
].display_str
= NULL
;
421 /* set thread name */
422 rtos
->thread_details
[i
].thread_name_str
= malloc(strlen((void *)task_name
) + 1);
423 if (NULL
== rtos
->thread_details
[i
].thread_name_str
)
425 strcpy(rtos
->thread_details
[i
].thread_name_str
, (void *)task_name
);
426 /* set thread extra info
430 * calculate length as:
431 * state length + address length + errno length + formatter length
433 extra_info_length
+= strlen((void *)state_name
) + 8 + 8 + 8;
434 rtos
->thread_details
[i
].extra_info_str
= malloc(extra_info_length
+ 1);
435 if (NULL
== rtos
->thread_details
[i
].extra_info_str
)
438 rtos
->thread_details
[i
].extra_info_str
, extra_info_length
, "%s : 0x%x : %u",
439 state_name
, task_addr
, task_errno
441 /* set active thread */
442 if (active_td_addr
== task_addr
)
443 rtos
->current_thread
= task_id
;
449 * API function, get info of selected thread
451 static int mqx_get_thread_reg_list(
457 int64_t stack_ptr
= 0;
458 uint32_t my_task_addr
= 0;
459 uint32_t task_queue_addr
= 0;
460 uint32_t task_queue_size
= 0;
461 uint32_t kernel_data_addr
= 0;
463 *hex_reg_list
= NULL
;
464 if (thread_id
== 0) {
465 LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id
);
468 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
470 /* get kernel_data symbol */
471 if (ERROR_OK
!= mqx_get_symbol(
472 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
476 /* read kernel_data */
477 if (ERROR_OK
!= mqx_get_member(
478 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
482 /* get task queue address */
483 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
484 /* get task queue size */
485 if (ERROR_OK
!= mqx_get_member(
486 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
487 "kernel_data->TD_LIST.SIZE", &task_queue_size
491 /* search for taskid */
493 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
494 i
< (uint32_t)rtos
->thread_count
;
497 uint32_t tmp_address
= 0, task_addr
= 0;
498 uint32_t task_id
= 0;
499 /* set current taskpool address */
500 tmp_address
= taskpool_addr
;
501 if (ERROR_OK
!= mqx_get_member(
502 rtos
, tmp_address
, MQX_TASK_OFFSET_NEXT
, 4,
503 "td_struct_ptr->NEXT", &taskpool_addr
507 /* get task address from taskpool */
508 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
509 /* get value of td_struct->TASK_ID */
510 if (ERROR_OK
!= mqx_get_member(
511 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
512 "td_struct_ptr->TASK_ID", &task_id
516 /* found taskid, break */
517 if (task_id
== thread_id
) {
518 my_task_addr
= task_addr
;
523 LOG_ERROR("MQX_RTOS - threadid %" PRId64
" does not match any task", thread_id
);
526 /* get task stack head address */
527 if (ERROR_OK
!= mqx_get_member(
528 rtos
, my_task_addr
, MQX_TASK_OFFSET_STACK
, 4, "task->STACK_PTR", &stack_ptr
532 return rtos_generic_stack_read(
533 rtos
->target
, ((struct mqx_params
*)rtos
->rtos_specific_params
)->stacking_info
, stack_ptr
, hex_reg_list
537 /* API function, export list of required symbols */
538 static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
540 *symbol_list
= malloc(sizeof(symbol_table_elem_t
) * ARRAY_SIZE(mqx_symbol_list
));
541 if (NULL
== *symbol_list
)
543 /* export required symbols */
544 for (int i
= 0; i
< (int)(ARRAY_SIZE(mqx_symbol_list
)); i
++)
545 (*symbol_list
)[i
].symbol_name
= mqx_symbol_list
[i
];
549 struct rtos_type mqx_rtos
= {
551 .detect_rtos
= mqx_detect_rtos
,
552 .create
= mqx_create
,
553 .update_threads
= mqx_update_threads
,
554 .get_thread_reg_list
= mqx_get_thread_reg_list
,
555 .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)