mirror of
https://github.com/linux-msm/openocd.git
synced 2026-02-25 13:15:07 -08:00
RTOS Thread awareness support wip
- 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.
This commit is contained in:
committed by
Øyvind Harboe
parent
f9feeacb7f
commit
b69119668e
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
481
src/rtos/FreeRTOS.c
Normal file
481
src/rtos/FreeRTOS.c
Normal file
@@ -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;
|
||||
}
|
||||
35
src/rtos/Makefile.am
Normal file
35
src/rtos/Makefile.am
Normal file
@@ -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
|
||||
536
src/rtos/ThreadX.c
Normal file
536
src/rtos/ThreadX.c
Normal file
File diff suppressed because it is too large
Load Diff
657
src/rtos/rtos.c
Normal file
657
src/rtos/rtos.c
Normal file
File diff suppressed because it is too large
Load Diff
106
src/rtos/rtos.h
Normal file
106
src/rtos/rtos.h
Normal file
@@ -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
|
||||
65
src/rtos/rtos_standard_stackings.c
Normal file
65
src/rtos/rtos_standard_stackings.c
Normal file
@@ -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
|
||||
};
|
||||
|
||||
|
||||
32
src/rtos/rtos_standard_stackings.h
Normal file
32
src/rtos/rtos_standard_stackings.h
Normal file
@@ -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_
|
||||
@@ -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, ®_list, ®_list_size) ) )
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
if ((retval = target_get_gdb_reg_list(target, ®_list, ®_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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user