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 a73354f..8315a18 100644 (file)
@@ -1170,6 +1170,7 @@ AC_OUTPUT(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
index 7744986..3d7b05f 100644 (file)
@@ -8,7 +8,8 @@ SUBDIRS = \
        svf \
        xsvf \
        pld \
-       server
+       server \
+       rtos
 
 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/rtos/librtos.la \
        $(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 77142df..0b80858 100644 (file)
@@ -8,6 +8,9 @@
  *   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     *
@@ -35,6 +38,7 @@
 #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;
 }
 
-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;
@@ -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;
+               rtos_update_threads( target );
        }
 }
 
@@ -1034,6 +1039,12 @@ static int gdb_get_registers_packet(struct connection *connection,
        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);
@@ -2187,16 +2198,23 @@ static int gdb_input_inner(struct connection *connection)
                        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':
-                                       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(
index d7a6ad0..cb3962f 100644 (file)
@@ -8,6 +8,9 @@
  *   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     *
@@ -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_put_packet(struct connection *connection, char *buffer, int len);
+
 #define ERROR_GDB_BUFFER_TOO_SMALL (-800)
 #define ERROR_GDB_TIMEOUT (-801)
 
index 026ca13..abe1b43 100644 (file)
@@ -14,6 +14,9 @@
  *   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     *
@@ -44,6 +47,7 @@
 #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,
@@ -3704,6 +3708,7 @@ enum target_cfg_param {
        TCFG_COREID,
        TCFG_CHAIN_POSITION,
        TCFG_DBGBASE,
+       TCFG_RTOS,
 };
 
 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 = "-rtos",             .value = TCFG_RTOS },
        { .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;
+
+               case TCFG_RTOS:
+                       /* RTOS */
+                       {
+                               int result = rtos_create( goi, target );
+                               if ( result != JIM_OK )
+                               {
+                                       return result;
+                               }
+                       }
+                       /* loop for more */
+                       break;
                }
        } /* while (goi->argc) */
 
@@ -4746,6 +4764,9 @@ static int target_create(Jim_GetOptInfo *goi)
 
        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);
index fd7de56..5b67bf3 100644 (file)
@@ -8,6 +8,9 @@
  *   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     *
@@ -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. */
+       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. */