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 suppose 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 for (unsigned int i
= 0; i
< ARRAY_SIZE(mqx_params_list
); i
++) {
271 if (0 == strcmp(mqx_params_list
[i
].target_name
, target
->type
->name
)) {
272 target
->rtos
->rtos_specific_params
= (void *)&mqx_params_list
[i
];
273 /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */
277 LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target
->type
->name
);
282 * API function, update list of threads
284 static int mqx_update_threads(
288 uint32_t task_queue_addr
= 0;
289 uint32_t kernel_data_addr
= 0;
290 uint16_t task_queue_size
= 0;
291 uint32_t active_td_addr
= 0;
293 if (!rtos
->rtos_specific_params
)
300 rtos_free_threadlist(rtos
);
301 /* check scheduler */
302 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
304 /* get kernel_data symbol */
305 if (ERROR_OK
!= mqx_get_symbol(
306 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
310 /* read kernel_data */
311 if (ERROR_OK
!= mqx_get_member(
312 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
316 /* get task queue address */
317 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
318 /* get task queue size */
319 if (ERROR_OK
!= mqx_get_member(
320 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
321 "kernel_data->TD_LIST.SIZE", &task_queue_size
326 if (ERROR_OK
!= mqx_get_member(
327 rtos
, kernel_data_addr
, MQX_KERNEL_OFFSET_ACTIVE_TASK
, 4,
328 "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
333 /* setup threads info */
334 rtos
->thread_count
= task_queue_size
;
335 rtos
->current_thread
= 0;
336 rtos
->thread_details
= calloc(rtos
->thread_count
, sizeof(struct thread_detail
));
337 if (NULL
== rtos
->thread_details
)
340 /* loop over each task and setup thread details,
341 the current_taskpool_addr is set to queue head
342 NOTE: debugging functions task create/destroy
343 might cause to show invalid data.
346 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
347 i
< (uint32_t)rtos
->thread_count
;
350 uint8_t task_name
[MQX_THREAD_NAME_LENGTH
+ 1];
351 uint32_t task_addr
= 0, task_template
= 0, task_state
= 0;
352 uint32_t task_name_addr
= 0, task_id
= 0, task_errno
= 0;
353 uint32_t state_index
= 0;
354 uint32_t extra_info_length
= 0;
355 char *state_name
= "Unknown";
357 /* set current taskpool address */
358 if (ERROR_OK
!= mqx_get_member(
359 rtos
, taskpool_addr
, MQX_TASK_OFFSET_NEXT
, 4,
360 "td_struct_ptr->NEXT", &taskpool_addr
364 /* get task address from taskpool */
365 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
366 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
367 if (ERROR_OK
!= mqx_get_member(
368 rtos
, task_addr
, MQX_TASK_OFFSET_TEMPLATE
, 4,
369 "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
373 /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
374 if (ERROR_OK
!= mqx_get_member(
375 rtos
, task_template
, MQX_TASK_TEMPLATE_OFFSET_NAME
, 4,
376 "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
380 /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
381 if (ERROR_OK
!= mqx_get_member(
382 rtos
, task_name_addr
, 0, MQX_THREAD_NAME_LENGTH
,
383 "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
387 /* always terminate last character by force,
388 otherwise openocd might fail if task_name
389 has corrupted data */
390 task_name
[MQX_THREAD_NAME_LENGTH
] = '\0';
391 /* get value of 'td_struct_ptr->TASK_ID' */
392 if (ERROR_OK
!= mqx_get_member(
393 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
394 "td_struct_ptr->TASK_ID", &task_id
399 if (ERROR_OK
!= mqx_get_member(
400 rtos
, task_addr
, MQX_TASK_OFFSET_ERROR_CODE
, 4,
401 "td_struct_ptr->TASK_ERROR_CODE", &task_errno
405 /* get value of 'td_struct_ptr->STATE' */
406 if (ERROR_OK
!= mqx_get_member(
407 rtos
, task_addr
, MQX_TASK_OFFSET_STATE
, 4,
408 "td_struct_ptr->STATE", &task_state
412 task_state
&= MQX_TASK_STATE_MASK
;
413 /* and search for defined state */
414 for (state_index
= 0; state_index
< ARRAY_SIZE(mqx_states
); state_index
++) {
415 if (mqx_states
[state_index
].state
== task_state
) {
416 state_name
= mqx_states
[state_index
].name
;
421 /* setup thread details struct */
422 rtos
->thread_details
[i
].threadid
= task_id
;
423 rtos
->thread_details
[i
].exists
= true;
424 /* set thread name */
425 rtos
->thread_details
[i
].thread_name_str
= malloc(strlen((void *)task_name
) + 1);
426 if (NULL
== rtos
->thread_details
[i
].thread_name_str
)
428 strcpy(rtos
->thread_details
[i
].thread_name_str
, (void *)task_name
);
429 /* set thread extra info
433 * calculate length as:
434 * state length + address length + errno length + formatter length
436 extra_info_length
+= strlen((void *)state_name
) + 7 + 13 + 8 + 15 + 8;
437 rtos
->thread_details
[i
].extra_info_str
= malloc(extra_info_length
+ 1);
438 if (NULL
== rtos
->thread_details
[i
].extra_info_str
)
440 snprintf(rtos
->thread_details
[i
].extra_info_str
, extra_info_length
,
441 "State: %s, Address: 0x%" PRIx32
", Error Code: %" PRIu32
,
442 state_name
, task_addr
, task_errno
444 /* set active thread */
445 if (active_td_addr
== task_addr
)
446 rtos
->current_thread
= task_id
;
452 * API function, get info of selected thread
454 static int mqx_get_thread_reg_list(
457 struct rtos_reg
**reg_list
,
461 int64_t stack_ptr
= 0;
462 uint32_t my_task_addr
= 0;
463 uint32_t task_queue_addr
= 0;
464 uint32_t task_queue_size
= 0;
465 uint32_t kernel_data_addr
= 0;
467 if (thread_id
== 0) {
468 LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id
);
471 if (ERROR_OK
!= mqx_is_scheduler_running(rtos
))
473 /* get kernel_data symbol */
474 if (ERROR_OK
!= mqx_get_symbol(
475 rtos
, mqx_VAL_mqx_kernel_data
, &kernel_data_addr
479 /* read kernel_data */
480 if (ERROR_OK
!= mqx_get_member(
481 rtos
, kernel_data_addr
, 0, 4, "_mqx_kernel_data", &kernel_data_addr
485 /* get task queue address */
486 task_queue_addr
= kernel_data_addr
+ MQX_KERNEL_OFFSET_TDLIST
;
487 /* get task queue size */
488 if (ERROR_OK
!= mqx_get_member(
489 rtos
, task_queue_addr
, MQX_QUEUE_OFFSET_SIZE
, 2,
490 "kernel_data->TD_LIST.SIZE", &task_queue_size
494 /* search for taskid */
496 uint32_t i
= 0, taskpool_addr
= task_queue_addr
;
497 i
< (uint32_t)rtos
->thread_count
;
500 uint32_t tmp_address
= 0, task_addr
= 0;
501 uint32_t task_id
= 0;
502 /* set current taskpool address */
503 tmp_address
= taskpool_addr
;
504 if (ERROR_OK
!= mqx_get_member(
505 rtos
, tmp_address
, MQX_TASK_OFFSET_NEXT
, 4,
506 "td_struct_ptr->NEXT", &taskpool_addr
510 /* get task address from taskpool */
511 task_addr
= taskpool_addr
- MQX_TASK_OFFSET_TDLIST
;
512 /* get value of td_struct->TASK_ID */
513 if (ERROR_OK
!= mqx_get_member(
514 rtos
, task_addr
, MQX_TASK_OFFSET_ID
, 4,
515 "td_struct_ptr->TASK_ID", &task_id
519 /* found taskid, break */
520 if (task_id
== thread_id
) {
521 my_task_addr
= task_addr
;
526 LOG_ERROR("MQX_RTOS - threadid %" PRId64
" does not match any task", thread_id
);
529 /* get task stack head address */
530 if (ERROR_OK
!= mqx_get_member(
531 rtos
, my_task_addr
, MQX_TASK_OFFSET_STACK
, 4, "task->STACK_PTR", &stack_ptr
535 return rtos_generic_stack_read(
536 rtos
->target
, ((struct mqx_params
*)rtos
->rtos_specific_params
)->stacking_info
, stack_ptr
, reg_list
, num_regs
540 /* API function, export list of required symbols */
541 static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
543 *symbol_list
= calloc(ARRAY_SIZE(mqx_symbol_list
), sizeof(struct symbol_table_elem
));
544 if (NULL
== *symbol_list
)
546 /* export required symbols */
547 for (int i
= 0; i
< (int)(ARRAY_SIZE(mqx_symbol_list
)); i
++)
548 (*symbol_list
)[i
].symbol_name
= mqx_symbol_list
[i
];
552 struct rtos_type mqx_rtos
= {
554 .detect_rtos
= mqx_detect_rtos
,
555 .create
= mqx_create
,
556 .update_threads
= mqx_update_threads
,
557 .get_thread_reg_list
= mqx_get_thread_reg_list
,
558 .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)