Hi,
I found that currently OpenOCD supports ThreadX only for Cortext M3 and R4
cores. But I work with Cypress FX3 chip that has ARM926EJS core and ThreadX.
I found that I need to search next information:
1. TX_THREAD offset information
2. Stacking information
TX_THREAD offset information is a simple. It same to the Cortex M3/R4 one.
Stacking information more difficult for me.
I use disassembler to restore some ThreadX procs to understand how to
registers saves to stack. I found that for ARM926 uses two types of
stacking:
1. Solicited and
2. Interrupt
First type of context saves only R4-R11, R14 and CPSR registers. Interrupt
context saves full set of registers: R0-R12,R14 and CPSR.
First DWORD (32bit) in stack indicates type of context:
0x00000000 - Solicited context
0x00000001 - Interrupt context
Solicited context uses when rescheduling occured via API calls, like
_tx_thread_sleep(), _tx_thread_relinquish() and any other that calls
_tx_thread_system_return() at the end (this function saves Solicited
context). This type of scheduling like to simple function call so PC (r14)
does not saves. This type of context requires 11 DWORDS to save (1 for type
and 10 for registers).
Interrupt context uses when rescheduling occured from ISR. This type of
context requires 17 DWORDS to save (1 for type and 16 for registers).
Context restores at the _tx_thread_schedule(). It determine type of context
and load appropriate registers set from stack.
I modify ThreadX.c to add ARM926EJS support (patch is attached). Now I can
see threads, it names and states. But I see wrong stack trace, like:
(arm-gdb)info threads
[New Thread 1074062196]
[New Thread 1074057804]
[New Thread 1074056680]
[New Thread 1074056948]
[New Thread 1074056224]
[New Thread 1074058112]
[New Thread 1074057256]
[New Thread 1074059220]
Id Target Id Frame
9 Thread 1074059220 (04_UIB_THREAD : : Sleeping) 0x00000000 in ?? ()
8 Thread 1074057256 (05_LPP_THREAD : : Waiting - Event flag)
0x00000000 in ?? ()
7 Thread 1074058112 (03_PIB_THREAD : : Waiting - Event flag)
0x00000000 in ?? ()
6 Thread 1074056224 (Debug Thread : : Waiting - Queue) 0x00000000 in
?? ()
5 Thread 1074056948 (06_SIB_THREAD : : Sleeping) 0x00000000 in ?? ()
4 Thread 1074056680 (02_SYSTEM_THREAD : : Waiting - Event flag)
0x00000000 in ?? ()
3 Thread 1074057804 (01_DMA_THREAD : : Waiting - Queue) 0x00000000 in
?? ()
2 Thread 1074062196 (System Timer Thread : : Suspended) 0x00000000 in
?? ()
* 1 Thread 1074051620 (MAIN : : Ready) 0x4001429c in gpio_init () at
epilib/gpio.c:84
(arm-gdb)thread 5
[Switching to thread 5 (Thread 1074056948)]
#0 0x00000000 in ?? ()
(arm-gdb)bt
#0 0x00000000 in ?? ()
#1 0x40003a30 in _tx_thread_system_suspend (thread_ptr=0x4004d7d4
<glUibThread>) at tx_thread_system_suspend.c:803
#2 0x60000052 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(arm-gdb)info registers
r0 0x0 0
r1 0x0 0
r2 0x0 0
r3 0x0 0
r4 0x4004d7d4 1074059220
r5 0x60000053 1610612819
r6 0x600000d3 1610612947
r7 0x4 4
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x0 0
sp 0x40059380 0x40059380
lr 0x40003a30 0x40003a30 <_tx_thread_system_suspend+1472>
pc 0x0 0x0
cpsr 0x60000053 1610612819
Only one thread at time shows more-less correct stack trace.
I don't understand where I am wrong. So any help and suggestions is
welcomed!
PS Patch based on OpenOCD-0.8.0
--
WBR, Alexander Drozdov
http://htrd.su
--- openocd-0.8.0/src/rtos/ThreadX.c 2014-03-30 14:54:34.000000000 +1100
+++ openocd-0.8.0.new/src/rtos/ThreadX.c 2015-01-29 14:49:32.825672075
+1000
@@ -31,12 +31,17 @@
#include "helper/types.h"
#include "rtos_standard_stackings.h"
+static const struct rtos_register_stacking* get_stacking_info(struct rtos
*rtos, int64_t stack_ptr);
+static const struct rtos_register_stacking* get_stacking_info_arm926ejs(struct
rtos *rtos, int64_t stack_ptr);
+
static int ThreadX_detect_rtos(struct target *target);
static int ThreadX_create(struct target *target);
static int ThreadX_update_threads(struct rtos *rtos);
static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
char **hex_reg_list);
static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list[]);
+
+
struct ThreadX_thread_state {
int value;
char *desc;
@@ -61,6 +66,66 @@
#define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct
ThreadX_thread_state))
+#define ARM926EJS_REGISTERS_SIZE_SOLICITED (11 * 4)
+static const struct stack_register_offset
rtos_threadx_arm926ejs_stack_offsets_solicited[] = {
+ { -1, 32 }, /* r0 */
+ { -1, 32 }, /* r1 */
+ { -1, 32 }, /* r2 */
+ { -1, 32 }, /* r3 */
+ { 0x08, 32 }, /* r4 */
+ { 0x0C, 32 }, /* r5 */
+ { 0x10, 32 }, /* r6 */
+ { 0x14, 32 }, /* r7 */
+ { 0x18, 32 }, /* r8 */
+ { 0x1C, 32 }, /* r9 */
+ { 0x20, 32 }, /* r10 */
+ { 0x24, 32 }, /* r11 */
+ { -1, 32 }, /* r12 */
+ { -2, 32 }, /* sp (r13) */
+ { 0x28, 32 }, /* lr (r14) */
+ { -1, 32 }, /* pc (r15) */
+// { -1, 32 }, /* lr (r14) */
+// { 0x28, 32 }, /* pc (r15) */
+ { 0x04, 32 }, /* xPSR */
+};
+#define ARM926EJS_REGISTERS_SIZE_INTERRUPT (17 * 4)
+static const struct stack_register_offset
rtos_threadx_arm926ejs_stack_offsets_interrupt[] = {
+ { 0x08, 32 }, /* r0 */
+ { 0x0C, 32 }, /* r1 */
+ { 0x10, 32 }, /* r2 */
+ { 0x14, 32 }, /* r3 */
+ { 0x18, 32 }, /* r4 */
+ { 0x1C, 32 }, /* r5 */
+ { 0x20, 32 }, /* r6 */
+ { 0x24, 32 }, /* r7 */
+ { 0x28, 32 }, /* r8 */
+ { 0x2C, 32 }, /* r9 */
+ { 0x30, 32 }, /* r10 */
+ { 0x34, 32 }, /* r11 */
+ { 0x38, 32 }, /* r12 */
+ { -2, 32 }, /* sp (r13) */
+ { 0x3C, 32 }, /* lr (r14) */
+ { 0x40, 32 }, /* pc (r15) */
+ { 0x04, 32 }, /* xPSR */
+};
+
+const struct rtos_register_stacking rtos_threadx_arm926ejs_stacking[] = {
+ {
+ ARM926EJS_REGISTERS_SIZE_SOLICITED, /* stack_registers_size */
+ -1, /*
stack_growth_direction */
+ 17, /* num_output_registers */
+ 8, /* stack_alignment */
+ rtos_threadx_arm926ejs_stack_offsets_solicited /* register_offsets */
+ },
+ {
+ ARM926EJS_REGISTERS_SIZE_INTERRUPT, /* stack_registers_size */
+ -1, /*
stack_growth_direction */
+ 17, /* num_output_registers */
+ 8, /* stack_alignment */
+ rtos_threadx_arm926ejs_stack_offsets_interrupt /* register_offsets */
+ },
+};
+
struct ThreadX_params {
char *target_name;
unsigned char pointer_width;
@@ -69,6 +134,8 @@
unsigned char thread_state_offset;
unsigned char thread_next_offset;
const struct rtos_register_stacking *stacking_info;
+ size_t stacking_info_nb;
+ const struct rtos_register_stacking* (*stacking_info_proc)(struct rtos
*rtos, int64_t stack_ptr);
};
const struct ThreadX_params ThreadX_params_list[] = {
@@ -80,6 +147,8 @@
48, /*
thread_state_offset; */
136, /* thread_next_offset */
&rtos_standard_Cortex_M3_stacking, /* stacking_info */
+ 1, /* stacking_info_nb */
+ NULL, /* stacking_info_proc */
},
{
"cortex_r4", /* target_name */
@@ -89,6 +158,19 @@
48, /*
thread_state_offset; */
136, /* thread_next_offset */
&rtos_standard_Cortex_R4_stacking, /* stacking_info */
+ 1, /* stacking_info_nb */
+ NULL, /* stacking_info_proc */
+ },
+ {
+ "arm926ejs", /* target_name */
+ 4, /*
pointer_width; */
+ 8, /*
thread_stack_offset; */
+ 40, /*
thread_name_offset; */
+ 48, /*
thread_state_offset; */
+ 136, /* thread_next_offset */
+ rtos_threadx_arm926ejs_stacking, /* stacking_info */
+ 2, /* stacking_info_nb */
+ get_stacking_info_arm926ejs, /* stacking_info_proc */
},
};
@@ -118,6 +200,41 @@
};
+static const struct rtos_register_stacking* get_stacking_info(struct rtos
*rtos, int64_t stack_ptr)
+{
+ const struct ThreadX_params *param = (const struct ThreadX_params *)
rtos->rtos_specific_params;
+
+ if (param->stacking_info_proc != NULL) {
+ return param->stacking_info_proc(rtos, stack_ptr);
+ }
+
+ return (param->stacking_info + 0);
+}
+
+static const struct rtos_register_stacking* get_stacking_info_arm926ejs(struct
rtos *rtos, int64_t stack_ptr)
+{
+ const struct ThreadX_params *param = (const struct ThreadX_params *)
rtos->rtos_specific_params;
+ int retval;
+ uint32_t flag;
+
+ retval = target_read_buffer(rtos->target,
+ stack_ptr,
+ sizeof(flag),
+ (uint8_t *)&flag);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error reading stack data from ThreadX thread");
+ return NULL;
+ }
+
+ if (flag == 0) {
+ LOG_INFO(" solicited stack");
+ return param->stacking_info + 0;
+ } else {
+ LOG_INFO(" interrupt stack: %u", flag);
+ return param->stacking_info + 1;
+ }
+}
+
static int ThreadX_update_threads(struct rtos *rtos)
{
int retval;
@@ -324,8 +441,18 @@
LOG_ERROR("Error reading stack frame from ThreadX thread");
return retval;
}
+
+ LOG_INFO("thread: 0x%llx, stack_ptr=0x%llx", (uint64_t)thread_id,
(uint64_t)stack_ptr);
+
+ if (stack_ptr == 0) {
+ LOG_ERROR("null stack pointer in thread");
+ return -5;
+ }
+
+ const struct rtos_register_stacking *stacking_info =
+ get_stacking_info(rtos, stack_ptr);
- return rtos_generic_stack_read(rtos->target, param->stacking_info,
stack_ptr, hex_reg_list);
+ return rtos_generic_stack_read(rtos->target, stacking_info, stack_ptr,
hex_reg_list);
}
static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list[])
------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel