RTOS Thread awareness support wip
authorBroadcom Corporation (Evan Hunter) <ehunter@broadcom.com>
Thu, 14 Apr 2011 08:25:01 +0000 (10:25 +0200)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Fri, 15 Apr 2011 06:24:18 +0000 (08:24 +0200)
- works on Cortex-M3 with ThreadX and FreeRTOS

Compared to original patch a few nits were fixed:

- remove stricmp usage
- unsigned compare fix
- printf formatting fixes
- fixed a bug with overrunning a memory buffer allocated with malloc.

13 files changed:
configure.in
src/Makefile.am
src/rtos/FreeRTOS.c [new file with mode: 0644]
src/rtos/Makefile.am [new file with mode: 0644]
src/rtos/ThreadX.c [new file with mode: 0644]
src/rtos/rtos.c [new file with mode: 0644]
src/rtos/rtos.h [new file with mode: 0644]
src/rtos/rtos_standard_stackings.c [new file with mode: 0644]
src/rtos/rtos_standard_stackings.h [new file with mode: 0644]
src/server/gdb_server.c
src/server/gdb_server.h
src/target/target.c
src/target/target.h

index a73354f9acfd05ba4bcca31e2d72d396d6ed5390..8315a18d229935b6af2b774d3b792a5bf7c75bdf 100644 (file)
@@ -1170,6 +1170,7 @@ AC_OUTPUT(dnl
     src/xsvf/Makefile dnl
     src/svf/Makefile dnl
     src/target/Makefile dnl
     src/xsvf/Makefile dnl
     src/svf/Makefile dnl
     src/target/Makefile dnl
+    src/rtos/Makefile dnl
     src/server/Makefile dnl
     src/flash/Makefile dnl
     src/flash/nor/Makefile dnl
     src/server/Makefile dnl
     src/flash/Makefile dnl
     src/flash/nor/Makefile dnl
index 77449862dadc8547a91075877080131aaeaa08a4..3d7b05f6a3c8e75ddb933ade5e87e8f6dbce4543 100644 (file)
@@ -8,7 +8,8 @@ SUBDIRS = \
        svf \
        xsvf \
        pld \
        svf \
        xsvf \
        pld \
-       server
+       server \
+       rtos
 
 lib_LTLIBRARIES = libopenocd.la
 bin_PROGRAMS = openocd
 
 lib_LTLIBRARIES = libopenocd.la
 bin_PROGRAMS = openocd
@@ -100,6 +101,7 @@ libopenocd_la_LIBADD = \
        $(top_builddir)/src/flash/libflash.la \
        $(top_builddir)/src/target/libtarget.la \
        $(top_builddir)/src/server/libserver.la \
        $(top_builddir)/src/flash/libflash.la \
        $(top_builddir)/src/target/libtarget.la \
        $(top_builddir)/src/server/libserver.la \
+       $(top_builddir)/src/rtos/librtos.la \
        $(top_builddir)/src/helper/libhelper.la \
        $(FTDI2232LIB) $(MINGWLDADD) $(LIBUSB)
 
        $(top_builddir)/src/helper/libhelper.la \
        $(FTDI2232LIB) $(MINGWLDADD) $(LIBUSB)
 
diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c
new file mode 100644 (file)
index 0000000..0007416
--- /dev/null
@@ -0,0 +1,481 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/time_support.h>
+#include <jtag/jtag.h>
+#include "target/target.h"
+#include "target/target_type.h"
+#include "rtos.h"
+#include "helper/log.h"
+#include "rtos_standard_stackings.h"
+
+#define FreeRTOS_STRUCT( int_type, ptr_type, list_prev_offset )
+
+
+struct FreeRTOS_params
+{
+       const char *                         target_name;
+       const unsigned char                  thread_count_width;
+       const unsigned char                  pointer_width;
+       const unsigned char                  list_next_offset;
+       const unsigned char                  list_width;
+       const unsigned char                  list_elem_next_offset;
+       const unsigned char                  list_elem_content_offset;
+       const unsigned char                  thread_stack_offset;
+       const unsigned char                  thread_name_offset;
+       const struct rtos_register_stacking* stacking_info;
+};
+
+
+
+
+const struct FreeRTOS_params FreeRTOS_params_list[] =
+{
+               { "cortex_m3",                      // target_name
+          4,                                // thread_count_width;
+          4,                                // pointer_width;
+          16,                               // list_next_offset;
+          20,                               // list_width;
+          8,                                // list_elem_next_offset;
+          12,                               // list_elem_content_offset
+          0,                                // thread_stack_offset;
+          52,                               // thread_name_offset;
+          &rtos_standard_Cortex_M3_stacking, // stacking_info
+               }
+
+};
+
+
+#define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
+
+static int FreeRTOS_detect_rtos( struct target* target );
+static int FreeRTOS_create( struct target* target );
+static int FreeRTOS_update_threads( struct rtos *rtos );
+static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, long long thread_id, char ** hex_reg_list );
+static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[]);
+
+
+
+
+struct rtos_type FreeRTOS_rtos =
+{
+       .name                       = "FreeRTOS",
+
+       .detect_rtos                = FreeRTOS_detect_rtos,
+       .create                     = FreeRTOS_create,
+       .update_threads            = FreeRTOS_update_threads,
+       .get_thread_reg_list        = FreeRTOS_get_thread_reg_list,
+       .get_symbol_list_to_lookup  = FreeRTOS_get_symbol_list_to_lookup,
+};
+
+enum FreeRTOS_symbol_values
+{
+       FreeRTOS_VAL_pxCurrentTCB              = 0,
+       FreeRTOS_VAL_pxReadyTasksLists         = 1,
+       FreeRTOS_VAL_xDelayedTaskList1         = 2,
+       FreeRTOS_VAL_xDelayedTaskList2         = 3,
+       FreeRTOS_VAL_pxDelayedTaskList         = 4,
+       FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
+       FreeRTOS_VAL_xPendingReadyList         = 6,
+       FreeRTOS_VAL_xTasksWaitingTermination  = 7,
+       FreeRTOS_VAL_xSuspendedTaskList        = 8,
+       FreeRTOS_VAL_uxCurrentNumberOfTasks    = 9,
+};
+
+static char* FreeRTOS_symbol_list[] =
+{
+               "pxCurrentTCB",
+               "pxReadyTasksLists",
+               "xDelayedTaskList1",
+               "xDelayedTaskList2",
+               "pxDelayedTaskList",
+               "pxOverflowDelayedTaskList",
+               "xPendingReadyList",
+               "xTasksWaitingTermination",
+               "xSuspendedTaskList",
+               "uxCurrentNumberOfTasks",
+               NULL
+};
+
+#define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char*))
+
+// TODO:
+// this is not safe for little endian yet
+// may be problems reading if sizes are not 32 bit long integers.
+// test mallocs for failure
+
+static int FreeRTOS_update_threads( struct rtos *rtos )
+{
+       int i = 0;
+       int retval;
+       int tasks_found = 0;
+       const struct FreeRTOS_params* param;
+
+       if (rtos->rtos_specific_params == NULL )
+       {
+               return -1;
+       }
+
+       param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
+
+       if ( rtos->symbols == NULL )
+       {
+               LOG_OUTPUT("No symbols for FreeRTOS\r\n");
+               return -3;
+       }
+
+       if ( rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0 )
+       {
+               LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
+               return -2;
+       }
+
+       int thread_list_size = 0;
+       retval = target_read_buffer( rtos->target, rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address, param->thread_count_width, (uint8_t *)&thread_list_size);
+
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
+               return retval;
+       }
+
+
+       // wipe out previous thread details if any
+       if ( rtos->thread_details != NULL )
+       {
+               int j;
+               for( j = 0; j < rtos->thread_count; j++ )
+               {
+                       if ( rtos->thread_details[j].display_str != NULL )
+                       {
+                               free( rtos->thread_details[j].display_str );
+                               rtos->thread_details[j].display_str = NULL;
+                       }
+                       if ( rtos->thread_details[j].thread_name_str != NULL )
+                       {
+                               free( rtos->thread_details[j].thread_name_str );
+                               rtos->thread_details[j].thread_name_str = NULL;
+                       }
+                       if ( rtos->thread_details[j].extra_info_str != NULL )
+                       {
+                               free( rtos->thread_details[j].extra_info_str );
+                               rtos->thread_details[j].extra_info_str = NULL;
+                       }
+               }
+               free( rtos->thread_details );
+               rtos->thread_details = NULL;
+       }
+
+
+       // read the current thread
+       retval = target_read_buffer( rtos->target, rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address, param->pointer_width, (uint8_t *)&rtos->current_thread );
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
+               return retval;
+       }
+
+       if ( ( thread_list_size  == 0 ) || ( rtos->current_thread == 0 ) )
+       {
+               // Either : No RTOS threads - there is always at least the current execution though
+               // OR     : No current thread - all threads suspended - show the current execution of idling
+               char tmp_str[] = "Current Execution";
+               thread_list_size++;
+               tasks_found++;
+               rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
+               rtos->thread_details->threadid = 1;
+               rtos->thread_details->exists = true;
+               rtos->thread_details->display_str = NULL;
+               rtos->thread_details->extra_info_str = NULL;
+               rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
+               strcpy( rtos->thread_details->thread_name_str, tmp_str );
+
+
+               if ( thread_list_size == 1 )
+               {
+                       rtos->thread_count = 1;
+                       return ERROR_OK;
+               }
+       }
+       else
+       {
+               // create space for new thread details
+               rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
+       }
+
+
+       // Unfortunately, we can't know how many lists there are for pxReadyTasksLists,
+       // So figure it out via other variables
+       int num_ready_task_lists = (rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address - rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address) / param->list_width;
+
+
+       symbol_address_t* list_of_lists = (symbol_address_t *)malloc( sizeof( symbol_address_t ) * ( num_ready_task_lists + 5 ) );
+
+       int num_lists;
+       for( num_lists = 0; num_lists < num_ready_task_lists; num_lists++ )
+       {
+               list_of_lists[num_lists] =  rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address + num_lists * param->list_width;
+       }
+
+       list_of_lists[num_lists++] =  rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address;
+       list_of_lists[num_lists++] =  rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address;
+       list_of_lists[num_lists++] =  rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address;
+       list_of_lists[num_lists++] =  rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
+
+
+       for( i = 0; i < num_lists; i++ )
+       {
+               if ( list_of_lists[i] == 0 )
+               {
+                       continue;
+               }
+
+               // Read the number of threads in this list
+               long long list_thread_count = 0;
+               retval = target_read_buffer( rtos->target, list_of_lists[i], param->thread_count_width, (uint8_t *)&list_thread_count);
+               if ( retval != ERROR_OK )
+               {
+                       LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
+                       return retval;
+               }
+
+               if ( list_thread_count == 0 )
+               {
+                       continue;
+               }
+
+               // Read the location of first list item
+               unsigned long long prev_list_elem_ptr = -1;
+               unsigned long long list_elem_ptr = 0;
+               retval = target_read_buffer( rtos->target, list_of_lists[i] + param->list_next_offset, param->pointer_width, (uint8_t *)&list_elem_ptr);
+               if ( retval != ERROR_OK )
+               {
+                       LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
+                       return retval;
+               }
+
+
+               while ( (list_thread_count > 0) && ( list_elem_ptr != 0) && ( list_elem_ptr != prev_list_elem_ptr ) && ( tasks_found < thread_list_size ) )
+               {
+                       // Get the location of the thread structure.
+                       rtos->thread_details[tasks_found].threadid = 0;
+                       retval = target_read_buffer( rtos->target, list_elem_ptr + param->list_elem_content_offset, param->pointer_width, (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
+                       if ( retval != ERROR_OK )
+                       {
+                               LOG_OUTPUT("Error reading thread list item object in FreeRTOS thread list\r\n");
+                               return retval;
+                       }
+
+
+                       // get thread name
+
+                       #define FREERTOS_THREAD_NAME_STR_SIZE (200)
+                       char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
+
+                       // Read the thread name
+                       retval = target_read_buffer( rtos->target, rtos->thread_details[tasks_found].threadid + param->thread_name_offset, FREERTOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
+                       if ( retval != ERROR_OK )
+                       {
+                               LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
+                               return retval;
+                       }
+                       tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
+
+                       if ( tmp_str[0] == '\x00' )
+                       {
+                               strcpy(tmp_str,"No Name");
+                       }
+
+                       rtos->thread_details[tasks_found].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
+                       strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_str );
+                       rtos->thread_details[tasks_found].display_str = NULL;
+                       rtos->thread_details[tasks_found].exists = true;
+
+                       if ( rtos->thread_details[tasks_found].threadid == rtos->current_thread )
+                       {
+                               char running_str[] = "Running";
+                               rtos->thread_details[tasks_found].extra_info_str = (char*) malloc( sizeof(running_str) );
+                               strcpy( rtos->thread_details[tasks_found].extra_info_str, running_str );
+                       }
+                       else
+                       {
+                               rtos->thread_details[tasks_found].extra_info_str = NULL;
+                       }
+
+
+                       tasks_found++;
+                       list_thread_count--;
+
+                       prev_list_elem_ptr = list_elem_ptr;
+                       list_elem_ptr = 0;
+                       retval = target_read_buffer( rtos->target, prev_list_elem_ptr + param->list_elem_next_offset, param->pointer_width, (uint8_t *)&list_elem_ptr);
+                       if ( retval != ERROR_OK )
+                       {
+                               LOG_OUTPUT("Error reading next thread item location in FreeRTOS thread list\r\n");
+                               return retval;
+                       }
+               }
+
+
+       }
+       free( list_of_lists );
+       rtos->thread_count = tasks_found;
+       return 0;
+}
+
+static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, long long thread_id, char ** hex_reg_list )
+{
+       int retval;
+       const struct FreeRTOS_params* param;
+       long long stack_ptr = 0;
+
+
+       *hex_reg_list = NULL;
+       if ( rtos == NULL )
+       {
+               return -1;
+       }
+
+       if ( thread_id == 0 )
+       {
+               return -2;
+       }
+
+       if (rtos->rtos_specific_params == NULL )
+       {
+               return -1;
+       }
+
+       param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
+
+       // Read the stack pointer
+       retval = target_read_buffer( rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
+               return retval;
+       }
+
+       return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
+
+}
+
+static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[])
+{
+       unsigned int i;
+       *symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * FREERTOS_NUM_SYMBOLS );
+
+       for( i = 0; i < FREERTOS_NUM_SYMBOLS; i++ )
+       {
+               (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
+       }
+
+       return 0;
+}
+
+#if 0
+
+static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
+{
+       return 0;
+}
+
+
+
+static int FreeRTOS_get_thread_ascii_info( struct rtos*   rtos, threadid_t   thread_id, char ** info )
+{
+       int retval;
+       const struct FreeRTOS_params* param;
+
+       if ( rtos == NULL )
+       {
+               return -1;
+       }
+
+       if ( thread_id == 0 )
+       {
+               return -2;
+       }
+
+       if (rtos->rtos_specific_params == NULL )
+       {
+               return -3;
+       }
+
+       param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
+
+#define FREERTOS_THREAD_NAME_STR_SIZE (200)
+       char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
+
+       // Read the thread name
+       retval = target_read_buffer( rtos->target, thread_id + param->thread_name_offset, FREERTOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
+               return retval;
+       }
+       tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
+
+       if ( tmp_str[0] == '\x00' )
+       {
+               strcpy(tmp_str,"No Name");
+       }
+
+       *info = (char*)malloc( strlen(tmp_str)+1 );
+       strcpy( *info, tmp_str );
+       return 0;
+}
+
+#endif
+
+static int FreeRTOS_detect_rtos( struct target* target )
+{
+       if ( ( target->rtos->symbols != NULL ) &&
+                ( target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0 ) )
+       {
+               // looks like FreeRTOS
+               return 1;
+       }
+       return 0;
+       return 0;
+}
+
+
+static int FreeRTOS_create( struct target* target )
+{
+       int i = 0;
+       while ( ( i < FREERTOS_NUM_PARAMS ) && ( 0 != strcmp( FreeRTOS_params_list[i].target_name, target->type->name ) ) )
+       {
+               i++;
+       }
+       if ( i >= FREERTOS_NUM_PARAMS )
+       {
+               LOG_OUTPUT("Could not find target in FreeRTOS compatability list\r\n");
+               return -1;
+       }
+
+       target->rtos->rtos_specific_params = (void*) &FreeRTOS_params_list[i];
+       return 0;
+}
diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
new file mode 100644 (file)
index 0000000..12368d2
--- /dev/null
@@ -0,0 +1,35 @@
+# ***************************************************************************
+# *   Copyright (C) 2011 by Broadcom Corporation                            *
+# *   Evan Hunter - ehunter@broadcom.com                                    *
+# *                                                                         *
+# *   This program is free software; you can redistribute it and/or modify  *
+# *   it under the terms of the GNU General Public License as published by  *
+# *   the Free Software Foundation; either version 2 of the License, or     *
+# *   (at your option) any later version.                                   *
+# *                                                                         *
+# *   This program is distributed in the hope that it will be useful,       *
+# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+# *   GNU General Public License for more details.                          *
+# *                                                                         *
+# *   You should have received a copy of the GNU General Public License     *
+# *   along with this program; if not, write to the                         *
+# *   Free Software Foundation, Inc.,                                       *
+# *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+# ***************************************************************************
+
+include $(top_srcdir)/common.mk
+
+METASOURCES = AUTO
+noinst_LTLIBRARIES = librtos.la
+noinst_HEADERS = rtos.h
+librtos_la_SOURCES = rtos.c rtos_standard_stackings.c FreeRTOS.c ThreadX.c
+
+
+librtos_la_CFLAGS =
+if IS_MINGW
+# FD_* macros are sloppy with their signs on MinGW32 platform
+librtos_la_CFLAGS += -Wno-sign-compare
+endif
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/rtos/ThreadX.c b/src/rtos/ThreadX.c
new file mode 100644 (file)
index 0000000..da84111
--- /dev/null
@@ -0,0 +1,536 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/time_support.h>
+#include <jtag/jtag.h>
+#include "target/target.h"
+#include "target/target_type.h"
+#include "rtos.h"
+#include "helper/log.h"
+#include "rtos_standard_stackings.h"
+
+
+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, long long 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;
+};
+
+
+struct ThreadX_thread_state ThreadX_thread_states[] =
+{
+    { 0,  "Ready" },
+    { 1,  "Completed" },
+    { 2,  "Terminated" },
+    { 3,  "Suspended" },
+    { 4,  "Sleeping" },
+    { 5,  "Waiting - Queue" },
+    { 6,  "Waiting - Semaphore" },
+    { 7,  "Waiting - Event flag" },
+    { 8,  "Waiting - Memory" },
+    { 9,  "Waiting - Memory" },
+    { 10, "Waiting - I/O" },
+    { 11, "Waiting - Filesystem" },
+    { 12, "Waiting - Network" },
+    { 13, "Waiting - Mutex" },
+};
+
+
+#define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
+
+
+struct ThreadX_params
+{
+       char *                               target_name;
+       unsigned char                        pointer_width;
+       unsigned char                        thread_stack_offset;
+       unsigned char                        thread_name_offset;
+       unsigned char                        thread_state_offset;
+       unsigned char                        thread_next_offset;
+       const struct rtos_register_stacking* stacking_info;
+};
+
+const struct ThreadX_params ThreadX_params_list[] =
+{
+               { "cortex_m3",                       // target_name
+          4,                                 // pointer_width;
+          8,                                 // thread_stack_offset;
+          40,                                // thread_name_offset;
+          48,                                // thread_state_offset;
+          136,                               // thread_next_offset
+          &rtos_standard_Cortex_M3_stacking, // stacking_info
+               }
+
+};
+
+#define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
+
+enum ThreadX_symbol_values
+{
+       ThreadX_VAL_tx_thread_current_ptr     = 0,
+       ThreadX_VAL_tx_thread_created_ptr     = 1,
+       ThreadX_VAL_tx_thread_created_count   = 2,
+};
+
+static char* ThreadX_symbol_list[] =
+{
+               "_tx_thread_current_ptr",
+               "_tx_thread_created_ptr",
+               "_tx_thread_created_count",
+               NULL
+};
+
+
+
+#define THREADX_NUM_SYMBOLS (sizeof(ThreadX_symbol_list)/sizeof(char*))
+
+
+const struct rtos_type ThreadX_rtos =
+{
+       .name                      = "ThreadX",
+
+       .detect_rtos               = ThreadX_detect_rtos,
+       .create                    = ThreadX_create,
+       .update_threads            = ThreadX_update_threads,
+       .get_thread_reg_list       = ThreadX_get_thread_reg_list,
+       .get_symbol_list_to_lookup = ThreadX_get_symbol_list_to_lookup,
+
+};
+
+static int ThreadX_update_threads( struct rtos* rtos)
+{
+       int retval;
+       int tasks_found = 0;
+       int thread_list_size = 0;
+       const struct ThreadX_params* param;
+
+       if ( rtos == NULL )
+       {
+               return -1;
+       }
+
+       if (rtos->rtos_specific_params == NULL )
+       {
+               return -3;
+       }
+
+       param = (const struct ThreadX_params*) rtos->rtos_specific_params;
+
+       if ( rtos->symbols == NULL )
+       {
+               LOG_OUTPUT("No symbols for ThreadX\r\n");
+               return -4;
+       }
+
+       if ( rtos->symbols[ThreadX_VAL_tx_thread_created_count].address == 0 )
+       {
+               LOG_OUTPUT("Don't have the number of threads in ThreadX \r\n");
+               return -2;
+       }
+
+
+
+
+
+       // read the number of threads
+       retval = target_read_buffer( rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_created_count].address, 4, (uint8_t *)&thread_list_size);
+
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Could not read ThreadX thread count from target\r\n");
+               return retval;
+       }
+
+
+       // wipe out previous thread details if any
+       if ( rtos->thread_details != NULL )
+       {
+               int j;
+               for( j = 0; j < rtos->thread_count; j++ )
+               {
+                       if ( rtos->thread_details[j].display_str != NULL )
+                       {
+                               free( rtos->thread_details[j].display_str );
+                               rtos->thread_details[j].display_str = NULL;
+                       }
+                       if ( rtos->thread_details[j].thread_name_str != NULL )
+                       {
+                               free( rtos->thread_details[j].thread_name_str );
+                               rtos->thread_details[j].thread_name_str = NULL;
+                       }
+                       if ( rtos->thread_details[j].extra_info_str != NULL )
+                       {
+                               free( rtos->thread_details[j].extra_info_str );
+                               rtos->thread_details[j].extra_info_str = NULL;
+                       }
+               }
+               free( rtos->thread_details );
+               rtos->thread_details = NULL;
+       }
+
+
+       // read the current thread id
+       retval = target_read_buffer( rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_current_ptr].address, 4, (uint8_t *)&rtos->current_thread);
+
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Could not read ThreadX current thread from target\r\n");
+               return retval;
+       }
+
+       if ( ( thread_list_size  == 0 ) || ( rtos->current_thread == 0 ) )
+       {
+               // Either : No RTOS threads - there is always at least the current execution though
+               // OR     : No current thread - all threads suspended - show the current execution of idling
+               char tmp_str[] = "Current Execution";
+               thread_list_size++;
+               tasks_found++;
+               rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
+               rtos->thread_details->threadid = 1;
+               rtos->thread_details->exists = true;
+               rtos->thread_details->display_str = NULL;
+               rtos->thread_details->extra_info_str = NULL;
+               rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
+               strcpy( rtos->thread_details->thread_name_str, tmp_str );
+
+
+               if ( thread_list_size == 0 )
+               {
+                       rtos->thread_count = 1;
+                       return ERROR_OK;
+               }
+       }
+       else
+       {
+               // create space for new thread details
+               rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
+       }
+
+
+
+       // Read the pointer to the first thread
+       long long thread_ptr = 0;
+       retval = target_read_buffer( rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address, param->pointer_width, (uint8_t *)&thread_ptr);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Could not read ThreadX thread location from target\r\n");
+               return retval;
+       }
+
+
+       // loop over all threads
+       long long prev_thread_ptr = 0;
+       while ( ( thread_ptr != prev_thread_ptr ) && ( tasks_found < thread_list_size ) )
+       {
+
+               #define THREADX_THREAD_NAME_STR_SIZE (200)
+           char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
+               unsigned int i = 0;
+               long long name_ptr = 0;
+
+               // Save the thread pointer
+               rtos->thread_details[tasks_found].threadid = thread_ptr;
+
+
+               // read the name pointer
+               retval = target_read_buffer( rtos->target, thread_ptr + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
+               if ( retval != ERROR_OK )
+               {
+                       LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
+                       return retval;
+               }
+
+               // Read the thread name
+               retval = target_read_buffer( rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
+               if ( retval != ERROR_OK )
+               {
+                       LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
+                       return retval;
+               }
+               tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
+
+               if ( tmp_str[0] == '\x00' )
+               {
+                       strcpy(tmp_str,"No Name");
+               }
+
+
+               rtos->thread_details[tasks_found].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
+               strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_str );
+
+
+
+               // Read the thread status
+               long long thread_status = 0;
+               retval = target_read_buffer( rtos->target, thread_ptr + param->thread_state_offset, 4, (uint8_t *)&thread_status);
+               if ( retval != ERROR_OK )
+               {
+                       LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
+                       return retval;
+               }
+
+               for( i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value!=thread_status); i++ )
+               {
+               }
+
+
+               char * state_desc;
+               if  (i < THREADX_NUM_STATES)
+               {
+                       state_desc = ThreadX_thread_states[i].desc;
+               }
+               else
+               {
+                       state_desc = "Unknown state";
+               }
+
+               rtos->thread_details[tasks_found].extra_info_str = (char*)malloc( strlen(state_desc)+1 );
+               strcpy( rtos->thread_details[tasks_found].extra_info_str, state_desc );
+
+               rtos->thread_details[tasks_found].exists = true;
+
+               rtos->thread_details[tasks_found].display_str = NULL;
+
+
+
+
+
+               tasks_found++;
+               prev_thread_ptr = thread_ptr;
+
+               // Get the location of the next thread structure.
+               thread_ptr = 0;
+               retval = target_read_buffer( rtos->target, prev_thread_ptr + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_ptr );
+               if ( retval != ERROR_OK )
+               {
+                       LOG_OUTPUT("Error reading next thread pointer in ThreadX thread list\r\n");
+                       return retval;
+               }
+
+       }
+
+       rtos->thread_count = tasks_found;
+
+       return 0;
+}
+
+static int ThreadX_get_thread_reg_list(struct rtos *rtos, long long thread_id, char ** hex_reg_list )
+{
+
+       int retval;
+       const struct ThreadX_params* param;
+
+       *hex_reg_list = NULL;
+
+       if ( rtos == NULL )
+       {
+               return -1;
+       }
+
+       if ( thread_id == 0 )
+       {
+               return -2;
+       }
+
+       if (rtos->rtos_specific_params == NULL )
+       {
+               return -3;
+       }
+
+       param = (const struct ThreadX_params*) rtos->rtos_specific_params;
+
+       // Read the stack pointer
+       long long stack_ptr = 0;
+       retval = target_read_buffer( rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Error reading stack frame from ThreadX thread\r\n");
+               return retval;
+       }
+
+       return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
+}
+
+
+
+static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[])
+{
+       unsigned int i;
+       *symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * THREADX_NUM_SYMBOLS );
+
+       for( i = 0; i < THREADX_NUM_SYMBOLS; i++ )
+       {
+               (*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
+       }
+
+       return 0;
+}
+
+static int ThreadX_detect_rtos( struct target* target )
+{
+       if ( ( target->rtos->symbols != NULL ) &&
+                ( target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0 ) )
+       {
+               // looks like ThreadX
+               return 1;
+       }
+       return 0;
+}
+
+
+
+#if 0
+
+static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
+{
+       return 0;
+}
+
+
+
+static int ThreadX_get_thread_detail( struct rtos*   rtos, threadid_t   thread_id, struct thread_detail* detail )
+{
+       unsigned int i = 0;
+       int retval;
+
+#define THREADX_THREAD_NAME_STR_SIZE (200)
+       char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
+
+       const struct ThreadX_params* param;
+
+       if ( rtos == NULL )
+       {
+               return -1;
+       }
+
+       if ( thread_id == 0 )
+       {
+               return -2;
+       }
+
+       if (rtos->rtos_specific_params == NULL )
+       {
+               return -3;
+       }
+
+       param = (const struct ThreadX_params*) rtos->rtos_specific_params;
+
+       if ( rtos->symbols == NULL )
+       {
+               LOG_OUTPUT("No symbols for ThreadX\r\n");
+               return -3;
+       }
+
+       detail->threadid = thread_id;
+
+       long long name_ptr = 0;
+       // read the name pointer
+       retval = target_read_buffer( rtos->target, thread_id + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
+               return retval;
+       }
+
+       // Read the thread name
+       retval = target_read_buffer( rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
+               return retval;
+       }
+       tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
+
+       if ( tmp_str[0] == '\x00' )
+       {
+               strcpy(tmp_str,"No Name");
+       }
+
+       detail->thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
+
+
+       // Read the thread status
+       long long thread_status = 0;
+       retval = target_read_buffer( rtos->target, thread_id + param->thread_state_offset, 4, (uint8_t *)&thread_status);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
+               return retval;
+       }
+
+       for( i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value!=thread_status); i++ )
+       {
+       }
+
+
+       char * state_desc;
+       if  (i < THREADX_NUM_STATES)
+       {
+               state_desc = ThreadX_thread_states[i].desc;
+       }
+       else
+       {
+               state_desc = "Unknown state";
+       }
+
+       detail->extra_info_str = (char*)malloc( strlen(state_desc)+1 );
+
+       detail->exists = true;
+
+       detail->display_str = NULL;
+
+
+
+
+       return 0;
+}
+
+#endif
+
+static int ThreadX_create( struct target* target )
+{
+       int i = 0;
+       while ( ( i < THREADX_NUM_PARAMS ) && ( 0 != strcmp( ThreadX_params_list[i].target_name, target->type->name ) ) )
+       {
+               i++;
+       }
+       if ( i >= THREADX_NUM_PARAMS )
+       {
+               LOG_OUTPUT("Could not find target in ThreadX compatability list\r\n");
+               return -1;
+       }
+
+       target->rtos->rtos_specific_params = (void*) &ThreadX_params_list[i];
+       target->rtos->current_thread = 0;
+       target->rtos->thread_details = NULL;
+       return 0;
+}
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
new file mode 100644 (file)
index 0000000..129770e
--- /dev/null
@@ -0,0 +1,657 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "rtos.h"
+#include "target/target.h"
+#include "helper/log.h"
+#include "server/gdb_server.h"
+
+
+static long long current_threadid = -1;
+
+static void hex_to_str( char* dst, char * hex_src );
+static int str_to_hex( char* hex_dst, char* src );
+
+
+/* RTOSs */
+extern struct rtos_type FreeRTOS_rtos;
+extern struct rtos_type ThreadX_rtos;
+
+static struct rtos_type *rtos_types[] =
+{
+       &ThreadX_rtos,
+       &FreeRTOS_rtos,
+       NULL
+};
+
+
+int rtos_create(Jim_GetOptInfo *goi, struct target * target)
+{
+       int x;
+       char *cp;
+
+       if (! goi->isconfigure) {
+               if (goi->argc != 0) {
+                       if (goi->argc != 0) {
+                               Jim_WrongNumArgs(goi->interp,
+                                               goi->argc, goi->argv,
+                                               "NO PARAMS");
+                               return JIM_ERR;
+                       }
+
+                       Jim_SetResultString(goi->interp,
+                                       target_type_name(target), -1);
+               }
+       }
+
+       if (target->rtos) {
+               free((void *)(target->rtos));
+       }
+//                     e = Jim_GetOpt_String(goi, &cp, NULL);
+//                     target->rtos = strdup(cp);
+
+       Jim_GetOpt_String(goi, &cp, NULL);
+       /* now does target type exist */
+
+       if ( 0 == strcmp( cp, "auto") )
+       {
+               // auto detection of RTOS
+               target->rtos_auto_detect = true;
+               x = 0;
+       }
+       else
+       {
+
+               for (x = 0 ; rtos_types[x] ; x++) {
+                       if (0 == strcmp(cp, rtos_types[x]->name)) {
+                               /* found */
+                               break;
+                       }
+               }
+               if (rtos_types[x] == NULL) {
+                       Jim_SetResultFormatted(goi->interp, "Unknown rtos type %s, try one of ", cp);
+                       for (x = 0 ; rtos_types[x] ; x++) {
+                               if (rtos_types[x + 1]) {
+                                       Jim_AppendStrings(goi->interp,
+                                                                          Jim_GetResult(goi->interp),
+                                                                          rtos_types[x]->name,
+                                                                          ", ", NULL);
+                               } else {
+                                       Jim_AppendStrings(goi->interp,
+                                                                          Jim_GetResult(goi->interp),
+                                                                          " or ",
+                                                                          rtos_types[x]->name,NULL);
+                               }
+                       }
+                       return JIM_ERR;
+               }
+       }
+       /* Create it */
+       target->rtos = calloc(1,sizeof(struct rtos));
+       target->rtos->type = rtos_types[x];
+       target->rtos->current_thread = 0;
+       target->rtos->symbols = NULL;
+       target->rtos->target = target;
+
+       if ( 0 != strcmp( cp, "auto") )
+       {
+               target->rtos->type->create( target );
+       }
+
+       return JIM_OK;
+}
+
+
+
+
+int gdb_thread_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
+{
+       if (strstr(packet, "qP"))
+       {
+               #define TAG_THREADID 1          /* Echo the thread identifier */
+               #define TAG_EXISTS 2            /* Is this process defined enough to
+                                                  fetch registers and its stack */
+               #define TAG_DISPLAY 4           /* A short thing maybe to put on a window */
+               #define TAG_THREADNAME 8        /* string, maps 1-to-1 with a thread is */
+               #define TAG_MOREDISPLAY 16      /* Whatever the kernel wants to say about */
+
+                       // TODO: need to scanf the mode variable (or it with the tags), and the threadid
+
+               unsigned long mode;
+               threadid_t threadid = 0;
+               struct thread_detail* detail;
+               sscanf(packet, "qP%8lx%16" SCNx64, &mode, &threadid);
+
+
+               int found = -1;
+
+               if ((target->rtos != NULL) && (target->rtos->thread_details
+                               != NULL)) {
+                       int thread_num;
+                       for (thread_num = 0; thread_num
+                                       < target->rtos->thread_count; thread_num++) {
+                               if (target->rtos->thread_details[thread_num].threadid
+                                               == threadid) {
+                                       if (target->rtos->thread_details[thread_num].exists) {
+                                               found = thread_num;
+                                       }
+                               }
+                       }
+               }
+               if (found == -1) {
+                       gdb_put_packet(connection, "E01", 3); // thread not found
+                       return ERROR_OK;
+               }
+
+               detail = &target->rtos->thread_details[found];
+
+               if ( detail->display_str != NULL )
+               {
+                       mode &= TAG_DISPLAY;
+               }
+               if ( detail->thread_name_str != NULL )
+               {
+                       mode &= TAG_THREADNAME;
+               }
+               if ( detail->extra_info_str != NULL )
+               {
+                       mode &= TAG_MOREDISPLAY;
+               }
+
+
+               mode &= TAG_THREADID | TAG_EXISTS;
+
+               char thread_str[1000];
+
+               sprintf(thread_str, "%08lx", mode);
+               sprintf(thread_str, "%016" PRIx64, threadid);
+
+
+               if (mode & TAG_THREADID) {
+                       sprintf(thread_str, "%08" PRIx32 "10%016" PRIx64, TAG_THREADID, threadid);
+               }
+               if (mode & TAG_EXISTS) {
+                       sprintf(thread_str, "%08" PRIx32 "08%08" PRIx32, TAG_EXISTS, (detail->exists==true)?1:0);
+               }
+               if (mode & TAG_DISPLAY) {
+                       sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_DISPLAY, (unsigned char)strlen(detail->display_str), detail->display_str );
+               }
+               if (mode & TAG_MOREDISPLAY) {
+                       sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_MOREDISPLAY, (unsigned char)strlen(detail->extra_info_str), detail->extra_info_str );
+               }
+               if (mode & TAG_THREADNAME) {
+                       sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_THREADNAME, (unsigned char)strlen(detail->thread_name_str), detail->thread_name_str );
+               }
+
+               //gdb_put_packet(connection, tmpstr, sizeof(tmpstr)-1);
+               gdb_put_packet(connection, thread_str, strlen(thread_str));
+
+               //                      gdb_put_packet(connection, "", 0);
+               //              gdb_put_packet(connection, "OK", 2); // all threads alive
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qThreadExtraInfo,"))
+       {
+               if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) && (target->rtos->thread_count != 0))
+               {
+                       threadid_t threadid = 0;
+                       int found = -1;
+                       sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid );
+
+                       if ((target->rtos != NULL) && (target->rtos->thread_details
+                                       != NULL)) {
+                               int thread_num;
+                               for (thread_num = 0; thread_num
+                                               < target->rtos->thread_count; thread_num++) {
+                                       if (target->rtos->thread_details[thread_num].threadid
+                                                       == threadid) {
+                                               if (target->rtos->thread_details[thread_num].exists) {
+                                                       found = thread_num;
+                                               }
+                                       }
+                               }
+                       }
+                       if (found == -1) {
+                               gdb_put_packet(connection, "E01", 3); // thread not found
+                               return ERROR_OK;
+                       }
+
+                       struct thread_detail* detail = &target->rtos->thread_details[found];
+
+                       int str_size = 0;
+                       if ( detail->display_str != NULL )
+                       {
+                               str_size += strlen(detail->display_str);
+                       }
+                       if ( detail->thread_name_str != NULL )
+                       {
+                               str_size += strlen(detail->thread_name_str);
+                       }
+                       if ( detail->extra_info_str != NULL )
+                       {
+                               str_size += strlen(detail->extra_info_str);
+                       }
+
+                       char * tmp_str = (char*) malloc( str_size + 7 );
+                       char*  tmp_str_ptr = tmp_str;
+
+                       if ( detail->display_str != NULL )
+                       {
+                               tmp_str_ptr += sprintf( tmp_str_ptr, "%s", detail->display_str );
+                       }
+                       if ( detail->thread_name_str != NULL )
+                       {
+                               if ( tmp_str_ptr != tmp_str )
+                               {
+                                       tmp_str_ptr += sprintf( tmp_str_ptr, " : " );
+                               }
+                               tmp_str_ptr += sprintf( tmp_str_ptr, "%s", detail->thread_name_str );
+                       }
+                       if ( detail->extra_info_str != NULL )
+                       {
+                               if ( tmp_str_ptr != tmp_str )
+                               {
+                                       tmp_str_ptr += sprintf( tmp_str_ptr, " : " );
+                               }
+                               tmp_str_ptr += sprintf( tmp_str_ptr, " : %s", detail->extra_info_str );
+                       }
+
+                       char * hex_str = (char*) malloc( strlen(tmp_str)*2 +1 );
+                       str_to_hex( hex_str, tmp_str );
+
+                       gdb_put_packet(connection, hex_str, strlen(hex_str));
+                       free(hex_str);
+                       free(tmp_str);
+                       return ERROR_OK;
+
+               }
+               gdb_put_packet(connection, "", 0);
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qSymbol"))
+       {
+               if ( target->rtos != NULL )
+               {
+                       int next_symbol_num = -1;
+                       if (target->rtos->symbols == NULL)
+                       {
+                               target->rtos->type->get_symbol_list_to_lookup( &target->rtos->symbols );
+                       }
+                       if (0 == strcmp( "qSymbol::", packet ) )
+                       {
+                               // first query -
+                               next_symbol_num = 0;
+                       }
+                       else
+                       {
+                               long long value = 0;
+                               char * hex_name_str = malloc( strlen(packet));
+                               char * name_str;
+                               int symbol_num;
+
+                               char* found = strstr( packet, "qSymbol::" );
+                               int numconv;
+                               if (0 == found )
+                               {
+                                       numconv =sscanf(packet, "qSymbol:%" SCNx64 ":%s", &value, hex_name_str);
+                               }
+                               else
+                               {
+                                       // No value returned by GDB - symbol was not found
+                                       numconv =sscanf(packet, "qSymbol::%s", hex_name_str);
+                               }
+                               name_str = (char*) malloc( 1+ strlen(hex_name_str) / 2 );
+
+                               hex_to_str( name_str, hex_name_str );
+
+
+                               symbol_num = 0;
+                               while ( ( target->rtos->symbols[ symbol_num ].symbol_name != NULL ) && ( 0 != strcmp( target->rtos->symbols[ symbol_num ].symbol_name, name_str ) ) )
+                               {
+                                       symbol_num++;
+                               }
+
+
+                               if ( target->rtos->symbols[ symbol_num ].symbol_name == NULL )
+                               {
+                                       LOG_OUTPUT("ERROR: unknown symbol\r\n");
+                                       gdb_put_packet(connection, "OK", 2);
+                                       return ERROR_OK;
+                               }
+
+                               target->rtos->symbols[ symbol_num ].address = value;
+
+                               next_symbol_num = symbol_num+1;
+                               free( hex_name_str );
+                               free( name_str );
+
+                       }
+
+                       int symbols_done = 0;
+                       if ( target->rtos->symbols[ next_symbol_num ].symbol_name == NULL )
+                       {
+                               if ( ( target->rtos_auto_detect == false ) ||
+                                        ( 1 == target->rtos->type->detect_rtos( target ) ) )
+                               {
+                                       // Found correct RTOS or not autodetecting
+                                       if ( target->rtos_auto_detect == true )
+                                       {
+                                               LOG_OUTPUT( "Auto-detected RTOS: %s\r\n",target->rtos->type->name );
+                                       }
+                                       symbols_done = 1;
+                               }
+                               else
+                               {
+                                       // Auto detecting RTOS and currently not found
+                                       if( 1 != rtos_try_next( target ) )
+                                       {
+                                               // No more RTOS's to try
+                                               symbols_done = 1;
+                                       }
+                                       else
+                                       {
+                                               next_symbol_num = 0;
+                                               target->rtos->type->get_symbol_list_to_lookup( &target->rtos->symbols );
+                                       }
+
+                               }
+                       }
+
+
+                       if ( symbols_done == 1 )
+                       {
+                               target->rtos_auto_detect = false;
+                               target->rtos->type->create( target );
+                               target->rtos->type->update_threads(target->rtos);
+                               // No more symbols needed
+                               gdb_put_packet(connection, "OK", 2);
+                               return ERROR_OK;
+
+                       }
+                       else
+                       {
+                               char* symname = target->rtos->symbols[ next_symbol_num ].symbol_name;
+                               char qsymstr[] = "qSymbol:";
+                               char * opstring = (char*)malloc(sizeof(qsymstr)+strlen(symname)*2+1);
+                               char * posptr = opstring;
+                               posptr += sprintf( posptr, "%s", qsymstr );
+                               str_to_hex( posptr, symname );
+                               gdb_put_packet(connection, opstring, strlen(opstring));
+                               free(opstring);
+                               return ERROR_OK;
+                       }
+
+               }
+               gdb_put_packet(connection, "OK", 2);
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qfThreadInfo"))
+       {
+               int i;
+               if ( ( target->rtos != NULL ) && ( target->rtos->thread_count != 0 ) )
+               {
+
+                       char* out_str = (char*) malloc(17 * target->rtos->thread_count + 5);
+                       char* tmp_str = out_str;
+                       tmp_str += sprintf(tmp_str, "m");
+                       for (i = 0; i < target->rtos->thread_count; i++) {
+                               if (i != 0) {
+                                       tmp_str += sprintf(tmp_str, ",");
+                               }
+                               tmp_str += sprintf(tmp_str, "%016" PRIx64,
+                                               target->rtos->thread_details[i].threadid);
+                       }
+                       tmp_str[0] = 0;
+                       gdb_put_packet(connection, out_str, strlen(out_str));
+               }
+               else
+               {
+                       gdb_put_packet(connection, "", 0);
+               }
+
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qsThreadInfo"))
+       {
+               gdb_put_packet(connection, "l", 1);
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qAttached"))
+       {
+               gdb_put_packet(connection, "1", 1);
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qOffsets"))
+       {
+               char offsets[] = "Text=0;Data=0;Bss=0";
+               gdb_put_packet(connection, offsets, sizeof(offsets)-1);
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qC"))
+       {
+               gdb_put_packet(connection, "QC0", 3);
+               return ERROR_OK;
+       }
+       else if ( packet[0] == 'T' ) // Is thread alive?
+       {
+               threadid_t threadid;
+               int found = -1;
+               sscanf(packet, "T%" SCNx64, &threadid);
+               if ((target->rtos != NULL) && (target->rtos->thread_details
+                               != NULL)) {
+                       int thread_num;
+                       for (thread_num = 0; thread_num
+                                       < target->rtos->thread_count; thread_num++) {
+                               if (target->rtos->thread_details[thread_num].threadid
+                                               == threadid) {
+                                       if (target->rtos->thread_details[thread_num].exists) {
+                                               found = thread_num;
+                                       }
+                               }
+                       }
+               }
+               if (found != -1) {
+                       gdb_put_packet(connection, "OK", 2); // thread alive
+               } else {
+                       gdb_put_packet(connection, "E01", 3); // thread not found
+               }
+       }
+       else if ( packet[0] == 'H') // Set current thread ( 'c' for step and continue, 'g' for all other operations )
+       {
+               if (packet[1] == 'g')
+               {
+                       sscanf(packet, "Hg%16" SCNx64, &current_threadid);
+               }
+               gdb_put_packet(connection, "OK", 2);
+       }
+
+       return GDB_THREAD_PACKET_NOT_CONSUMED;
+}
+
+int rtos_get_gdb_reg_list(struct connection *connection, struct target *target, struct reg **reg_list[], int *reg_list_size)
+{
+       if ( ( target->rtos != NULL ) &&
+                ( current_threadid != 1 ) &&
+                ( current_threadid != 0 ) &&
+                ( current_threadid != target->rtos->current_thread ) )
+       {
+               char * hex_reg_list;
+               target->rtos->type->get_thread_reg_list( target->rtos, current_threadid, &hex_reg_list );
+
+               if ( hex_reg_list != NULL )
+               {
+                       gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
+                       free(hex_reg_list);
+                       return ERROR_OK;
+               }
+       }
+       return ERROR_FAIL;
+}
+
+
+
+int rtos_generic_stack_read( struct target * target, const struct rtos_register_stacking* stacking, long long stack_ptr, char ** hex_reg_list )
+{
+       int list_size = 0;
+       char * tmp_str_ptr;
+       long long new_stack_ptr;
+       int i;
+       int retval;
+
+       if ( stack_ptr == 0)
+       {
+               LOG_OUTPUT("Error: null stack pointer in thread\r\n");
+               return -5;
+       }
+       // Read the stack
+       uint8_t * stack_data = (uint8_t*) malloc( stacking->stack_registers_size );
+       uint32_t address = stack_ptr;
+
+       if ( stacking->stack_growth_direction == 1 )
+       {
+               address -=  stacking->stack_registers_size;
+       }
+       retval = target_read_buffer( target, stack_ptr, stacking->stack_registers_size, stack_data);
+       if ( retval != ERROR_OK )
+       {
+               LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
+               return retval;
+       }
+/*
+       LOG_OUTPUT("Stack Data :");
+       for(i = 0; i < stacking->stack_registers_size; i++ )
+       {
+               LOG_OUTPUT("%02X",stack_data[i]);
+       }
+       LOG_OUTPUT("\r\n");
+*/
+       for( i = 0; i < stacking->num_output_registers; i++ )
+       {
+               list_size += stacking->register_offsets[i].width_bits/8;
+       }
+       *hex_reg_list = (char*)malloc( list_size*2 +1 );
+       tmp_str_ptr = *hex_reg_list;
+       new_stack_ptr = stack_ptr + stacking->stack_growth_direction * stacking->stack_registers_size;
+       for( i = 0; i < stacking->num_output_registers; i++ )
+       {
+               int j;
+               for ( j = 0; j < stacking->register_offsets[i].width_bits/8; j++ )
+               {
+                       if ( stacking->register_offsets[i].offset == -1 )
+                       {
+                               tmp_str_ptr += sprintf( tmp_str_ptr, "%02x", 0 );
+                       }
+                       else if ( stacking->register_offsets[i].offset == -2 )
+                       {
+                               tmp_str_ptr += sprintf( tmp_str_ptr, "%02x", ((uint8_t*)&new_stack_ptr)[j] );
+                       }
+                       else
+                       {
+                               tmp_str_ptr += sprintf( tmp_str_ptr,"%02x", stack_data[ stacking->register_offsets[i].offset + j ] );
+                       }
+               }
+       }
+//     LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list);
+       return ERROR_OK;
+}
+
+int rtos_try_next( struct target * target )
+{
+       int x;
+
+       if ( target->rtos == NULL )
+       {
+               return -1;
+       }
+
+       for (x = 0 ; rtos_types[x] ; x++) {
+               if (target->rtos->type == rtos_types[x] ) {
+                       /* found */
+                       if ( rtos_types[x+1] != NULL )
+                       {
+                               target->rtos->type = rtos_types[x+1];
+                               if ( target->rtos->symbols != NULL )
+                               {
+                                       free( target->rtos->symbols );
+                               }
+                               return 1;
+                       }
+                       else
+                       {
+                               // No more rtos types
+                               return 0;
+                       }
+
+               }
+       }
+       return 0;
+
+}
+
+static void hex_to_str( char* dst, char * hex_src )
+{
+       int src_pos = 0;
+       int dst_pos = 0;
+
+       while ( hex_src[src_pos] != '\x00' )
+       {
+               char hex_char = hex_src[src_pos];
+               char hex_digit_val = (hex_char>='a')?hex_char-'a'+10:(hex_char>='A')?hex_char-'A'+10:hex_char-'0';
+               if ( 0 == (src_pos & 0x01) )
+               {
+                       dst[dst_pos] = hex_digit_val;
+                       dst[dst_pos+1] = 0;
+               }
+               else
+               {
+                       ((unsigned char*)dst)[dst_pos] <<= 4;
+                       ((unsigned char*)dst)[dst_pos] += hex_digit_val;
+                       dst_pos++;
+               }
+               src_pos++;
+       }
+
+}
+
+static int str_to_hex( char* hex_dst, char* src )
+{
+       char * posptr = hex_dst;
+       unsigned i;
+       for( i = 0; i < strlen(src); i++)
+       {
+               posptr += sprintf( posptr, "%02x", (unsigned char)src[i] );
+       }
+       return (posptr-hex_dst);
+}
+
+
+int rtos_update_threads( struct target* target )
+{
+       if ((target->rtos != NULL) && (target->rtos->type != NULL))
+       {
+               target->rtos->type->update_threads(target->rtos);
+       }
+       return ERROR_OK;
+}
diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h
new file mode 100644 (file)
index 0000000..cd4bbb2
--- /dev/null
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef RTOS_H
+#define RTOS_H
+
+
+#include "server/server.h"
+#include <helper/types.h>
+#include <jim-nvp.h>
+
+typedef long long threadid_t;
+typedef long long symbol_address_t;
+
+struct reg;
+
+/**
+ * Table should be terminated by an element with NULL in symbol_name
+ */
+typedef struct symbol_table_elem_struct
+{
+       char * symbol_name;
+       symbol_address_t address;
+
+} symbol_table_elem_t;
+
+struct thread_detail
+{
+       threadid_t threadid;
+       bool exists;
+       char * display_str;
+       char * thread_name_str;
+       char * extra_info_str;
+};
+
+struct rtos
+{
+       const struct rtos_type *type;
+
+
+       symbol_table_elem_t * symbols;
+       struct target *target;
+
+       threadid_t current_thread;
+       struct thread_detail* thread_details;
+       int thread_count;
+
+       void * rtos_specific_params;
+
+};
+
+
+
+struct rtos_type
+{
+       char * name;
+       int (*detect_rtos)                 ( struct target* target );
+       int (*create)                      ( struct target* target );
+       int (*update_threads)              ( struct rtos*   rtos );
+       int (*get_thread_reg_list)         ( struct rtos *rtos, long long thread_id, char ** hex_reg_list );
+       int (*get_symbol_list_to_lookup)   (symbol_table_elem_t * symbol_list[] );
+};
+
+
+struct stack_register_offset
+{
+       signed short   offset;       // offset in bytes from stack head, or -1 to indicate register is not stacked, or -2 to indicate this is the stack pointer register
+       unsigned short width_bits;
+
+};
+
+struct rtos_register_stacking
+{
+       unsigned char                       stack_registers_size;
+       signed   char                       stack_growth_direction;
+       unsigned char                       num_output_registers;
+       const struct stack_register_offset* register_offsets;
+};
+
+#define GDB_THREAD_PACKET_NOT_CONSUMED (-40)
+
+int rtos_create(Jim_GetOptInfo *goi, struct target * target);
+int rtos_generic_stack_read( struct target * target, const struct rtos_register_stacking* stacking, long long stack_ptr, char ** hex_reg_list );
+int rtos_try_next( struct target * target );
+int gdb_thread_packet(struct connection *connection, struct target *target, char *packet, int packet_size);
+int rtos_get_gdb_reg_list(struct connection *connection, struct target *target, struct reg **reg_list[], int *reg_list_size);
+int rtos_update_threads( struct target *target );
+
+#endif // RTOS_H
diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c
new file mode 100644 (file)
index 0000000..e0ae065
--- /dev/null
@@ -0,0 +1,65 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rtos.h"
+
+static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets [] =
+{ { 0x20, 32 },       // r0
+  { 0x24, 32 },       // r1
+  { 0x28, 32 },       // r2
+  { 0x2c, 32 },       // r3
+  { 0x00, 32 },       // r4
+  { 0x04, 32 },       // r5
+  { 0x08, 32 },       // r6
+  { 0x0c, 32 },       // r7
+  { 0x10, 32 },       // r8
+  { 0x14, 32 },       // r9
+  { 0x18, 32 },       // r10
+  { 0x1c, 32 },       // r11
+  { 0x30, 32 },       // r12
+  { -2,   32 },       // sp
+  { 0x34, 32 },       // lr
+  { 0x38, 32 },       // pc
+  { -1,   96 },       // FPA1
+  { -1,   96 },       // FPA2
+  { -1,   96 },       // FPA3
+  { -1,   96 },       // FPA4
+  { -1,   96 },       // FPA5
+  { -1,   96 },       // FPA6
+  { -1,   96 },       // FPA7
+  { -1,   96 },       // FPA8
+  { -1,   32 },       // FPS
+  { 0x3c, 32 },       // xPSR
+};
+
+
+const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking =
+{
+          0x40,                                 // stack_registers_size
+          1,                                    // stack_growth_direction
+          26,                                   // num_output_registers
+          rtos_standard_Cortex_M3_stack_offsets // register_offsets
+};
+
+
diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h
new file mode 100644 (file)
index 0000000..1e8568c
--- /dev/null
@@ -0,0 +1,32 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_
+#define INCLUDED_RTOS_STANDARD_STACKINGS_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rtos.h"
+
+extern const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking;
+
+#endif //ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_
index 77142dfadec8acfd5c2ebf41560cd491ded3ca38..0b8085896615fa61aa5338f456d8987ab76933c8 100644 (file)
@@ -8,6 +8,9 @@
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -35,6 +38,7 @@
 #include "gdb_server.h"
 #include <target/image.h>
 #include <jtag/jtag.h>
 #include "gdb_server.h"
 #include <target/image.h>
 #include <jtag/jtag.h>
+#include "rtos/rtos.h"
 
 
 /**
 
 
 /**
@@ -479,7 +483,7 @@ static int gdb_put_packet_inner(struct connection *connection,
        return ERROR_OK;
 }
 
        return ERROR_OK;
 }
 
-static int gdb_put_packet(struct connection *connection, char *buffer, int len)
+int gdb_put_packet(struct connection *connection, char *buffer, int len)
 {
        struct gdb_connection *gdb_con = connection->priv;
        gdb_con->busy = 1;
 {
        struct gdb_connection *gdb_con = connection->priv;
        gdb_con->busy = 1;
@@ -767,6 +771,7 @@ static void gdb_frontend_halted(struct target *target, struct connection *connec
                snprintf(sig_reply, 4, "T%2.2x", signal_var);
                gdb_put_packet(connection, sig_reply, 3);
                gdb_connection->frontend_state = TARGET_HALTED;
                snprintf(sig_reply, 4, "T%2.2x", signal_var);
                gdb_put_packet(connection, sig_reply, 3);
                gdb_connection->frontend_state = TARGET_HALTED;
+               rtos_update_threads( target );
        }
 }
 
        }
 }
 
@@ -1034,6 +1039,12 @@ static int gdb_get_registers_packet(struct connection *connection,
        LOG_DEBUG("-");
 #endif
 
        LOG_DEBUG("-");
 #endif
 
+       if ( ( target->rtos != NULL ) &&
+                ( ERROR_FAIL != rtos_get_gdb_reg_list( connection, target, &reg_list, &reg_list_size) ) )
+       {
+               return ERROR_OK;
+       }
+
        if ((retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
        {
                return gdb_error(connection, retval);
        if ((retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
        {
                return gdb_error(connection, retval);
@@ -2187,16 +2198,23 @@ static int gdb_input_inner(struct connection *connection)
                        retval = ERROR_OK;
                        switch (packet[0])
                        {
                        retval = ERROR_OK;
                        switch (packet[0])
                        {
-                               case 'H':
-                                       /* Hct... -- set thread
-                                        * we don't have threads, send empty reply */
-                                       gdb_put_packet(connection, NULL, 0);
-                                       break;
+                           case 'T': // Is thread alive?
+                               gdb_thread_packet(connection, target, packet, packet_size);
+                               break;
+                           case 'H': // Set current thread ( 'c' for step and continue, 'g' for all other operations )
+                               gdb_thread_packet(connection, target, packet, packet_size);
+                               break;
                                case 'q':
                                case 'Q':
                                case 'q':
                                case 'Q':
-                                       retval = gdb_query_packet(connection,
-                                                       target, packet,
-                                                       packet_size);
+                                       retval = gdb_thread_packet(connection,
+                                                                                               target, packet,
+                                                                                               packet_size);
+                                       if ( retval == GDB_THREAD_PACKET_NOT_CONSUMED )
+                                       {
+                                               retval = gdb_query_packet(connection,
+                                                               target, packet,
+                                                               packet_size);
+                                       }
                                        break;
                                case 'g':
                                        retval = gdb_get_registers_packet(
                                        break;
                                case 'g':
                                        retval = gdb_get_registers_packet(
index d7a6ad0abd434f28c5a321da7ec92c48b9a3684e..cb3962ff971cca4b3a437ddbde47e0868efb3727 100644 (file)
@@ -8,6 +8,9 @@
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -39,6 +42,8 @@ struct gdb_service
 int gdb_target_add_all(struct target *target);
 int gdb_register_commands(struct command_context *command_context);
 
 int gdb_target_add_all(struct target *target);
 int gdb_register_commands(struct command_context *command_context);
 
+int gdb_put_packet(struct connection *connection, char *buffer, int len);
+
 #define ERROR_GDB_BUFFER_TOO_SMALL (-800)
 #define ERROR_GDB_TIMEOUT (-801)
 
 #define ERROR_GDB_BUFFER_TOO_SMALL (-800)
 #define ERROR_GDB_TIMEOUT (-801)
 
index 026ca13b9c41875b43bac347893d7b42b3b50bd3..abe1b43ae03e01f5d79a464f5281d2cf93b23545 100644 (file)
@@ -14,6 +14,9 @@
  *   Copyright (C) 2008 by Rick Altherr                                    *
  *   kc8apf@kc8apf.net>                                                    *
  *                                                                         *
  *   Copyright (C) 2008 by Rick Altherr                                    *
  *   kc8apf@kc8apf.net>                                                    *
  *                                                                         *
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -44,6 +47,7 @@
 #include "register.h"
 #include "trace.h"
 #include "image.h"
 #include "register.h"
 #include "trace.h"
 #include "image.h"
+#include "rtos/rtos.h"
 
 
 static int target_read_buffer_default(struct target *target, uint32_t address,
 
 
 static int target_read_buffer_default(struct target *target, uint32_t address,
@@ -3704,6 +3708,7 @@ enum target_cfg_param {
        TCFG_COREID,
        TCFG_CHAIN_POSITION,
        TCFG_DBGBASE,
        TCFG_COREID,
        TCFG_CHAIN_POSITION,
        TCFG_DBGBASE,
+       TCFG_RTOS,
 };
 
 static Jim_Nvp nvp_config_opts[] = {
 };
 
 static Jim_Nvp nvp_config_opts[] = {
@@ -3718,6 +3723,7 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-coreid",           .value = TCFG_COREID },
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
        { .name = "-dbgbase",          .value = TCFG_DBGBASE },
        { .name = "-coreid",           .value = TCFG_COREID },
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
        { .name = "-dbgbase",          .value = TCFG_DBGBASE },
+       { .name = "-rtos",             .value = TCFG_RTOS },
        { .name = NULL, .value = -1 }
 };
 
        { .name = NULL, .value = -1 }
 };
 
@@ -4024,6 +4030,18 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
                        /* loop for more */
                        break;
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
                        /* loop for more */
                        break;
+
+               case TCFG_RTOS:
+                       /* RTOS */
+                       {
+                               int result = rtos_create( goi, target );
+                               if ( result != JIM_OK )
+                               {
+                                       return result;
+                               }
+                       }
+                       /* loop for more */
+                       break;
                }
        } /* while (goi->argc) */
 
                }
        } /* while (goi->argc) */
 
@@ -4746,6 +4764,9 @@ static int target_create(Jim_GetOptInfo *goi)
 
        target->endianness = TARGET_ENDIAN_UNKNOWN;
 
 
        target->endianness = TARGET_ENDIAN_UNKNOWN;
 
+       target->rtos = NULL;
+       target->rtos_auto_detect = false;
+
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
index fd7de560e3e375c113b7144a8b0852a838b63ab4..5b67bf345daa2e3e5e28cee98599de8003ba87cb 100644 (file)
@@ -8,6 +8,9 @@
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -160,6 +163,9 @@ struct target
        uint32_t dbgbase;                                       /* Really a Cortex-A specific option, but there is no
                                                                                   system in place to support target specific options
                                                                                   currently. */
        uint32_t dbgbase;                                       /* Really a Cortex-A specific option, but there is no
                                                                                   system in place to support target specific options
                                                                                   currently. */
+       struct rtos *rtos;                                      /* Instance of Real Time Operating System support */
+       bool rtos_auto_detect;                          /* A flag that indicates that the RTOS has been specified as "auto" 
+                                            * and must be detected when symbols are offered */
 };
 
 /** Returns the instance-specific name of the specified target. */
 };
 
 /** Returns the instance-specific name of the specified target. */

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)