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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
24 #include <helper/time_support.h>
25 #include <jtag/jtag.h>
26 #include "target/target.h"
27 #include "target/target_type.h"
29 #include "helper/log.h"
30 #include "helper/types.h"
31 #include "rtos_mqx_stackings.h"
34 #define MQX_THREAD_NAME_LENGTH (255)
35 #define MQX_KERNEL_OFFSET_TDLIST (0x0108)
36 #define MQX_KERNEL_OFFSET_SYSTEM_TASK (0x0050)
37 #define MQX_KERNEL_OFFSET_ACTIVE_TASK (0x001C)
38 #define MQX_KERNEL_OFFSET_CAPABILITY (0x0000)
39 #define MQX_QUEUE_OFFSET_SIZE (0x0008)
40 #define MQX_TASK_OFFSET_STATE (0x0008)
41 #define MQX_TASK_OFFSET_ID (0x000c)
42 #define MQX_TASK_OFFSET_TEMPLATE (0x0068)
43 #define MQX_TASK_OFFSET_STACK (0x0014)
44 #define MQX_TASK_OFFSET_TDLIST (0x006C)
45 #define MQX_TASK_OFFSET_NEXT (0x0000)
46 #define MQX_TASK_TEMPLATE_OFFSET_NAME (0x0010)
47 #define MQX_TASK_OFFSET_ERROR_CODE (0x005C)
48 #define MQX_TASK_STATE_MASK (0xFFF)
52 mqx_VAL_mqx_kernel_data
,
53 mqx_VAL_MQX_init_struct
,
61 const char *target_name
;
62 const enum mqx_arch target_arch
;
63 const struct rtos_register_stacking
*stacking_info
;
72 static const struct mqx_state mqx_states
[] = {
74 { 0x0003, "BLOCKED" },
75 { 0x0005, "RCV_SPECIFIC_BLOCKED" },
76 { 0x0007, "RCV_ANY_BLOCKED" },
78 { 0x000B, "UNHANDLED_INT_BLOCKED" },
79 { 0x000D, "SEND_BLOCKED" },
80 { 0x000F, "BREAKPOINT_BLOCKED" },
81 { 0x0211, "IO_BLOCKED" },
82 { 0x0021, "SEM_BLOCKED" },
83 { 0x0223, "MUTEX_BLOCKED" },
84 { 0x0025, "EVENT_BLOCKED" },
85 { 0x0229, "TASK_QUEUE_BLOCKED" },
86 { 0x042B, "LWSEM_BLOCKED" },
87 { 0x042D, "LWEVENT_BLOCKED" },
90 static const char * const mqx_symbol_list
[] = {
96 static const struct mqx_params mqx_params_list
[] = {
97 { "cortex_m", mqx_arch_cortexm
, &rtos_mqx_arm_v7m_stacking
},
101 * Perform simple address check to avoid bus fault.
103 static int mqx_valid_address_check(
108 enum mqx_arch arch_type
= ((struct mqx_params
*)rtos
->rtos_specific_params
)->target_arch
;
109 const char * targetname
= ((struct mqx_params
*)rtos
->rtos_specific_params
)->target_name
;
111 /* Cortex-M address range */
112 if (arch_type
== mqx_arch_cortexm
) {
114 /* code and sram area */
115 (address
&& address
<= 0x3FFFFFFFu
) ||
116 /* external ram area*/
117 (address
>= 0x6000000u
&& address
<= 0x9FFFFFFFu
)
123 LOG_ERROR("MQX RTOS - unknown architecture %s", targetname
);
128 * Wrapper of 'target_read_buffer' fn.
129 * Include address check.
131 static int mqx_target_read_buffer(
132 struct target
*target
,
138 int status
= mqx_valid_address_check(target
->rtos
, address
);
139 if (status
!= ERROR_OK
) {
140 LOG_WARNING("MQX RTOS - target address 0x%" PRIx32
" is not allowed to read", address
);
143 status
= target_read_buffer(target
, address
, size
, buffer
);
144 if (status
!= ERROR_OK
) {
145 LOG_ERROR("MQX RTOS - reading target address 0x%" PRIx32
" failed", address
);
152 * Get symbol address if present
154 static int mqx_get_symbol(
156 enum mqx_symbols symbol
,
160 /* TODO: additional check ?? */
161 (*(int *)result
) = (uint32_t)rtos
->symbols
[symbol
].address
;
166 * Get value of struct member by passing
167 * member offset, width and name (debug purpose)
169 static int mqx_get_member(
171 const uint32_t base_address
,
172 int32_t member_offset
,
173 int32_t member_width
,
174 const char *member_name
,
178 int status
= ERROR_FAIL
;
179 status
= mqx_target_read_buffer(
180 rtos
->target
, base_address
+ member_offset
, member_width
, result
182 if (status
!= ERROR_OK
)
183 LOG_WARNING("MQX RTOS - cannot read \"%s\" at address 0x%" PRIx32
,
184 member_name
, (uint32_t)(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;
294 if (!rtos
->rtos_specific_params
)
301 rtos_free_threadlist(rtos
);
302 /* check scheduler */
303 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
305 /* get kernel_data symbol */
306 if (ERROR_OK
!= mqx_get_symbol(
307 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
311 /* read kernel_data */
312 if (ERROR_OK
!= mqx_get_member(
313 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
317 /* get task queue address */
318 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
319 /* get task queue size */
320 if (ERROR_OK
!= mqx_get_member(
321 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
322 "kernel_data->TD_LIST.SIZE", &task_queue_size
327 if (ERROR_OK
!= mqx_get_member(
328 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
329 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
334 /* setup threads info */
335 rtos
->thread_count
= task_queue_size
;
336 rtos
->current_thread
= 0;
337 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
338 if (NULL
== rtos
->thread_details
)
341 /* loop over each task and setup thread details,
342 the current_taskpool_addr is set to queue head
343 NOTE: debugging functions task create/destroy
344 might cause to show invalid data.
347 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
348 i
< (uint32_t)rtos
->thread_count
;
351 uint8_t task_name
[MQX_THREAD_NAME_LENGTH
+ 1];
352 uint32_t task_addr
= 0, task_template
= 0, task_state
= 0;
353 uint32_t task_name_addr
= 0, task_id
= 0, task_errno
= 0;
354 uint32_t state_index
= 0, state_max
= 0;
355 uint32_t extra_info_length
= 0;
356 char *state_name
= "unknown state";
358 /* set current taskpool address */
359 if (ERROR_OK
!= mqx_get_member(
360 rtos
, taskpool_addr
, MQX_TASK_OFFSET_NEXT
, 4,
361 "td_struct_ptr->NEXT", &taskpool_addr
365 /* get task address from taskpool */
366 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
367 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
368 if (ERROR_OK
!= mqx_get_member(
369 rtos
, task_addr
, MQX_TASK_OFFSET_TEMPLATE
, 4,
370 "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
374 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
375 if (ERROR_OK
!= mqx_get_member(
376 rtos
, task_template
, MQX_TASK_TEMPLATE_OFFSET_NAME
, 4,
377 "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
381 /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
382 if (ERROR_OK
!= mqx_get_member(
383 rtos
, task_name_addr
, 0, MQX_THREAD_NAME_LENGTH
,
384 "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
388 /* always terminate last character by force,
389 otherwise openocd might fail if task_name
390 has corrupted data */
391 task_name
[MQX_THREAD_NAME_LENGTH
] = '\0';
392 /* get value of 'td_struct_ptr->TASK_ID' */
393 if (ERROR_OK
!= mqx_get_member(
394 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
395 "td_struct_ptr->TASK_ID", &task_id
400 if (ERROR_OK
!= mqx_get_member(
401 rtos
, task_addr
, MQX_TASK_OFFSET_ERROR_CODE
, 4,
402 "td_struct_ptr->TASK_ERROR_CODE", &task_errno
406 /* get value of 'td_struct_ptr->STATE' */
407 if (ERROR_OK
!= mqx_get_member(
408 rtos
, task_addr
, MQX_TASK_OFFSET_STATE
, 4,
409 "td_struct_ptr->STATE", &task_state
413 task_state
&= MQX_TASK_STATE_MASK
;
414 /* and search for defined state */
415 state_max
= (sizeof(mqx_states
)/sizeof(struct mqx_state
));
416 for (state_index
= 0; (state_index
< state_max
); state_index
++) {
417 if (mqx_states
[state_index
].state
== task_state
) {
418 state_name
= mqx_states
[state_index
].name
;
423 /* setup thread details struct */
424 rtos
->thread_details
[i
].threadid
= task_id
;
425 rtos
->thread_details
[i
].exists
= true;
426 rtos
->thread_details
[i
].display_str
= NULL
;
427 /* set thread name */
428 rtos
->thread_details
[i
].thread_name_str
= malloc(strlen((void *)task_name
) + 1);
429 if (NULL
== rtos
->thread_details
[i
].thread_name_str
)
431 strcpy(rtos
->thread_details
[i
].thread_name_str
, (void *)task_name
);
432 /* set thread extra info
436 * calculate length as:
437 * state length + address length + errno length + formatter length
439 extra_info_length
+= strlen((void *)state_name
) + 8 + 8 + 8;
440 rtos
->thread_details
[i
].extra_info_str
= malloc(extra_info_length
+ 1);
441 if (NULL
== rtos
->thread_details
[i
].extra_info_str
)
444 rtos
->thread_details
[i
].extra_info_str
, extra_info_length
, "%s : 0x%"PRIx32
" : %" PRIu32
,
445 state_name
, task_addr
, task_errno
447 /* set active thread */
448 if (active_td_addr
== task_addr
)
449 rtos
->current_thread
= task_id
;
455 * API function, get info of selected thread
457 static int mqx_get_thread_reg_list(
463 int64_t stack_ptr
= 0;
464 uint32_t my_task_addr
= 0;
465 uint32_t task_queue_addr
= 0;
466 uint32_t task_queue_size
= 0;
467 uint32_t kernel_data_addr
= 0;
469 *hex_reg_list
= NULL
;
470 if (thread_id
== 0) {
471 LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id
);
474 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
476 /* get kernel_data symbol */
477 if (ERROR_OK
!= mqx_get_symbol(
478 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
482 /* read kernel_data */
483 if (ERROR_OK
!= mqx_get_member(
484 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
488 /* get task queue address */
489 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
490 /* get task queue size */
491 if (ERROR_OK
!= mqx_get_member(
492 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
493 "kernel_data->TD_LIST.SIZE", &task_queue_size
497 /* search for taskid */
499 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
500 i
< (uint32_t)rtos
->thread_count
;
503 uint32_t tmp_address
= 0, task_addr
= 0;
504 uint32_t task_id
= 0;
505 /* set current taskpool address */
506 tmp_address
= taskpool_addr
;
507 if (ERROR_OK
!= mqx_get_member(
508 rtos
, tmp_address
, MQX_TASK_OFFSET_NEXT
, 4,
509 "td_struct_ptr->NEXT", &taskpool_addr
513 /* get task address from taskpool */
514 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
515 /* get value of td_struct->TASK_ID */
516 if (ERROR_OK
!= mqx_get_member(
517 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
518 "td_struct_ptr->TASK_ID", &task_id
522 /* found taskid, break */
523 if (task_id
== thread_id
) {
524 my_task_addr
= task_addr
;
529 LOG_ERROR("MQX_RTOS - threadid %" PRId64
" does not match any task", thread_id
);
532 /* get task stack head address */
533 if (ERROR_OK
!= mqx_get_member(
534 rtos
, my_task_addr
, MQX_TASK_OFFSET_STACK
, 4, "task->STACK_PTR", &stack_ptr
538 return rtos_generic_stack_read(
539 rtos
->target
, ((struct mqx_params
*)rtos
->rtos_specific_params
)->stacking_info
, stack_ptr
, hex_reg_list
543 /* API function, export list of required symbols */
544 static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
546 *symbol_list
= calloc(ARRAY_SIZE(mqx_symbol_list
), sizeof(symbol_table_elem_t
));
547 if (NULL
== *symbol_list
)
549 /* export required symbols */
550 for (int i
= 0; i
< (int)(ARRAY_SIZE(mqx_symbol_list
)); i
++)
551 (*symbol_list
)[i
].symbol_name
= mqx_symbol_list
[i
];
555 struct rtos_type mqx_rtos
= {
557 .detect_rtos
= mqx_detect_rtos
,
558 .create
= mqx_create
,
559 .update_threads
= mqx_update_threads
,
560 .get_thread_reg_list
= mqx_get_thread_reg_list
,
561 .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)