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 true if MQX is present
249 static bool 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";
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 /* set thread name */
427 rtos
->thread_details
[i
].thread_name_str
= malloc(strlen((void *)task_name
) + 1);
428 if (NULL
== rtos
->thread_details
[i
].thread_name_str
)
430 strcpy(rtos
->thread_details
[i
].thread_name_str
, (void *)task_name
);
431 /* set thread extra info
435 * calculate length as:
436 * state length + address length + errno length + formatter length
438 extra_info_length
+= strlen((void *)state_name
) + 7 + 13 + 8 + 15 + 8;
439 rtos
->thread_details
[i
].extra_info_str
= malloc(extra_info_length
+ 1);
440 if (NULL
== rtos
->thread_details
[i
].extra_info_str
)
442 snprintf(rtos
->thread_details
[i
].extra_info_str
, extra_info_length
,
443 "State: %s, Address: 0x%" PRIx32
", Error Code: %" PRIu32
,
444 state_name
, task_addr
, task_errno
446 /* set active thread */
447 if (active_td_addr
== task_addr
)
448 rtos
->current_thread
= task_id
;
454 * API function, get info of selected thread
456 static int mqx_get_thread_reg_list(
459 struct rtos_reg
**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 if (thread_id
== 0) {
470 LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id
);
473 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
475 /* get kernel_data symbol */
476 if (ERROR_OK
!= mqx_get_symbol(
477 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
481 /* read kernel_data */
482 if (ERROR_OK
!= mqx_get_member(
483 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
487 /* get task queue address */
488 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
489 /* get task queue size */
490 if (ERROR_OK
!= mqx_get_member(
491 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
492 "kernel_data->TD_LIST.SIZE", &task_queue_size
496 /* search for taskid */
498 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
499 i
< (uint32_t)rtos
->thread_count
;
502 uint32_t tmp_address
= 0, task_addr
= 0;
503 uint32_t task_id
= 0;
504 /* set current taskpool address */
505 tmp_address
= taskpool_addr
;
506 if (ERROR_OK
!= mqx_get_member(
507 rtos
, tmp_address
, MQX_TASK_OFFSET_NEXT
, 4,
508 "td_struct_ptr->NEXT", &taskpool_addr
512 /* get task address from taskpool */
513 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
514 /* get value of td_struct->TASK_ID */
515 if (ERROR_OK
!= mqx_get_member(
516 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
517 "td_struct_ptr->TASK_ID", &task_id
521 /* found taskid, break */
522 if (task_id
== thread_id
) {
523 my_task_addr
= task_addr
;
528 LOG_ERROR("MQX_RTOS - threadid %" PRId64
" does not match any task", thread_id
);
531 /* get task stack head address */
532 if (ERROR_OK
!= mqx_get_member(
533 rtos
, my_task_addr
, MQX_TASK_OFFSET_STACK
, 4, "task->STACK_PTR", &stack_ptr
537 return rtos_generic_stack_read(
538 rtos
->target
, ((struct mqx_params
*)rtos
->rtos_specific_params
)->stacking_info
, stack_ptr
, reg_list
, num_regs
542 /* API function, export list of required symbols */
543 static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
545 *symbol_list
= calloc(ARRAY_SIZE(mqx_symbol_list
), sizeof(symbol_table_elem_t
));
546 if (NULL
== *symbol_list
)
548 /* export required symbols */
549 for (int i
= 0; i
< (int)(ARRAY_SIZE(mqx_symbol_list
)); i
++)
550 (*symbol_list
)[i
].symbol_name
= mqx_symbol_list
[i
];
554 struct rtos_type mqx_rtos
= {
556 .detect_rtos
= mqx_detect_rtos
,
557 .create
= mqx_create
,
558 .update_threads
= mqx_update_threads
,
559 .get_thread_reg_list
= mqx_get_thread_reg_list
,
560 .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)