1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2014 by Marian Cingel *
5 * cingel.marian@gmail.com *
6 ***************************************************************************/
13 #include <helper/time_support.h>
14 #include <jtag/jtag.h>
15 #include "target/target.h"
16 #include "target/target_type.h"
18 #include "helper/log.h"
19 #include "helper/types.h"
20 #include "rtos_mqx_stackings.h"
23 #define MQX_THREAD_NAME_LENGTH (255)
24 #define MQX_KERNEL_OFFSET_TDLIST (0x0108)
25 #define MQX_KERNEL_OFFSET_SYSTEM_TASK (0x0050)
26 #define MQX_KERNEL_OFFSET_ACTIVE_TASK (0x001C)
27 #define MQX_KERNEL_OFFSET_CAPABILITY (0x0000)
28 #define MQX_QUEUE_OFFSET_SIZE (0x0008)
29 #define MQX_TASK_OFFSET_STATE (0x0008)
30 #define MQX_TASK_OFFSET_ID (0x000c)
31 #define MQX_TASK_OFFSET_TEMPLATE (0x0068)
32 #define MQX_TASK_OFFSET_STACK (0x0014)
33 #define MQX_TASK_OFFSET_TDLIST (0x006C)
34 #define MQX_TASK_OFFSET_NEXT (0x0000)
35 #define MQX_TASK_TEMPLATE_OFFSET_NAME (0x0010)
36 #define MQX_TASK_OFFSET_ERROR_CODE (0x005C)
37 #define MQX_TASK_STATE_MASK (0xFFF)
41 MQX_VAL_MQX_KERNEL_DATA
,
42 MQX_VAL_MQX_INIT_STRUCT
,
50 const char *target_name
;
51 const enum mqx_arch target_arch
;
52 const struct rtos_register_stacking
*stacking_info
;
61 static const struct mqx_state mqx_states
[] = {
63 { 0x0003, "BLOCKED" },
64 { 0x0005, "RCV_SPECIFIC_BLOCKED" },
65 { 0x0007, "RCV_ANY_BLOCKED" },
67 { 0x000B, "UNHANDLED_INT_BLOCKED" },
68 { 0x000D, "SEND_BLOCKED" },
69 { 0x000F, "BREAKPOINT_BLOCKED" },
70 { 0x0211, "IO_BLOCKED" },
71 { 0x0021, "SEM_BLOCKED" },
72 { 0x0223, "MUTEX_BLOCKED" },
73 { 0x0025, "EVENT_BLOCKED" },
74 { 0x0229, "TASK_QUEUE_BLOCKED" },
75 { 0x042B, "LWSEM_BLOCKED" },
76 { 0x042D, "LWEVENT_BLOCKED" },
79 static const char * const mqx_symbol_list
[] = {
85 static const struct mqx_params mqx_params_list
[] = {
86 { "cortex_m", mqx_arch_cortexm
, &rtos_mqx_arm_v7m_stacking
},
90 * Perform simple address check to avoid bus fault.
92 static int mqx_valid_address_check(
97 enum mqx_arch arch_type
= ((struct mqx_params
*)rtos
->rtos_specific_params
)->target_arch
;
98 const char *targetname
= ((struct mqx_params
*)rtos
->rtos_specific_params
)->target_name
;
100 /* Cortex-M address range */
101 if (arch_type
== mqx_arch_cortexm
) {
103 /* code and sram area */
104 (address
&& address
<= 0x3FFFFFFFu
) ||
105 /* external ram area*/
106 (address
>= 0x6000000u
&& address
<= 0x9FFFFFFFu
)
112 LOG_ERROR("MQX RTOS - unknown architecture %s", targetname
);
117 * Wrapper of 'target_read_buffer' fn.
118 * Include address check.
120 static int mqx_target_read_buffer(
121 struct target
*target
,
127 int status
= mqx_valid_address_check(target
->rtos
, address
);
128 if (status
!= ERROR_OK
) {
129 LOG_WARNING("MQX RTOS - target address 0x%" PRIx32
" is not allowed to read", address
);
132 status
= target_read_buffer(target
, address
, size
, buffer
);
133 if (status
!= ERROR_OK
) {
134 LOG_ERROR("MQX RTOS - reading target address 0x%" PRIx32
" failed", address
);
141 * Get symbol address if present
143 static int mqx_get_symbol(
145 enum mqx_symbols symbol
,
149 /* TODO: additional check ?? */
150 (*(int *)result
) = (uint32_t)rtos
->symbols
[symbol
].address
;
155 * Get value of struct member by passing
156 * member offset, width and name (debug purpose)
158 static int mqx_get_member(
160 const uint32_t base_address
,
161 int32_t member_offset
,
162 int32_t member_width
,
163 const char *member_name
,
167 int status
= ERROR_FAIL
;
168 status
= mqx_target_read_buffer(
169 rtos
->target
, base_address
+ member_offset
, member_width
, result
171 if (status
!= ERROR_OK
)
172 LOG_WARNING("MQX RTOS - cannot read \"%s\" at address 0x%" PRIx32
,
173 member_name
, (uint32_t)(base_address
+ member_offset
));
178 * Check whether scheduler started
180 static int mqx_is_scheduler_running(
184 uint32_t kernel_data_symbol
= 0;
185 uint32_t kernel_data_addr
= 0;
186 uint32_t system_td_addr
= 0;
187 uint32_t active_td_addr
= 0;
188 uint32_t capability_value
= 0;
190 /* get '_mqx_kernel_data' symbol */
191 if (mqx_get_symbol(rtos
, MQX_VAL_MQX_KERNEL_DATA
, &kernel_data_symbol
) != ERROR_OK
)
194 /* get '_mqx_kernel_data' */
195 if (mqx_get_member(rtos
, kernel_data_symbol
, 0, 4,
196 "_mqx_kernel_data", &kernel_data_addr
) != ERROR_OK
)
199 /* return if '_mqx_kernel_data' is NULL or default 0xFFFFFFFF */
200 if (kernel_data_addr
== 0 || kernel_data_addr
== (uint32_t)(-1))
202 /* get kernel_data->ADDRESSING_CAPABILITY */
203 if (mqx_get_member(rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_CAPABILITY
, 4,
204 "kernel_data->ADDRESSING_CAPABILITY", (void *)&capability_value
) != ERROR_OK
)
207 /* check first member, the '_mqx_kernel_data->ADDRESSING_CAPABILITY'.
208 it suppose to be set to value 8 */
209 if (capability_value
!= 8) {
210 LOG_WARNING("MQX RTOS - value of '_mqx_kernel_data->ADDRESSING_CAPABILITY' contains invalid value");
214 if (mqx_get_member(rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
215 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
) != ERROR_OK
)
218 /* active task is system task, scheduler has not not run yet */
219 system_td_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_SYSTEM_TASK
;
220 if (active_td_addr
== system_td_addr
) {
221 LOG_WARNING("MQX RTOS - scheduler does not run");
228 * API function, return true if MQX is present
230 static bool mqx_detect_rtos(
231 struct target
*target
235 (target
->rtos
->symbols
) &&
236 (target
->rtos
->symbols
[MQX_VAL_MQX_KERNEL_DATA
].address
!= 0)
244 * API function, pass MQX extra info to context data
246 static int mqx_create(
247 struct target
*target
250 /* check target name against supported architectures */
251 for (unsigned int i
= 0; i
< ARRAY_SIZE(mqx_params_list
); i
++) {
252 if (strcmp(mqx_params_list
[i
].target_name
, target
->type
->name
) == 0) {
253 target
->rtos
->rtos_specific_params
= (void *)&mqx_params_list
[i
];
254 /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */
258 LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target
->type
->name
);
263 * API function, update list of threads
265 static int mqx_update_threads(
269 uint32_t task_queue_addr
= 0;
270 uint32_t kernel_data_addr
= 0;
271 uint16_t task_queue_size
= 0;
272 uint32_t active_td_addr
= 0;
274 if (!rtos
->rtos_specific_params
)
281 rtos_free_threadlist(rtos
);
282 /* check scheduler */
283 if (mqx_is_scheduler_running(rtos
) != ERROR_OK
)
285 /* get kernel_data symbol */
286 if (mqx_get_symbol(rtos
, MQX_VAL_MQX_KERNEL_DATA
, &kernel_data_addr
) != ERROR_OK
)
289 /* read kernel_data */
290 if (mqx_get_member(rtos
, kernel_data_addr
, 0, 4,
291 "_mqx_kernel_data", &kernel_data_addr
) != ERROR_OK
)
294 /* get task queue address */
295 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
296 /* get task queue size */
297 if (mqx_get_member(rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
298 "kernel_data->TD_LIST.SIZE", &task_queue_size
) != ERROR_OK
)
302 if (mqx_get_member(rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
303 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
) != ERROR_OK
)
306 /* setup threads info */
307 rtos
->thread_count
= task_queue_size
;
308 rtos
->current_thread
= 0;
309 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
310 if (!rtos
->thread_details
)
313 /* loop over each task and setup thread details,
314 the current_taskpool_addr is set to queue head
315 NOTE: debugging functions task create/destroy
316 might cause to show invalid data.
319 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
320 i
< (uint32_t)rtos
->thread_count
;
323 uint8_t task_name
[MQX_THREAD_NAME_LENGTH
+ 1];
324 uint32_t task_addr
= 0, task_template
= 0, task_state
= 0;
325 uint32_t task_name_addr
= 0, task_id
= 0, task_errno
= 0;
326 uint32_t state_index
= 0;
327 uint32_t extra_info_length
= 0;
328 char *state_name
= "Unknown";
330 /* set current taskpool address */
331 if (mqx_get_member(rtos
, taskpool_addr
, MQX_TASK_OFFSET_NEXT
, 4,
332 "td_struct_ptr->NEXT", &taskpool_addr
) != ERROR_OK
)
335 /* get task address from taskpool */
336 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
337 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
338 if (mqx_get_member(rtos
, task_addr
, MQX_TASK_OFFSET_TEMPLATE
, 4,
339 "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
) != ERROR_OK
)
342 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
343 if (mqx_get_member(rtos
, task_template
, MQX_TASK_TEMPLATE_OFFSET_NAME
, 4,
344 "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
) != ERROR_OK
)
347 /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
348 if (mqx_get_member(rtos
, task_name_addr
, 0, MQX_THREAD_NAME_LENGTH
,
349 "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
) != ERROR_OK
)
352 /* always terminate last character by force,
353 otherwise openocd might fail if task_name
354 has corrupted data */
355 task_name
[MQX_THREAD_NAME_LENGTH
] = '\0';
356 /* get value of 'td_struct_ptr->TASK_ID' */
357 if (mqx_get_member(rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
358 "td_struct_ptr->TASK_ID", &task_id
) != ERROR_OK
)
362 if (mqx_get_member(rtos
, task_addr
, MQX_TASK_OFFSET_ERROR_CODE
, 4,
363 "td_struct_ptr->TASK_ERROR_CODE", &task_errno
) != ERROR_OK
)
366 /* get value of 'td_struct_ptr->STATE' */
367 if (mqx_get_member(rtos
, task_addr
, MQX_TASK_OFFSET_STATE
, 4,
368 "td_struct_ptr->STATE", &task_state
) != ERROR_OK
)
371 task_state
&= MQX_TASK_STATE_MASK
;
372 /* and search for defined state */
373 for (state_index
= 0; state_index
< ARRAY_SIZE(mqx_states
); state_index
++) {
374 if (mqx_states
[state_index
].state
== task_state
) {
375 state_name
= mqx_states
[state_index
].name
;
380 /* setup thread details struct */
381 rtos
->thread_details
[i
].threadid
= task_id
;
382 rtos
->thread_details
[i
].exists
= true;
383 /* set thread name */
384 rtos
->thread_details
[i
].thread_name_str
= malloc(strlen((void *)task_name
) + 1);
385 if (!rtos
->thread_details
[i
].thread_name_str
)
387 strcpy(rtos
->thread_details
[i
].thread_name_str
, (void *)task_name
);
388 /* set thread extra info
392 * calculate length as:
393 * state length + address length + errno length + formatter length
395 extra_info_length
+= strlen((void *)state_name
) + 7 + 13 + 8 + 15 + 8;
396 rtos
->thread_details
[i
].extra_info_str
= malloc(extra_info_length
+ 1);
397 if (!rtos
->thread_details
[i
].extra_info_str
)
399 snprintf(rtos
->thread_details
[i
].extra_info_str
, extra_info_length
,
400 "State: %s, Address: 0x%" PRIx32
", Error Code: %" PRIu32
,
401 state_name
, task_addr
, task_errno
403 /* set active thread */
404 if (active_td_addr
== task_addr
)
405 rtos
->current_thread
= task_id
;
411 * API function, get info of selected thread
413 static int mqx_get_thread_reg_list(
416 struct rtos_reg
**reg_list
,
420 int64_t stack_ptr
= 0;
421 uint32_t my_task_addr
= 0;
422 uint32_t task_queue_addr
= 0;
423 uint32_t task_queue_size
= 0;
424 uint32_t kernel_data_addr
= 0;
426 if (thread_id
== 0) {
427 LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id
);
430 if (mqx_is_scheduler_running(rtos
) != ERROR_OK
)
432 /* get kernel_data symbol */
433 if (mqx_get_symbol(rtos
, MQX_VAL_MQX_KERNEL_DATA
, &kernel_data_addr
) != ERROR_OK
)
436 /* read kernel_data */
437 if (mqx_get_member(rtos
, kernel_data_addr
, 0, 4,
438 "_mqx_kernel_data", &kernel_data_addr
) != ERROR_OK
)
441 /* get task queue address */
442 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
443 /* get task queue size */
444 if (mqx_get_member(rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
445 "kernel_data->TD_LIST.SIZE", &task_queue_size
) != ERROR_OK
)
448 /* search for taskid */
450 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
451 i
< (uint32_t)rtos
->thread_count
;
454 uint32_t tmp_address
= 0, task_addr
= 0;
455 uint32_t task_id
= 0;
456 /* set current taskpool address */
457 tmp_address
= taskpool_addr
;
458 if (mqx_get_member(rtos
, tmp_address
, MQX_TASK_OFFSET_NEXT
, 4,
459 "td_struct_ptr->NEXT", &taskpool_addr
) != ERROR_OK
)
462 /* get task address from taskpool */
463 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
464 /* get value of td_struct->TASK_ID */
465 if (mqx_get_member(rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
466 "td_struct_ptr->TASK_ID", &task_id
) != ERROR_OK
)
469 /* found taskid, break */
470 if (task_id
== thread_id
) {
471 my_task_addr
= task_addr
;
476 LOG_ERROR("MQX_RTOS - threadid %" PRId64
" does not match any task", thread_id
);
479 /* get task stack head address */
480 if (mqx_get_member(rtos
, my_task_addr
, MQX_TASK_OFFSET_STACK
, 4,
481 "task->STACK_PTR", &stack_ptr
) != ERROR_OK
)
484 return rtos_generic_stack_read(
485 rtos
->target
, ((struct mqx_params
*)rtos
->rtos_specific_params
)->stacking_info
, stack_ptr
, reg_list
, num_regs
489 /* API function, export list of required symbols */
490 static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
492 *symbol_list
= calloc(ARRAY_SIZE(mqx_symbol_list
), sizeof(struct symbol_table_elem
));
495 /* export required symbols */
496 for (int i
= 0; i
< (int)(ARRAY_SIZE(mqx_symbol_list
)); i
++)
497 (*symbol_list
)[i
].symbol_name
= mqx_symbol_list
[i
];
501 struct rtos_type mqx_rtos
= {
503 .detect_rtos
= mqx_detect_rtos
,
504 .create
= mqx_create
,
505 .update_threads
= mqx_update_threads
,
506 .get_thread_reg_list
= mqx_get_thread_reg_list
,
507 .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)